docs(readme): self-hoster setup + env-var reference; CLAUDE.md convention to keep it current (#114) #118

Merged
james merged 1 commit from 114-readme-config into main 2026-06-18 15:30:48 +00:00
Owner

Closes #114.

What lands

README.md

  • New Configuration section. Tables grouped by concern (Data, Authentication, OIDC providers, Operations), one row per env var with default, allowed values, when the default holds.
  • New Self-hosted deployment section: minimal podman run, a Postgres + OIDC + reverse-proxy variant, and a compose.yaml. Volume mount for /app/data is called out.
  • Setup → renamed Local development with an explicit .env.local override pattern and the third LEFTHOOK_EXCLUDE=conventional line added (was missing).
  • CI-runner-only / test-only env vars (BASE_REF, FORGEJO_*, GITHUB_*, PR_NUMBER, TEST_POSTGRES_URL, NEXT_RUNTIME) are deliberately excluded with a callout — they belong with the workflow or test that uses them.

CLAUDE.md

  • New bullet under Conventions making README the env-var source of truth: any PR adding / removing / renaming a self-hoster-facing env var must update the README's Configuration table in the same commit. ADRs and docs/* may link but must not restate defaults.
  • Stack defaults bullets for Auth (OIDC) and Blob storage demoted to link into README#configuration instead of restating CAROL_STORAGE_ROOT / OIDC_<NAME>_* values. The architectural claim stays; the env-var values move.

Acceptance criteria

  • README.md has a Configuration section listing every self-hoster-facing env var with default + brief description, grouped by concern.
  • README.md has a self-hosted deployment snippet that names the data-directory volume and shows the minimum env vars to start the container.
  • CLAUDE.md adds the convention bullet that ties future env-var changes to README updates.
  • The audit grep shows no name that isn't either in the README table or explicitly marked as internal:
    $ grep -rohE 'process\.env\.[A-Z_]+' lib/ app/ db/ proxy.ts instrumentation.ts | sort -u
    process.env.APP_URL          ✓ README → Authentication
    process.env.CAROL_STORAGE_ROOT ✓ README → Data
    process.env.DATABASE_URL     ✓ README → Data
    process.env.NEXT_RUNTIME     ✓ README → CI-runner-only callout
    process.env.NODE_ENV         ✓ README → Operations
    process.env.REGISTRATION_POLICY ✓ README → Authentication
    
    Plus the dynamic OIDC_<NAME>_* set, covered in the OIDC providers table.
  • No env-var values duplicated between README.md and CLAUDE.md / docs/*grep -nE 'CAROL_STORAGE_ROOT|OIDC_<NAME>_|REGISTRATION_POLICY|DATABASE_URL|APP_URL' CLAUDE.md returns empty after this PR.

Composes with

  • #21 / ADR-0018 — CAROL_STORAGE_ROOT got its first user there; this PR puts it where self-hosters can find it.
  • #115/#117 — OIDC_<NAME>_REQUIRE_EMAIL_VERIFIED (just merged) is captured in the OIDC table.
  • #103APP_URL for reverse-proxy deployments is now visible from the README rather than the bug-fix description.
  • ADR-0017 / docs/oidc-self-hoster-guide.md — the README summary points at the deep-dive guide; the guide stays as the recipe book.

Out of scope (called out in #114)

  • A CI check that enforces the convention by grepping process.env.* and failing the build on a new name missing from the README table. Worth a follow-up if drift turns out to be real; the convention bullet is the soft enforcement first.
  • A .env.example file. Useful but follow-up — README table is the source of truth first.
  • Reformatting docs/ci.md / docs/oidc-self-hoster-guide.md. Those stay as references; the README now links into them.
Closes #114. ## What lands **`README.md`** - New **Configuration** section. Tables grouped by concern (Data, Authentication, OIDC providers, Operations), one row per env var with default, allowed values, when the default holds. - New **Self-hosted deployment** section: minimal `podman run`, a Postgres + OIDC + reverse-proxy variant, and a `compose.yaml`. Volume mount for `/app/data` is called out. - Setup → renamed **Local development** with an explicit `.env.local` override pattern and the third `LEFTHOOK_EXCLUDE=conventional` line added (was missing). - CI-runner-only / test-only env vars (`BASE_REF`, `FORGEJO_*`, `GITHUB_*`, `PR_NUMBER`, `TEST_POSTGRES_URL`, `NEXT_RUNTIME`) are deliberately excluded with a callout — they belong with the workflow or test that uses them. **`CLAUDE.md`** - New bullet under **Conventions** making README the env-var source of truth: any PR adding / removing / renaming a self-hoster-facing env var must update the README's Configuration table in the same commit. ADRs and `docs/*` may link but must not restate defaults. - *Stack defaults* bullets for **Auth (OIDC)** and **Blob storage** demoted to *link* into `README#configuration` instead of restating `CAROL_STORAGE_ROOT` / `OIDC_<NAME>_*` values. The architectural claim stays; the env-var values move. ## Acceptance criteria - [x] `README.md` has a *Configuration* section listing every self-hoster-facing env var with default + brief description, grouped by concern. - [x] `README.md` has a self-hosted deployment snippet that names the data-directory volume and shows the minimum env vars to start the container. - [x] `CLAUDE.md` adds the convention bullet that ties future env-var changes to README updates. - [x] The audit grep shows no name that isn't either in the README table or explicitly marked as internal: ``` $ grep -rohE 'process\.env\.[A-Z_]+' lib/ app/ db/ proxy.ts instrumentation.ts | sort -u process.env.APP_URL ✓ README → Authentication process.env.CAROL_STORAGE_ROOT ✓ README → Data process.env.DATABASE_URL ✓ README → Data process.env.NEXT_RUNTIME ✓ README → CI-runner-only callout process.env.NODE_ENV ✓ README → Operations process.env.REGISTRATION_POLICY ✓ README → Authentication ``` Plus the dynamic `OIDC_<NAME>_*` set, covered in the OIDC providers table. - [x] No env-var values duplicated between `README.md` and `CLAUDE.md` / `docs/*` — `grep -nE 'CAROL_STORAGE_ROOT|OIDC_<NAME>_|REGISTRATION_POLICY|DATABASE_URL|APP_URL' CLAUDE.md` returns empty after this PR. ## Composes with - #21 / ADR-0018 — `CAROL_STORAGE_ROOT` got its first user there; this PR puts it where self-hosters can find it. - #115/#117 — `OIDC_<NAME>_REQUIRE_EMAIL_VERIFIED` (just merged) is captured in the OIDC table. - #103 — `APP_URL` for reverse-proxy deployments is now visible from the README rather than the bug-fix description. - ADR-0017 / `docs/oidc-self-hoster-guide.md` — the README summary points at the deep-dive guide; the guide stays as the recipe book. ## Out of scope (called out in #114) - A CI check that enforces the convention by grepping `process.env.*` and failing the build on a new name missing from the README table. Worth a follow-up if drift turns out to be real; the convention bullet is the soft enforcement first. - A `.env.example` file. Useful but follow-up — README table is the source of truth first. - Reformatting `docs/ci.md` / `docs/oidc-self-hoster-guide.md`. Those stay as references; the README now links into them.
docs(readme): self-hoster setup + env-var reference; CLAUDE.md convention to keep it current (#114)
All checks were successful
Commits / Conventional Commits (pull_request) Successful in 5s
PR / OSV-Scanner (pull_request) Successful in 36s
PR / npm audit (pull_request) Successful in 51s
PR / Lint (pull_request) Successful in 56s
PR / Static analysis (pull_request) Successful in 56s
PR / Typecheck (pull_request) Successful in 1m0s
PR / Trivy (image) (pull_request) Successful in 1m0s
Secrets / gitleaks (pull_request) Successful in 25s
PR / Test (sqlite) (pull_request) Successful in 1m16s
PR / Coverage (soft) (pull_request) Successful in 1m12s
PR / Test (postgres) (pull_request) Successful in 1m19s
PR / Build (pull_request) Successful in 1m24s
e074562031
The self-hoster-facing surface was scattered across CLAUDE.md, the
Dockerfile, docs/ci.md, docs/oidc-self-hoster-guide.md, and the ADRs.
None of the env vars (DATABASE_URL, CAROL_STORAGE_ROOT, APP_URL,
REGISTRATION_POLICY, OIDC_<NAME>_*, PORT, HOSTNAME) appeared in the
README — anyone landing on the repo page had to grep source to find
them.

README.md
  - New "Configuration" section. Tables grouped by concern (Data,
    Authentication, OIDC providers, Operations), one row per env var
    with default + notes + when the default holds. The OIDC table
    summarises the pattern; the full walkthrough stays in
    docs/oidc-self-hoster-guide.md.
  - New "Self-hosted deployment" section: minimal podman run, a
    Postgres + OIDC + reverse-proxy variant, and a compose.yaml.
    Volume mount for /app/data is called out.
  - "Setup" renamed to "Local development" with an explicit
    .env.local override pattern.
  - CI-runner-only / test-only env vars (BASE_REF, FORGEJO_*,
    GITHUB_*, PR_NUMBER, TEST_POSTGRES_URL, NEXT_RUNTIME) are
    deliberately excluded with a callout.

CLAUDE.md
  - New convention bullet under "Conventions" making README the
    env-var source of truth. ADRs and docs/* may link but must not
    restate defaults.
  - "Stack defaults" lines for Auth (OIDC) and Blob storage demoted
    to link into README#configuration instead of restating
    CAROL_STORAGE_ROOT / OIDC_<NAME>_* values.

Audit (per ticket AC): grep -rohE 'process\.env\.[A-Z_]+' over lib/
app/ db/ proxy.ts instrumentation.ts returns APP_URL,
CAROL_STORAGE_ROOT, DATABASE_URL, NEXT_RUNTIME, NODE_ENV,
REGISTRATION_POLICY — all six covered (NEXT_RUNTIME explicitly
called out as internal). The dynamic OIDC_<NAME>_* set is covered
by the OIDC table.

📊 Test coverage

Patch coverage: no testable lines changed.

Overall (app/, lib/, db/, excluding UI per ADR-0019):

Metric Value Soft target
Lines 84.0% ≥ 50%
Branches 82.6% ≥ 75%
Functions 90.8% informational

Soft thresholds per ADR-0019. Coverage is informational and does not block merge.

<!-- coverage-comment --> ## 📊 Test coverage **Patch coverage:** no testable lines changed. **Overall** (`app/`, `lib/`, `db/`, excluding UI per ADR-0019): | Metric | Value | Soft target | |---|---|---| | Lines | 84.0% ✅ | ≥ 50% | | Branches | 82.6% ✅ | ≥ 75% | | Functions | 90.8% | informational | Soft thresholds per [ADR-0019](docs/adr/0019-coverage-soft-targets.md). Coverage is informational and does not block merge.
james merged commit 276ee6a5cb into main 2026-06-18 15:30:48 +00:00
james deleted branch 114-readme-config 2026-06-18 15:30:49 +00:00
Sign in to join this conversation.
No description provided.