Skip to content

feat(auth): OIDC observability and setup docs - #10

Merged
andreszb merged 2 commits into
mainfrom
feat/oidc-observability-docs
Aug 24, 2026
Merged

feat(auth): OIDC observability and setup docs#10
andreszb merged 2 commits into
mainfrom
feat/oidc-observability-docs

Conversation

@andreszb

Copy link
Copy Markdown
Owner

Tracks #7. Stacked on #9 (feat/oidc-modes-logout), which stacks on #8, which stacks on #4 — none of the parent PRs have merged yet. Retarget to main once the chain merges.

Last of the 4-PR OIDC/SSO split — see the plan in #4's description. This one is pure observability and docs: no new behavior, no new pure functions, nothing to unit test.

What shipped:

  • Admin dashboard: new "OIDC / SSO" card in System Health, next to the existing Database/Version cards — shows configured/not-configured, the display name (or a generic "SSO" fallback), and which of the three mode flags (OIDC_ONLY, OIDC_AUTO_REDIRECT, OIDC_RP_LOGOUT) are active
  • admin.getSystemHealth now returns an oidc object with that same data
  • Startup log: app.startup.auth_providers lists every enabled sign-in provider (google, oidc) and, when OIDC is among them, its mode flags — logged once per boot, alongside the existing app.startup line
  • .env.example: documents all 9 OIDC vars introduced across PR1–3 (OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_NAME, OIDC_ALLOW_LINKING, OIDC_TRUST_EMAIL, OIDC_AUTO_PROVISION, OIDC_ONLY, OIDC_AUTO_REDIRECT, OIDC_RP_LOGOUT), previously deferred on purpose
  • docker/docker-compose.yml: same 9 vars wired through as environment passthroughs, matching the existing GOOGLE_CLIENT_* pattern
  • README.md: new "OIDC / SSO (optional)" config section (full var table, callback URL to register with the IdP, two-step rollout guidance), a Features bullet, and translated systemHealth.oidc* keys across all 9 locales

Gates: tsc, lint, lint:i18n, all 337 unit tests, and npm run build all clean. No new tests — nothing here is a pure function worth extracting; it's wiring existing getOidcConfig/getOidcModes into two more call sites plus static docs.

Not covered: live re-verification against Pocket ID — this PR doesn't touch sign-in/logout behavior, only what's displayed/logged/documented about it, so the live checks from #8/#9 still stand.

Adds an OIDC status card to the admin System Health section, a
startup log line listing enabled sign-in providers and OIDC mode
flags, and documents every OIDC_* env var introduced across the
three prior PRs (.env.example, docker-compose.yml, README).
- README/.env.example: register *two* URLs with the IdP, not one. RP-initiated
  logout is on by default and sends `post_logout_redirect_uri`, which most
  providers require pre-registered — and the docs already warn that Pocket ID
  matches literally rather than by wildcard. An operator following the old
  instructions registered only the callback URL, and their first sign-out
  dead-ended on the IdP's error page with the local session already cleared.
  `OIDC_AUTO_REDIRECT` silently changes that URI to `/login?password=1`, which
  the docs also never mentioned.

- Document that `OIDC_TRUST_EMAIL` and `OIDC_AUTO_PROVISION` now interact with
  the verification requirement on the provisioning path.

- instrumentation: log `app.startup.auth_providers` unconditionally, with an
  explicit `oidcConfigured`. It was suppressed when no provider resolved,
  which is exactly the case it exists to diagnose — an `OIDC_CLIENT_SECRET`
  missing on a public client left an operator with no line at all,
  indistinguishable from a deliberately password-only instance.

- unraid/sharetab.xml: add all 10 `OIDC_*` Config entries. The template
  enumerates every other optional integration, and Unraid is the stated
  target; without them a Community Applications user has no field to set and
  the compose defaults never reach that path.

- docker/entrypoint.sh: report OIDC in the startup banner, including an
  explicit INCOMPLETE state when only some of the three required vars are set.

- admin System Health: stop asserting "Not configured" when the query failed
  rather than returned — `data` is undefined in both cases, and a health
  dashboard reporting a definite wrong state is worse than reporting none.
  Also skip the modes line entirely when no mode is on, instead of rendering
  an empty paragraph and its margin as a stray gap.
@andreszb
andreszb force-pushed the feat/oidc-modes-logout branch from 943c392 to 4532b64 Compare August 24, 2026 20:08
@andreszb
andreszb force-pushed the feat/oidc-observability-docs branch from 0f45b4f to d4c7e42 Compare August 24, 2026 20:08
@andreszb
andreszb changed the base branch from feat/oidc-modes-logout to main August 24, 2026 20:25
@andreszb
andreszb merged commit 869d006 into main Aug 24, 2026
1 check failed
andreszb added a commit that referenced this pull request Aug 24, 2026
PR #10 added a required `oidc` object to `admin.getSystemHealth` and had the
admin page render it, but never updated the e2e mock. `admin/page.tsx:144`
reads `data.oidc.configured` guarding only `data === undefined`, so against
the fixture — which had no `oidc` key — the admin page threw and took down
all 13 tests in admin-meridian.spec.ts.

Fixes the fixture rather than making the UI defensive: the real router always
returns `oidc`, so `data.oidc?.configured` would paper over a contract the
server actually guarantees. All presets route through `setSystemHealth()`,
so one default covers every case.

Not caught before merge because the audit step failed first and skipped e2e.
@andreszb
andreszb deleted the feat/oidc-observability-docs branch August 24, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant