Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# `@suaveplan/api-auth-provider` — abstract account-lifecycle contract
**Package**: `@suaveplan/api-auth-provider`
**Status**: PROPOSED
**Type**: new-package
**Stage**: 1 (Contracts) — see umbrella `openspec/changes/api-plugin-foundation/`
## Why
Account lifecycle (register, login, logout, refresh, oauth/*, verify-email, ...) is the second half of the auth split (design §2.3). It is OPTIONAL — sites using hosted IdPs (Clerk, Auth0, Cognito) don't need a provider; they only need a session resolver. Sites running their own auth pick one provider: Better-Auth (`api-auth-better-auth`, Stage 6) or the rolled-our-own reference (`api-auth-rolled`, Stage 8). This package owns the abstract contract: the route surface a provider owns, the path-ownership declaration (default `/auth/*`, configurable), and the collision detection that runs at install time so plugin routes can't accidentally squat on auth paths.
Per design §2.3: "Each provider adapter declares which paths it owns (default `/auth/*`, configurable). Host reserves the prefix and refuses plugin routes that collide."
## What changes
Net-new package. Contract types + the route-collision detector + the conformance harness.
- ADDED: `./provider` — abstract `AuthProviderAdapter`: `pathPrefix: string` (default `/auth`), `routes(router, ctx)` callback registering provider routes, `lifecycle: { install, start, stop, uninstall }` hooks.
- ADDED: `./route-surface` — declarative `ProviderRouteSurface`: the canonical set of paths a provider OWNS (`/register`, `/login`, `/logout`, `/refresh`, `/oauth/:provider/start`, `/oauth/:provider/callback`, `/verify-email/:token`, `/forgot-password`, `/reset-password`). Concrete providers MAY implement a subset; manifest declares which.
- ADDED: `./path-ownership` — `PathOwnership` shape: `{ prefix: string, owned: readonly string[] }`; runtime registry tracking which paths are reserved by an installed provider.
- ADDED: `./collision-detector` — `detectAuthPathCollisions({ provider, plugins }): CollisionReport`; runs at install time. Plugin routes whose prefix overlaps with `provider.pathPrefix` AND aren't `publicRoutes` MUST be reported as `AUTH_PROVIDER.PATH_COLLISION`.
- ADDED: `./capability-id` — adds `"auth.provider"` to the `CapabilityId` union.
- ADDED: `./error-codes` — frozen `AUTH_PROVIDER_CODES`: `PATH_COLLISION`, `MULTIPLE_PROVIDERS_REGISTERED`, `PROVIDER_LIFECYCLE_FAILED`, `OAUTH_CALLBACK_INVALID_STATE`.
- ADDED: `./testing` — `runAuthProviderConformance(factory)` reusable harness.
## CapabilityId additions
This package contributes `"auth.provider"` to the `CapabilityId` union — separate from `"auth.session"` so a plugin can require session resolution without forcing the host to ship account-lifecycle routes.
## Out of scope
- Concrete providers — `api-auth-better-auth` (Stage 6), `api-auth-rolled` (Stage 8).
- The `Principal` shape or session resolution — that's `api-auth` + `api-types`.
- OAuth state-store implementation — provider-specific.
## Source mapping
Genesis-original. Source of design intent: `docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md`.
| Requirement | Design doc section |
|---|---|
| Path ownership (`/auth/*`, configurable) | §2.3 (lines 192-198) |
| Collision detection at install | §2.3 ("Host reserves the prefix and refuses plugin routes that collide") |
| Provider lifecycle hooks | §4 (FSM inherited from generic plugin lifecycle) |
| Provider route surface (register/login/oauth/verify-email) | §2.3 (lines 193-194) |
### Requirements with no source line
| Requirement | Justification |
|---|---|
| `MULTIPLE_PROVIDERS_REGISTERED` enforcement | Implicit in §2.3 ("Mix-and-match" describes a single provider + session resolvers chain). Pinned here so the host's behavior is explicit. |
| `runAuthProviderConformance` harness | Stage-5 deliverable (§13.4). |
## Verification approach
- `src/provider/provider.spec-conformance.test.ts` — interface shape.
- `src/route-surface/route-surface.test.ts` — canonical path set documented; providers can declare a subset.
- `src/collision-detector/collision-detector.test.ts` — overlap rules: `/auth/register` collides with plugin route `/auth/x`; `/auth/register` does NOT collide with plugin route `/billing/x`; configurable prefix `/myauth` shifts the collision domain.
- `src/path-ownership/path-ownership.test.ts` — registry rejects double-registration (`MULTIPLE_PROVIDERS_REGISTERED`).
- `src/capability-id/capability-id.spec-conformance.test.ts` — `"auth.provider"` in `CapabilityId`.
- `tests/dep-graph.test.ts` — deps: `@suaveplan/api-types`, `@suaveplan/api-router` (peer, for `Router` type), `@suaveplan/error`, `@suaveplan/types`, `zod`.
## Migration impact
None — additive only.
## Impact
### Affected dependents
- (none) — [x] no action needed (reason: net-new; concrete providers land Stages 6/8)