Mobile API requests authenticated via OAuth2 bearer tokens bypassed the
Terms gate that the root loader applies to web cookie sessions. Extend
requireApiUser to compare the user's termsVersion with TERMS_VERSION
and return a structured 403 { code: "TERMS_OUTDATED", currentTermsVersion }
on mismatch so mobile clients can surface their own re-acceptance UI.
Spec delta on journal-auth captures the new requirement.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 KiB
2 KiB
Why
Mobile API requests authenticated via OAuth2 bearer tokens currently bypass the Terms gate. Web users with a stale users.terms_version are redirected to /auth/accept-terms by the journal root loader (apps/journal/app/root.tsx:58), but mobile clients hitting /api/v1/* with the same stale version get a normal 200 response. The Terms gate (defined in journal-auth/spec.md) is meant to apply to all authenticated requests, not only cookie-session traffic.
What Changes
- Extend the bearer-token API chokepoint (
requireApiUserinapps/journal/app/lib/api-guard.server.ts) to compare the authenticated user'stermsVersionagainst the currentTERMS_VERSION. On mismatch, return a structured HTTP 403 with{ error, code: "TERMS_OUTDATED", currentTermsVersion }so the mobile app can surface its own UI (or open the web Terms page in a webview). - Add
TERMS_OUTDATEDtopackages/api/src/errors.tsERROR_CODESso clients have a stable code to switch on. - Spec delta on
journal-auth: add a requirement that the Terms gate also applies to bearer-token API auth, with the structured-error contract as a scenario.
Web cookie-session behaviour is unchanged (still a redirect via the root loader). Only the API chokepoint changes.
Capabilities
New Capabilities
(none)
Modified Capabilities
journal-auth: adds a requirement that the Terms-version gate applies to bearer-token API requests, returning HTTP 403 with a structuredterms_outdatedpayload instead of a redirect.
Impact
- Code: one function (
requireApiUser) gains a terms check; one constant added to@trails-cool/api. - Clients: the mobile app needs to handle
403 { code: "TERMS_OUTDATED" }(out of scope for this change — tracked separately on the mobile side). - Tests: unit test for
requireApiUsercovering stale / current / nulltermsVersion. - Specs: 1 spec delta on
journal-auth(added requirement). - Out of scope: mobile client UI for the new error; any change to web cookie-session behaviour.