feat(authn): provider-agnostic Security AuthN backend (/api/v1/security) - #253
Conversation
Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
…s, TOTP, migration [skip ci] Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
… [skip ci] Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
…d vars [skip ci] Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
…pt @types/react) [skip ci] Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
| const token = jwt.sign({ userId: user.id, sessionId }, jwtSecret(), { | ||
| expiresIn: '24h', | ||
| }) |
| if (existing) throw new ConflictError() | ||
|
|
||
| const id = uuidv4() | ||
| const passwordHash = await bcrypt.hash(input.password, 10) |
| expect(session.token).toBeTruthy() | ||
| expect(session.user.id).toBe('u1') | ||
| expect(db.__tables.sessions.length).toBe(1) | ||
| const decoded = jwt.verify(session.token, 'test-secret') as any |
Automated code review (gate-code-review)Reviewing for runtime-correctness bugs only.
Note: the in-memory-map issue is the highest-impact and will manifest in any multi-replica deploy (the chart in this repo runs the backend with replicas). Report-only — this check never blocks merge. |
CI fix pushed — branch
|
#253 set the src tsconfig `types: [node]` (to expose URL/fetch globals), which tests/tsconfig.json inherits — dropping @types/jest so the security jest suites lost jest/describe/expect. Override types to [node, jest] in the TEST tsconfig only, leaving the src build node-only. Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7
Automated code review (gate-code-review)Reviewing the diff for runtime-correctness bugs only.
Report-only — this check never blocks merge. |
* fix(authn): route Authentik native paths under app host — restore OIDC (prod outage) #247's reverse-proxy stripped /api/auth/idp and relied on X-Forwarded-Prefix, but Authentik IGNORES it — so discovery advertised app.fuzefront.com/application/o/authorize/ (no prefix), an unrouted path → the browser authorize redirect 404'd → prod login broke. Fix: route Authentik's native root paths (/application,/if,/source,/flows,/ws,/-, /outpost.goauthentik.io,/static/dist,/static/authentik) straight to authentik-server under app.fuzefront.com (no strip); issuer -> https://app.fuzefront.com/application/o/fuzefront/. Boundary intact: browser stays on app.fuzefront.com, never sees the IdP host. Chart-only — deploys via Argo, no image build. helm template renders clean. Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7 * ci(release): add workflow_dispatch — enable manual image builds Auto-merged PRs push to master under GITHUB_TOKEN, which GitHub does not let trigger push-workflows — so release.yml never ran after #247/#253/#256 and the security-service/frontend images never built. workflow_dispatch gives a reliable manual build+GitOps-bump path (durable fix: switch auto-merge to a PAT — needs a RELEASE_PAT secret, tracked separately). Co-Authored-By: Claude claude-opus-4-8 <noreply@anthropic.com> Claude-Session-Id: cf830721-b1ef-4fe0-a024-035ad280dcf7 --------- Co-authored-by: fuzeone-bot[bot] <fuzeone-bot[bot]@users.noreply.github.com> Co-authored-by: Claude claude-opus-4-8 <noreply@anthropic.com>
AuthN backend slice — provider-agnostic Security API
Implements the AuthN surface under `/api/v1/security` against the frozen contract (PR #243: `packages/security/openapi.yaml` + `@fuzefront/security-client`), purely through the neutral `IdentityProvider` interface (env-driven factory). Authentik is named only inside the concrete provider.
Included
Typecheck fixes from prior WIP
Scope
AuthN backend only. AuthZ (`/authz/`, `/tenants/`) is a separate later stream. UI, independent acceptance tests, and deploy wiring are NOT in this PR.
🤖 Generated with Claude Code