# `composition` _(no submodules)_ ## Purpose Top-level factory `createRolledAuthAdapter` that wires the four sub-modules (`token-rotator`, `session`, `principal-projection`, `security-schemes`) into a single `AuthAdapter` ready for the host to register. Keeping the composition explicit (rather than letting each sub-module own its own host wiring) means the dependency graph is one arrow: options flow in, an adapter object flows out, no hidden state. The returned value extends the `AuthAdapter` contract (`resolver` + `securityScheme`) with three additional surfaces the future provider half (`api-auth-rolled-provider`) will consume: `issueToken`, `verifyToken`, and the rotator handle so operators can wire `setKeys(...)` from an out-of-band rotation cron. ## Features - Single entry point — `createRolledAuthAdapter(rawOptions)`. - Options validated via the package's Zod schema before any wiring runs. - Defaults filled at the composition layer (cookie name, rotation period, session TTL) so individual sub-modules stay focused on their one concern. - Returned adapter is structurally a valid `AuthAdapter` so any host that accepts the contract will accept the rolled adapter. ## Usage: Basic ```ts import { createRolledAuthAdapter } from "@suaveplan/api-auth-rolled"; const adapter = createRolledAuthAdapter({ store, keys: [ { kid: "k1", privateJwk, publicJwk, active: true }, ], issuer: "https://api.example.com", audience: "example-front", }); host.registerAuthSession(adapter); ``` ## Usage: Advanced ```ts import { createRolledAuthAdapter } from "@suaveplan/api-auth-rolled"; const adapter = createRolledAuthAdapter({ store, keys: initialKeys, issuer: "https://api.example.com", audience: "example-front", cookieName: "acme.session", sessionTtlSec: 1800, rotationPeriodMs: 12 * 60 * 60 * 1000, }); // Operator rotation cron — fetch new key from KMS, swap atomically. setInterval(async () => { if (!adapter.rotator.decide().shouldRotate) return; const next = await kms.nextKeyset(); adapter.rotator.setKeys(next); }, 60_000); ``` ## API Reference - `createRolledAuthAdapter(rawOptions: unknown): RolledAuthAdapter` - `RolledAuthAdapter extends AuthAdapter`: adds `id: "rolled"`, `rotator`, `issueToken(userId)`, `verifyToken(token)`. ## Implementation Notes The adapter intentionally keeps `id` as the literal `"rolled"` so a host running both Better-Auth and rolled can disambiguate by adapter id. The `securityScheme` slot points at the bearer contribution (the canonical single-scheme shape) but the `.schemes` map on the contribution exposes both the cookie and bearer entries — emitters aware of dual-transport adapters can register both names without a separate adapter property.