Initial Commit
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# `@suaveplan/api-auth-bearer-static` — Static-token service auth
|
||||
|
||||
**Package**: `@suaveplan/api-auth-bearer-static`
|
||||
**Status**: PROPOSED
|
||||
**Type**: new-package
|
||||
**Stage**: 4 (Base adapters) — see umbrella `openspec/changes/api-plugin-foundation/`
|
||||
|
||||
## Why
|
||||
|
||||
Service-to-service callers (cron runners, sidecar daemons, internal admin tooling) often present a single static bearer token in lieu of a full JWT or OAuth flow. Per design doc §2.3, `api-auth-bearer-static` resolves these tokens against a fixed table: `token → Principal`. No provider, no DB lookup, no JWKS — just constant-time match.
|
||||
|
||||
Common in chained-resolver topologies: `api-auth-jwt` for users AND `api-auth-bearer-static` for service callers, first match wins. When paired with the host's admin API, this adapter SHOULD be gated by mutual-TLS (operator config) — the bearer token is necessary but not sufficient.
|
||||
|
||||
Stage 4 invariant: ships both direct and worker-proxy surfaces; both pass `runAuthSessionConformance` (§5.2a, §13.4).
|
||||
|
||||
## What changes
|
||||
|
||||
Net-new package depending on `@suaveplan/api-auth`, `@suaveplan/api-types`, `@suaveplan/api-worker-rpc`, `@suaveplan/crypto-utils` (constant-time equality), `@suaveplan/error`, `zod`.
|
||||
|
||||
- ADDED: `createBearerStaticResolver(opts)` — direct-surface factory.
|
||||
- ADDED: `createBearerStaticResolverWorkerProxy(port, opts)` — proxy-surface factory.
|
||||
- ADDED: `BearerStaticResolverOptions` — Zod schema with `tokens: Array<{ token: string; principal: Principal; mtlsRequired?: boolean }>`, `headerName?: string` (default `Authorization`), `prefix?: string` (default `Bearer`).
|
||||
- ADDED: `securitySchemeContribution()` — OpenAPI `securitySchemes` entry for HTTP Bearer with custom scheme name.
|
||||
- ADDED: `AUTH_BEARER_STATIC_*` error codes (`AUTH_BEARER_STATIC_NO_TOKEN`, `AUTH_BEARER_STATIC_UNKNOWN_TOKEN`, `AUTH_BEARER_STATIC_MTLS_REQUIRED`, `AUTH_BEARER_STATIC_INVALID_OPTIONS`).
|
||||
- ADDED: Optional mutual-TLS gate — when `mtlsRequired: true` for a token entry, the host MUST surface a verified client-cert subject; absence → reject. The host integration point is `request.tls?.peerCertificate`; this adapter checks for its presence and rejects otherwise.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Token rotation — operators reload host config to swap tokens; this adapter is intentionally static.
|
||||
- DB-backed token lookups — that's `api-auth-better-auth` or a future `api-auth-token-table` adapter.
|
||||
- Establishing the TLS context — the host's listener configures TLS; this adapter only reads what the listener attached.
|
||||
|
||||
## Source mapping
|
||||
|
||||
Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`.
|
||||
|
||||
| Requirement | Design doc section |
|
||||
|---|---|
|
||||
| Service-to-service static tokens | §2.3 (`api-auth-bearer-static` bullet) |
|
||||
| Optional mTLS gate | §2.3 (final paragraph) |
|
||||
| Worker-proxy variant | §5.2a |
|
||||
| Conformance both surfaces | §13.4 |
|
||||
|
||||
## Verification approach
|
||||
|
||||
- `src/factory/create-bearer-static-resolver.test.ts` — token match returns Principal; unknown token → null; missing token → null.
|
||||
- `src/factory/create-bearer-static-resolver.spec-conformance.test.ts` — `runAuthSessionConformance("bearer-static-direct", ...)`.
|
||||
- `src/proxy/create-bearer-static-resolver-worker-proxy.test.ts` — proxy unit tests.
|
||||
- `src/proxy/create-bearer-static-resolver-worker-proxy.spec-conformance.test.ts` — `runAuthSessionConformance("bearer-static-worker-proxy", ...)`.
|
||||
- `src/mtls/mtls-gate.test.ts` — `mtlsRequired: true` rejects when peerCertificate missing.
|
||||
- `src/constant-time/token-match.test.ts` — constant-time comparison invariant (no early exit).
|
||||
|
||||
## Migration impact
|
||||
|
||||
None — additive only.
|
||||
Reference in New Issue
Block a user