Repository navigation
feat(core): serve auth API routes from the adapter manifest - #203
Merged
Merged
Conversation
The adapters hard-coded every API route: a handler, an ensureCookies table entry, and a route in each framework. A route missing from any of them answered the adapter's own 404, so TOTP sign-in, the phone registration steps and bulk user import were never reachable, and Next.js had no PUT. Core now loads the adapter manifest the auth API publishes at /.well-known/seamless-adapter.json, falling back to a bundled copy, and handleManifestRoute proxies any route it lists: it sends the held token the route names, stores the session it issues after verifying it, clears what it clears, keeps tokens out of cookie-transport bodies, and handles external delivery. ensureCookies takes the route's credential from the manifest. Express, Fastify and Next.js use it for every route without a handler of their own, so existing routes behave as before. Next.js also returns PUT. A path parameter that decodes to a dot segment does not match, so it cannot send the held token to a different upstream path. Closes #201.
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #201. Part of fells-code/seamless-auth-api#371.
Why
Every API route needed a handler here, an entry in the
ensureCookiestable, and a route in each of Express, Fastify and Next.js. A route missing from any of them answered the adapter's own 404, and nothing caught it. As a result, several API routes were never reachable through an adapter:POST /totp/verify-login)POST /registration/phoneand/registration/phone/verifyPOST /admin/users/importPUTOAuth provider retirement routesThe auth API now publishes which token each route takes and which tokens its response issues or clears (fells-code/seamless-auth-api#380). The adapters can follow that instead of a hand-maintained list, which is also what the Go, Rust and Python adapters will build on.
What changes
Core
createAdapterManifestSourcefetches/.well-known/seamless-adapter.jsononce.matchManifestRoutematches static segments case-insensitively and prefers a static segment over a parameter. It refuses a parameter that decodes to.or.., so a request cannot send the held token to a different upstream path.handleManifestRouteproxies a matched route:tokenandrefreshTokenout of cookie-transport bodies, and handles external delivery.ensureCookiestakes optionalmethodandmanifest, and then loads the cookie the manifest names. The existing table still covers routes the manifest does not list.scripts/sync-adapter-manifest.mjsregenerates the bundled copy from the API.Adapters. Each one sends any manifest route without a handler of its own through
handleManifestRoute, after the origin guard and cookie loading:OPTIONSis left to the application's CORS handling. Manifest routes are served whatever their path casing, as Express and Next.js already did.PUThandler.Every handler already here still serves its route, and every export stays, so this is not breaking. Dedicated handlers can shrink in follow-ups where the manifest grows to cover what they do (refresh,
/users/me, logout's 204, the delivery routes). The changeset isminorfor all four packages.Visible to adopters
fetchwill see it, andfetchManifest: falseuses only the bundled copy. Existing tests here pass that option so they stay deterministic.PUT. The catch-all route should export it:export const { GET, POST, PUT, PATCH, DELETE } = createSeamlessAuthHandler(...).Follow-ups
/registration/registerand/registration/phoneas delivery routes. It missed the #380 merge. Once it merges, rerunnode scripts/sync-adapter-manifest.mjs. Until then the register route keeps its own handler, which already delivers, and/registration/phonelets the API send the message itself.Checks
pnpm test: core 395, express 210, fastify 150, nextjs 159, all passing (846 before this change).pnpm check:types-currentpasses.ensureCookies.PUT, 404, and a route only the live manifest knows.