Expand description
The verb-shaped OAuth HTTP surface (hand-authored, user-owned).
Five verbs, no generic CRUD anywhere on it:
POST /oauth/authorize— initiation (write:integrations): returns the provider consent URL bound to a freshly minted account row.GET /oauth/callback— the provider redirect target. PUBLIC (the provider cannot carry the caller’s auth), and side-effect-free by construction: it verifies the signed state and serves a page whose only act is auto-submitting an invisible POST form — a safe method never writes.POST /oauth/complete— the form target (write:integrations): code exchange + identity gauntlet + store + transition. Accepts the RFC-8058-style form body the page submits AND a plain JSON body.POST /oauth/:id/disconnect— revoke credential + terminal account status (delete:integrations).GET /oauth/:id/status— metadata-only account view (any authenticated principal).
Authorization fails closed: every route except the callback sits behind
require_principal (401 without a validated principal extension — the
composing host’s auth layer inserts it) and enforces its own permission
(403 without it). No god flag grants every verb.
Tenancy (ADR-0029): the module’s tables carry no company column — the
composing service’s tenancy decorator owns org scoping, so isolation here
is the host’s fence plus permission checks, not a company predicate. The
principal’s company_id is forwarded only on the verbs that reach the
credential STORE (complete / disconnect) — it is the store’s scope key,
the documented legacy twin; an unknown value fails closed at the store.
No response ever carries token material — the account row holds none, and the store is reachable only through the service’s port calls.
Structs§
- OAuth
Principal - The validated principal the composing host’s auth layer inserts into the
request extensions. Present ⇒ authenticated; the permission list carries
the module-scope grants (
write:integrations,delete:integrations…).
Functions§
- create_
oauth_ routes - Build the OAuth verb routes. The callback is PUBLIC (the provider cannot carry the caller’s credentials); every other route requires a validated principal and enforces its own permission.
- require_
principal - Auth-required layer: 401 unless a validated principal extension is on the request (fail closed — absence of auth information is never access).