Fix #371: OIDC anonymous read + navbar identity #375

Merged
crueber merged 1 commit from fix/issue-371 into main 2026-09-12 13:43:05 +00:00
Owner

Fixes #371 (anonymous read in OIDC mode + navbar Login/identity dropdown).

A. Validation flip (oidc + anonymous_read=true allowed)

  • internal/config/validate.go: removed the blanket anonymous_read must be false in oidc mode refusal. true = default recommendation (visitors browse public repos per #345 visibility semantics, navbar offers Login); false = everything-requires-login hard-lock. Allowlist + oauth pair + #344 browser-login trio + secret-length rules unchanged.
  • web/src/lib/setup.js: setup copy rewritten (field note + removed client mirror of the ban); /api/v1/setup/test agrees via config.Validate.
  • Docs amended in the same change (law 12): 11_config_cli.md §5 rule 2 + key table + Decisions; 06_server_http.md §14 (notes the #345 interaction + pins the /_auth/logout clear-cookie + sanitized-next 302 contract — no code change, it already exists); 07_api.md §8 + §14.

B. Navbar identity surface

  • GET /api/v1/me gains admin; discovery auth block gains mode (none|token|oidc). Both ride already-fetched payloads (shared me key, one AuthOpen discovery GET per app load) — zero new hot-path trips. /_auth/me untouched (edge contract).
  • web/src/lib/identity.js (new, pure): navModel matrix — signed-out + browser_login → Login (/_auth/login?next=<current>); signed-in (non-anon, mode != none) → identity menu (profile /{username}, keys, invitations, setup iff admin, logout → /_auth/logout?next=/); none mode → today's nav, no Login, no menu; login hidden when the flow is disabled.
  • web/src/components/IdentityMenu.jsx (new): avatar-or-username button (optional avatarUrl prop stages #349), #255/#311 popover contract (outside-click, Esc + focus return, arrows, menu/menuitem roles), logout as plain anchor, username truncates for 390px.
  • App.jsx: keys/invitations/setup leave the primary nav for signed-in users (setup stays in nav in none mode); identity control left of the tray.

Tests

  • Go: TestValidateOIDC (anon true+false pass), new TestValidateOIDCAnonTrioMatrix (oidc x anon x trio), discovery mode assertions + none-mode case, TestMe admin assertions. -race green (config/api/server), cover 95.7%/95.2%.
  • JS: new identity-nav.test.js (render matrix + App wiring + popover source pins); setup-form/setup-oidc-trio updated. node 743/745 (2 fails are the live-server smoke tests hitting the foreign :8080 instance, which 401s /; against a scratch server on :18080 all 3 smoke subtests pass). vite + esbuild green.
  • No new deps (Go or npm).
Fixes #371 (anonymous read in OIDC mode + navbar Login/identity dropdown). ## A. Validation flip (oidc + anonymous_read=true allowed) - `internal/config/validate.go`: removed the blanket `anonymous_read must be false in oidc mode` refusal. true = default recommendation (visitors browse public repos per #345 visibility semantics, navbar offers Login); false = everything-requires-login hard-lock. Allowlist + oauth pair + #344 browser-login trio + secret-length rules unchanged. - `web/src/lib/setup.js`: setup copy rewritten (field note + removed client mirror of the ban); `/api/v1/setup/test` agrees via config.Validate. - Docs amended in the same change (law 12): 11_config_cli.md §5 rule 2 + key table + Decisions; 06_server_http.md §14 (notes the #345 interaction + pins the `/_auth/logout` clear-cookie + sanitized-next 302 contract — no code change, it already exists); 07_api.md §8 + §14. ## B. Navbar identity surface - `GET /api/v1/me` gains `admin`; discovery auth block gains `mode` (none|token|oidc). Both ride already-fetched payloads (shared `me` key, one AuthOpen discovery GET per app load) — zero new hot-path trips. `/_auth/me` untouched (edge contract). - `web/src/lib/identity.js` (new, pure): navModel matrix — signed-out + browser_login → Login (`/_auth/login?next=<current>`); signed-in (non-anon, mode != none) → identity menu (profile /{username}, keys, invitations, setup iff admin, logout → `/_auth/logout?next=/`); none mode → today's nav, no Login, no menu; login hidden when the flow is disabled. - `web/src/components/IdentityMenu.jsx` (new): avatar-or-username button (optional avatarUrl prop stages #349), #255/#311 popover contract (outside-click, Esc + focus return, arrows, menu/menuitem roles), logout as plain anchor, username truncates for 390px. - `App.jsx`: keys/invitations/setup leave the primary nav for signed-in users (setup stays in nav in none mode); identity control left of the tray. ## Tests - Go: TestValidateOIDC (anon true+false pass), new TestValidateOIDCAnonTrioMatrix (oidc x anon x trio), discovery mode assertions + none-mode case, TestMe admin assertions. -race green (config/api/server), cover 95.7%/95.2%. - JS: new identity-nav.test.js (render matrix + App wiring + popover source pins); setup-form/setup-oidc-trio updated. node 743/745 (2 fails are the live-server smoke tests hitting the foreign :8080 instance, which 401s /; against a scratch server on :18080 all 3 smoke subtests pass). vite + esbuild green. - No new deps (Go or npm).
Sign in to join this conversation.
No description provided.