Files
suaveplan/openspec/archive/2026-05-26-api-auth-static-principal/proposal.md
2026-05-27 23:29:53 +01:00

53 lines
2.9 KiB
Markdown

# `@suaveplan/api-auth-static-principal` — Fixed-Principal session resolver for tests
**Package**: `@suaveplan/api-auth-static-principal`
**Status**: PROPOSED
**Type**: new-package
**Stage**: 5 (Testing kit + conformance suites) — see umbrella `openspec/changes/api-plugin-foundation/`
## Why
Per design doc §13.2, the testing kit needs an auth adapter that supplies a fixed `Principal` without any token decoding. The §13.2 example uses it directly:
```ts
adapters: {
"auth.session": { kind: "static-principal", principal: { id: "u1", scopes: ["billing:write"], tenantId: "acme" } },
}
```
Tests exercise the whole pipeline — RBAC gate, tenant resolver chain reading `principal.tenantId`, tenant-scoped DB — with a deterministic principal carried verbatim in config. No mocks, no token signing, no JWKS setup.
## What changes
Net-new package depending on `@suaveplan/api-auth` (contract + `./testing` conformance), `@suaveplan/api-types`, `@suaveplan/error`, `zod`.
- ADDED: `createStaticPrincipalResolver(opts)` — factory returning an `AuthAdapter` whose `resolveSession()` always returns `opts.principal` (a single fixed `Principal`). Optional `nullForPaths?: string[]` makes the resolver return `null` for matching request paths (test public-route behaviour without rewiring the whole adapter chain).
- ADDED: `StaticPrincipalResolverOptions` — Zod schema validating the `Principal` shape (`id`, `scopes`, `tenantId?`, `claims?`) and the optional `nullForPaths` glob list.
- ADDED: `securitySchemeContribution()` — returns an empty `securitySchemes` block (no auth flows to document for test use).
- ADDED: `AUTH_STATIC_PRINCIPAL_*` error codes (`AUTH_STATIC_PRINCIPAL_INVALID_OPTIONS`).
- ADDED: Registered in `@suaveplan/api-host/testing`'s adapter table as the `{ kind: "static-principal", principal: ... }` shorthand.
## Out of scope
- Multiple Principals selected by token / header — for that, write a custom resolver or compose two `static-principal` resolvers behind a chain.
- Worker-proxy surface — Stage 5 in-memory adapters are direct-only (cf. `api-router-in-memory`).
## Source mapping
Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`.
| Requirement | Design doc section |
|---|---|
| Fixed Principal config in test host | §13.2 |
| Registered in `api-host/testing` adapter table | §15 Stage 5 |
## Verification approach
- `src/factory/create-static-principal-resolver.test.ts` — resolves to the configured Principal; null for matching path patterns; deep equality (not reference equality) on the returned Principal.
- `src/factory/create-static-principal-resolver.spec-conformance.test.ts` — `runAuthSessionConformance("static-principal-direct", ...)`.
- `tests/integration/integration.test.ts` — booted by `createTestHost`'s default adapter table.
## Migration impact
None — additive only.