4.4 KiB
@suaveplan/api-auth — abstract session-resolver contract
Package: @suaveplan/api-auth
Status: PROPOSED
Type: new-package
Stage: 1 (Contracts) — see umbrella openspec/changes/api-plugin-foundation/
Why
Conflating session resolution and account lifecycle is what makes most plugin systems painful to integrate with third-party auth (design §2.3). api-auth is the session-resolver half: Request → Principal | null, used on EVERY request, called at step 3 of the per-request pipeline (§6). Concrete adapters (api-auth-jwt, api-auth-anonymous, api-auth-bearer-static, api-auth-better-auth, api-auth-rolled) plug behind this contract. Multiple resolvers can be chained — host config takes an ordered chain, first match wins (e.g. JWT for users + bearer-static for service callers).
The contract also covers SecuritySchemeContribution — every resolver declares what OpenAPI securitySchemes entry it contributes (api-openapi reads these — design §7 step 3).
What changes
Net-new package. Contract types + the chain runner + the conformance harness.
- ADDED:
./resolver— abstractSessionResolver:resolve(req: Request): Promise<Principal | null>;dispose(): Promise<void>. - ADDED:
./chain—SessionResolverChain: ordered list of resolvers; runs each in order, first non-null wins; returnsnullif all return null. - ADDED:
./security-scheme—SecuritySchemeContribution:{ name: string, scheme: OpenApiSecurityScheme }; every resolver MUST contribute one soapi-openapican emit the rightsecuritySchemesblock. - ADDED:
./csrf-policy—CsrfPolicy:requiresCsrf(scheme): boolean; cookie-based schemes default ON (per §6), JWT/Bearer default OFF. - ADDED:
./session-adapter— compositeAuthAdapterinterface:{ resolver, securityScheme, csrf }; what concrete adapters export. - ADDED:
./error-codes— frozenAUTH_CODES:RESOLVER_THREW,CHAIN_EMPTY,PRINCIPAL_INVALID_SHAPE,SECURITY_SCHEME_MISSING. - ADDED:
./capability-id— adds"auth.session"to theCapabilityIdunion via type-level augmentation. - ADDED:
./testing—runAuthSessionConformance(factory)reusable harness.
CapabilityId additions
This package contributes "auth.session" to the CapabilityId union. (The provider-side "auth.provider" is contributed by api-auth-provider — they're intentionally separate capabilities so a plugin can require session resolution without forcing the host to ship account-lifecycle routes.)
Out of scope
- The
Principaltype itself — that's in@suaveplan/api-types. - Account lifecycle (login/register/oauth) — that's
api-auth-provider. - Concrete adapters (
api-auth-jwt,api-auth-anonymous,api-auth-bearer-static,api-auth-better-auth,api-auth-rolled) — Stages 4/6/8.
Source mapping
Genesis-original. Source of design intent: docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md.
| Requirement | Design doc section |
|---|---|
| Session-resolver shape | §2.3 (top half) |
| Chained resolvers (first match wins) | §2.3 ("ordered chain, first match wins") |
SecuritySchemeContribution for OpenAPI |
§7 step 3 |
| CSRF default ON for cookie auth | §6 ("Cookie-based auth adapters trigger CSRF verification") |
| 401 only if non-public AND null | §6 step 3 |
Requirements with no source line
| Requirement | Justification |
|---|---|
runAuthSessionConformance harness |
Stage-5 deliverable (§13.4). |
Verification approach
src/resolver/resolver.spec-conformance.test.ts—SessionResolvershape;disposelifecycle.src/chain/chain.test.ts— ordering: A returns null → B runs; A returns Principal → B skipped. Empty chain →AUTH.CHAIN_EMPTY.src/chain/chain.test.ts— A throws →AUTH.RESOLVER_THREWsurfaces; chain does NOT continue to B (fail closed).src/security-scheme/security-scheme.test.ts— resolver MUST contribute a scheme; missing →AUTH.SECURITY_SCHEME_MISSING.src/csrf-policy/csrf-policy.test.ts— cookie scheme default ON; JWT/Bearer default OFF.src/capability-id/capability-id.spec-conformance.test.ts—"auth.session"is inCapabilityId.tests/dep-graph.test.ts— deps:@suaveplan/api-types,@suaveplan/error,@suaveplan/types,zod.
Migration impact
None — additive only.
Impact
Affected dependents
- (none) — [x] no action needed (reason: net-new; concrete adapters land Stages 4/6/8)