Skip to content

feat(scopes): events declares and enforces oauth scopes - #18

Merged
albanm merged 11 commits into
mainfrom
feat-scopes
Oct 19, 2026
Merged

albanm merged 11 commits into
mainfrom
feat-scopes

Conversation

@albanm

@albanm albanm commented Oct 19, 2026

Copy link
Copy Markdown
Member

Make events scope-aware: a session whose token carries a scope claim only reaches routes that check one, and gets 403 everywhere else. Sessions without a scope claim and internal secret calls are unchanged.

  • Scopes: notifications:read/:write, events:read, webhooks:read/:admin, the bare family umbrellas, and the global all:read/all:write/all:admin, declared with defineScopes (lib-common-types).
  • Each session route is guarded through one operation table (api/src/shared/scopes.ts) with requireScope (lib-express). Push registrations and admin routes stay refused.
  • The notification and webhook-subscription websocket channels accept scoped sessions; canSubscribe still applies.
  • GET /api/api-docs.json declares the scopes (fr/en) in an oauth2 scheme (oauth2SecurityScheme), each accepted scope as its own security alternative (oauth2Alternatives). It is public and does not depend on the request origin, so data-fair can merge it into the platform document.
  • lib-express 1.33.0, lib-common-types 1.27.0, lib-node 2.16.1.

Why: phase 1d of the platform authorization roadmap. Scoped sessions come from the NHI token exchange today, and later from users authorizing OAuth client apps.

Heads-up:

  • Webhook management is admin tier only, so all:write does not grant it.
  • Dev and CI now use simple-directory:master (for the scoped NHI exchange) until a release ships it.
  • events is not yet a source of data-fair's platform document; adding it is a data-fair change.

albanm and others added 11 commits October 8, 2026 15:17
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Also the jose devDependency of the scope tests, the lockfile changes are interleaved.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Routes that never read the session (internal secret pushes, ui-logs, vapidkey,
api-docs) no longer depend on the caller's credentials: a broken cookie or a
stray bearer header used to fail them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…shared lib tools

The scope vocabulary is declared with defineScopes (lib-common-types 1.26.0), which brings the
global all:* tier scopes and their descriptions; the OpenAPI oauth2 scheme comes from
oauth2SecurityScheme; requireScope (lib-express 1.33.0) reads the session itself, so
requireOperationScope no longer wraps the session middleware.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
data-fair fetches the document over the private url, without the reverse-proxy headers, and merges
it into one document per site: it is now built without the request origin (servers /events/api,
relative token url). Each accepted scope is its own security alternative, as standard OpenAPI reads
the scopes of one requirement as all needed. x-scopeIncludes is dropped, the platform reads what a
global tier scope grants from the operations that accept it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
lib-common-types 1.27.0 builds one security alternative per accepted scope and its oauth2 scheme
no longer carries x-scopeIncludes, so events stops doing both by hand. The document is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@albanm
albanm merged commit 71d169b into main Oct 19, 2026
3 of 4 checks passed
@albanm
albanm deleted the feat-scopes branch October 19, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant