Repository navigation
feat(auth-permission): add expressRegisterPermissionAuth for Express-based services - #67
Merged
Merged
Conversation
β¦e shared logic wave-usage-api (and other Express-based wave-*-api services) can't use registerPermissionAuth as-is: it's Fastify-only (app.addHook, request .routeOptions.url). Generalizes the credential/broker-scope logic to a minimal transport-agnostic WaveRequest shape (headers, rawHeaders, query) that a real Express Request satisfies natively, and that Fastify's request converts into via one small adapter (to-wave-request.ts) since it nests rawHeaders under .raw. checkApiKeyPermission/authenticateWithSessionToken become pure β they return a BrokerContext instead of mutating the request β so each framework's own orchestrator assigns it onto its own native request object. Adds expressRegisterPermissionAuth as a new @wave-tech/framework/auth-permission/express subpath (kept separate from the main auth-permission subpath specifically so an Express-only consumer never pulls in @fastify/rate-limit, which register-permission-auth.ts imports as a value). Since Express gives a .use()-mounted middleware no equivalent to Fastify's already-resolved routeOptions.url, route resolution is done with path-to-regexp against the same "METHOD path" route map, matching in the map's own insertion order β mirroring Express's own first-registered-wins tie-break on overlapping patterns exactly, rather than trying to reject overlap as invalid (a real, unavoidable overlap between two fixed API paths already exists in wave-usage-api's own bff module). No rate-limiting option on the Express side: @fastify/rate-limit is Fastify-only. express and @types/express move from a regular dependency/devDependency to an optional peer dependency (mirroring the existing fastify pattern), and @types/express is aligned to the 4.x line to match the express runtime version actually in use. No observable behavior change for existing Fastify consumers β the pure- function refactor is covered by the existing register-permission-auth.spec.ts suite unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
register-permission-auth.ts(+spec), to-wave-request.ts and rate-limit/ only ever work with Fastify β moves them into fastify/, mirroring express/, so each transport's own pieces sit together and the shared/api-key/session-token folders stay unambiguously framework-neutral. Import-path-only change, no behavior difference β the public @wave-tech/framework/auth-permission export is unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Summary
wave-usage-api (BFF/API/Accounts, all Express) and potentially other
wave-*-apiservices can't useregisterPermissionAuthas-is β it's Fastify-only. This ships the Express-compatible sibling,expressRegisterPermissionAuth, on a new@wave-tech/framework/auth-permission/expresssubpath, sharing the same underlying permission/session-token/broker-scope logic instead of duplicating it.readApiKey/readBearerToken/readBrokerId/resolveBrokerScope(renamed fromresolveBrokerContext),checkApiKeyPermission,authenticateWithSessionTokennow operate on a minimalWaveRequestshape (headers,rawHeaders,query) instead ofFastifyRequest. A real ExpressRequestsatisfies it natively; Fastify gets one small per-request adapter (to-wave-request.ts) since it nestsrawHeadersunder.raw.checkApiKeyPermission/authenticateWithSessionTokennow return the resolvedBrokerContext(orundefined) instead of writingrequest.brokerContextdirectly. Each framework's own orchestrator assigns it onto its own native request β no observable behavior change for the existing Fastify hook, covered by the unmodifiedregister-permission-auth.spec.tssuite.expressRegisterPermissionAuth: mirrors the Fastify hook's contract (public-path bypass, credential-before-routing, deny-by-default,brokerScoped/acceptsSessionTokensupport) with two documented, deliberate divergences:publicPathsdefaults to[], not Fastify's β this middleware is meant for a sub-router, wherereq.pathis router-relative (GET /apiarrives as/), so reusing Fastify's defaults would silently make a router's own root public.403, never a synthetic404β Express gives a.use()-mounted middleware no equivalent to Fastify's already-resolved route before real handlers run, and letting a miss fall through unauthenticated would defeat deny-by-default.path-to-regexpagainst the same"METHOD path"map, matching in the map's own insertion order β mirroring Express's real first-registered-wins tie-break on overlapping patterns (a real, unavoidable overlap between two fixed paths already exists in wave-usage-api's ownbffmodule:/accounts/by-external-code/:externalCodevs/accounts/:accountId/balances)../auth-permissionbarrel) specifically so an Express-only consumer never pulls in@fastify/rate-limit, whichregister-permission-auth.tsimports as a value. No rate-limiting option on the Express side β that's Fastify-only for now.express/@types/expressmove from a regular dependency/devDependency to an optional peer dependency (mirroring the existingfastifypattern),@types/expressaligned to the 4.x line to match the actualexpressruntime version.This is Part 1 of a two-part effort (see internal plan) β wiring this into wave-usage-api itself is a separate, later PR.
Test plan
pnpm run lintpnpm testβ 237/237 passing, including 16 new tests (express-register-permission-auth.spec.ts,route-matcher.spec.ts) and the existingregister-permission-auth.spec.tssuite unchanged and still green after the pure-function refactorpnpm run buildβ confirmeddist/auth-permission/express/{index.js,index.d.ts}exist and that subpath's compiled output has zerorequire('fastify')/require('@fastify/rate-limit')in its dependency graphπ€ Generated with Claude Code