Pin the BFF authentication mechanics: OAuth 2.0 Authorization Code Flow
with PKCE, executed server-side via @azure/msal-node's
ConfidentialClientApplication. Tokens are held in the BFF session and
never reach the browser; the SPA only ever sees the opaque
__Host-portal_session cookie.
Token validation enforces the tenant allowlist from ADR-0008 (iss check)
and maps the audience claim to our Audience enum at the validation step.
Refresh-token rotation is enabled via MSAL acquireTokenSilent. Cookies
use the __Host- prefix (forces Secure/Path=/, no Domain) with
HttpOnly/SameSite=Lax. CSRF uses the double-submit pattern with a
matching X-CSRF-Token header on every state-changing request, enforced
by a NestJS interceptor and injected client-side by an Angular HTTP
interceptor. Logout is RP-initiated against Entra's end_session_endpoint.
Routes are pinned: GET /auth/login, GET /auth/callback, POST
/auth/logout, GET /auth/me. AuthGuard is registered globally - public
routes must be explicitly opted in.
Local dev runs over HTTPS via mkcert to keep cookie behaviour identical
to prod. All Entra-specific values come from environment variables; the
BFF refuses to start without them.
decisions/README.md index updated. CLAUDE.md gains an explicit
'Authentication flow' line pointing to ADR-0009.
Capture the v1 identity model: Microsoft Entra ID, multi-tenant app with
B2B guest invitation for partner-org employees, workforce-only
authentication in v1. Code and data are architected for dual audience
from day one (Audience enum, audience claim in sessions, audience column
+ RLS policies on shared tables, claims-based authz) so that adding Entra
External ID for customers later is a switch-flip rather than a refactor.
The dev environment uses a Microsoft 365 Developer Program tenant (free,
renewable) to unblock work while the prod tenant is being provisioned by
the org IT contact. Production requires Entra ID P1 licensing - flagged
here so it can be planned, not surprised.
decisions/README.md index updated. CLAUDE.md 'Identity' line now points
to ADR-0008.
- decisions/0007-pre-commit-hooks-and-conventional-commits.md formalizes
Husky + lint-staged + commitlint with Conventional Commits as the local
quality-gate baseline.
- decisions/README.md index updated.
- docs/setup/03 section 8 rewritten to reference the ADR and document the
full hook setup (pre-commit, commit-msg, commitlint config).
- docs/setup/03 future-work table 'ADR(s)' column removed; future ADR
numbers are now assigned at the moment each ADR is written, not
pre-reserved.
- CLAUDE.md aligned: pre-allocated phase-2 ADR numbers replaced by phase
references; a pointer to ADR-0007 added under 'Local quality gates'.
Set up the foundation for the adastra-portal project:
- CLAUDE.md captures durable project rules (quality bar, security/perf/a11y
as first-class, language, commit conventions, ADR proactivity).
- docs/ and decisions/ scaffolding with maintained indexes (docs/README.md
and decisions/README.md), MADR 4.0.0 template, and tag vocabulary.
- Phase-1 ADRs (0001-0006) lock structural choices: ADR usage, Nx monorepo
with the apps preset, naming convention (adastra-portal / portal-shell /
portal-bff), Angular CSR/zoneless/Signals/Vitest, NestJS over Express,
PostgreSQL with Prisma.
- docs/setup/ guides translated to English.
- .gitignore covers Node/Nx artifacts and the personal notes/ scratchpad.
The Nx workspace itself is not yet bootstrapped; that step is gated on a
revised setup guide aligned with the ADRs.