Auth Architecture
UCCA Auth Architecture Unified Identity, Credentialing & Access Control — All Surfaces Version 1.0 · 20 March 2026 · Session 26 LIVING DOCUMENT — update when any auth decision changes. This is the source of truth for the entire auth architecture.
- The Principle — One Trust Anchor Every authentication and authorisation decision across the UCCA ecosystem flows from a single root: the UCCA OAuth 2.1 server at mcp.ucca.online. This is not aspirational — the OAuth 2.1 server is live, production-grade, and battle-tested as of Session 26.
The architecture is built around one rule: an entity (human or machine) proves who it is once, receives scoped credentials from UCCA, and those credentials travel across all surfaces. There is no separate login for the MCP API, the operational API, the key server, or the ops console. One identity root, multiple scopes, one token shape.
This is the infrastructure equivalent of the UCCA pitch: 'The internet moved data without knowing who sent it. UCCO moves capability with full knowledge of who holds it.' UCCA's own infrastructure must demonstrate this thesis. It does.
- What Is Live — As of Session 26 2.1 OAuth 2.1 Server — mcp.ucca.online (ucca-mcp Worker) Full OAuth 2.1 with PKCE implementation. Confirmed live from code audit 20 March 2026.
Issuer https://mcp.ucca.online Authorization endpoint https://mcp.ucca.online/oauth/authorize Token endpoint https://mcp.ucca.online/oauth/token Revocation endpoint https://mcp.ucca.online/oauth/revoke Grant types authorization_code only PKCE S256 required — no exceptions Token format Opaque Bearer token (randomHex(48)), SHA-256 hashed in DB Token TTL 3600 seconds (1 hour) Client registration Via /ops/clients endpoint (OPS_API_KEY protected) Discovery /.well-known/oauth-authorization-server (RFC 8414) DB ucca-mcp D1 — oauth_clients, oauth_codes, oauth_tokens, oauth_usage, mcp_usage tables Scopes currently issued 'read' only — scope expansion is the roadmap item
⚠ Scope expansion is the key deferred item. Currently all OAuth tokens get 'read' scope. The architecture calls for granular scopes (rtopacks:operational, rtopacks:developer, etc.) — this is not yet implemented in the token issuance flow.
2.2 rtopacks-mcp — Bearer Key Auth (KV-based, interim) Deployed in B-MCP-02. Uses a separate KV namespace (MCP_API_KEYS, ID: 795d76eb) on the UCCA account. Keys are SHA-256 hashed, tiers stored as JSON values. This is an interim mechanism — the end state is OAuth tokens with rtopacks:developer / rtopacks:professional scopes replacing these KV keys.
KV namespace MCP_API_KEYS — 795d76eb Key format sha256(raw_key_string) Value schema { tier, user_id, rtopacks_subscription_id, ecosystem_rate, calls_this_month, calls_reset_at, active } Tiers developer (5k calls/mo) | professional (25k calls/mo) | enterprise (unlimited) Free tier No key required — 1 result, no components, no labour market data Ecosystem rate $100/mo off Developer ($199→$99) and Professional ($399→$299) when rtopacks_subscription_id present Tim test key rtopacks_pro_tim_4c1629c7b01276a3acc48d8bb997a1fc (Professional, 25k calls/mo) Migration path Replace KV keys with OAuth tokens scoped to rtopacks:developer / rtopacks:professional in B-API-02
2.3 rtopacks-api — Currently Open (Stop-gap in progress) As of Session 26, rtopacks-api (/v1/search, /v1/lookup, /v1/ladder, /v1/pathway) has NO authentication. This is a live data leak. B-MCP-02 addendum instructs Alex to add a temporary X-RTOpacks-Key shared secret header check while B-API-01 is designed.
⚠ rtopacks-api is leaking corpus data including full unit elements, performance criteria, and pathway analysis. Stop-gap must be deployed before B-API-01 is written.
2.4 keys.ucca.online (ucca-keys Worker) Magic link auth via Resend email + Twilio SMS phone verification. Issues credential ledger entries to rtopacks-db. Apple PassKit integration live (pass.online.ucca.credential, cert expiry 2027-04-16). This surface will eventually issue OAuth-backed credential tokens — not yet wired.
2.5 Cloudflare Access — ops.ucca.online ops.ucca.online is behind Cloudflare Access (zero-trust). Tim and Alex only. OPS_API_KEY provides a secondary check on ops API endpoints within the Worker. This layer is complete and correct — no changes planned.
- Scope Architecture — The Roadmap This is the target state. Not all scopes exist yet in the OAuth server. This table defines what they will be and what they gate.
Scope Consumer Access Pricing rtopacks:operational RTO systems (Moodle, LMS, SMS) lookup, search, ladder Included in RTOpacks subscription rtopacks:developer Developers, indie builders search, lookup, ladder + components $199/mo | $99 ecosystem rtopacks:professional Analytics, AI agents, data products All tools + employment_signals $399/mo | $299 ecosystem rtopacks:enterprise Enterprise, schema licensing All tools + custom corpus Contact us ucco:framework UCCO Foundation MCP clients UCCO standard tools Public / Foundation ucca:admin Internal ops console only All surfaces + ops endpoints Internal — OPS_API_KEY only
The scope expansion requires: (1) updating the OAuth token issuance flow to accept a requested scope, (2) storing the scope in the oauth_tokens table, (3) validating scope in each Worker's auth middleware rather than just checking token validity. This is B-API-02 scope (no pun intended).
- Surface Auth Map — Current + Target State
Surface Purpose Auth Method Notes mcp.ucca.online/mcp UCCA corporate MCP OAuth 2.1 PKCE (optional) Public tools — company info, standard relationship. Auth tracked for usage analytics. mcp.ucco.foundation UCCO standard MCP OAuth 2.1 PKCE (optional) UCCO standard tools. Separate server, separate DB. mcp.rtopacks.com.au/mcp RTOpacks Analytical MCP Bearer key → KV tier check Tiered: Free/Developer/Professional. employment_signals = Professional only. api.rtopacks.com.au/v1/ RTOpacks Operational API RTOpacks subscription token (B-API-01) RTO systems — lookup, search, ladder. NOT pathway. Generous limits. keys.ucca.online Key server + VCC ledger Magic link auth + phone verify Credential issuance, ledger entries, PassKit passes. ops.ucca.online Ops console Cloudflare Access + OPS_API_KEY Internal only — Tim/Alex. Never public.
⚠ api.rtopacks.com.au is listed as target state — it does not yet have its own subdomain or auth. Currently rtopacks-api serves from the worker URL. B-API-01 will create the proper surface.
- The Unified Auth Flow — Target State This is how it works when fully built:
Step 1 — Registration Entity (human or machine) registers at rtopacks.com.au/auth via magic link. UCCA creates a user record. An OAuth client is provisioned via /ops/clients on ucca-mcp. The client receives a client_id and client_secret.
Step 2 — Token Request Entity initiates OAuth 2.1 authorization_code flow with PKCE against mcp.ucca.online/oauth/authorize, requesting the appropriate scope (e.g. rtopacks:developer). UCCA verifies identity, issues an authorization code. Entity exchanges code for a Bearer access token at /oauth/token.
Step 3 — Surface Access Bearer token is presented to any UCCA surface. Each Worker validates the token hash against ucca-mcp D1, checks scope against the requested resource, and enforces rate limits. One token, all surfaces.
Step 4 — Ecosystem Rate If the token's user_id has an active RTOpacks subscription (verified via Stripe webhook → subscription record), the ecosystem rate applies automatically. $100/mo off Developer and Professional tiers. No coupon code, no manual process.
Step 5 — Credential Issuance (future) When a UCCA credential is issued via keys.ucca.online, the credential record is cryptographically linked to the OAuth identity. The credential carries the same client_id as the bearer. Trust is transitive — if you trust the OAuth token, you trust the credential.
- DB Schemas — What Exists 6.1 ucca-mcp D1 (OAuth server DB) oauth_clients: client_id, client_secret_hash, client_name, redirect_uris (JSON), created_at, active
oauth_codes: code, client_id, redirect_uri, code_challenge, code_challenge_method, expires_at, used
oauth_tokens: token_hash, client_id, scope, expires_at, revoked
mcp_usage: tool_name, authenticated (0|1), created_at
oauth_usage: client_id, tool_name, created_at
6.2 MCP_API_KEYS KV (rtopacks-mcp interim auth) key: sha256(raw_key) value: { tier, user_id, rtopacks_subscription_id, ecosystem_rate, calls_this_month, calls_reset_at, created_at, active }
6.3 Deferred — Pricing DB (L3 build) api_tiers: id, name, price_aud_monthly, ecosystem_price_aud_monthly, call_limit_monthly, includes_labour_market, stripe_price_id_standard, stripe_price_id_ecosystem, active
api_keys: (replaces MCP_API_KEYS KV when OAuth scope migration complete) key_hash, user_id, tier_id, rtopacks_subscription_id, ecosystem_rate_applied, calls_this_month, calls_reset_at, created_at, last_used_at, active
-
Build Sequence — Auth Roadmap DONE OAuth 2.1 server live at mcp.ucca.online — authorize, token, revoke, PKCE, client registration DONE rtopacks-mcp KV-based tier auth — Free/Developer/Professional, rate limiting, ecosystem rate DONE Cloudflare Access on ops.ucca.online — Tim/Alex only DONE Magic link auth at rtopacks.com.au/auth — users table, KV sessions IN PROGRESS rtopacks-api stop-gap — X-RTOpacks-Key shared secret (B-MCP-02 addendum) NEXT — B-API-01 rtopacks-api proper auth — RTOpacks subscription token, scope-based, /v1/pathway removed from operational surface FUTURE — B-API-02 OAuth scope expansion — rtopacks:operational, rtopacks:developer, rtopacks:professional scopes in token issuance flow FUTURE — B-API-02 Wire rtopacks-mcp and rtopacks-api to validate OAuth tokens in addition to (then replacing) KV keys FUTURE — L3 Stripe subscription → auto-provision OAuth client + scope. Ecosystem rate auto-applied via Stripe webhook. FUTURE — L3 keys.ucca.online credential issuance linked to OAuth client_id — cryptographic identity chain
-
Standing Rules — Never Break These UCCA OAuth server (mcp.ucca.online) is the single identity root. Never build a parallel auth system. Two Cloudflare accounts must never be crossed — UCCA (e5a9830215a8d88961dc6c80a8c7442a) vs UCCO Foundation (aed3398a...) ops.ucca.online is internal only — Cloudflare Access + OPS_API_KEY. Never expose ops endpoints publicly. All OAuth tokens are opaque Bearers hashed with SHA-256. Never issue JWTs from UCCA OAuth — UCCA is the verifier, not the issuer of signed assertions. PKCE S256 is required on all OAuth flows — no exceptions, no implicit flow, no password grant. Ecosystem rate is automatic — no coupon codes, no manual overrides. If rtopacks_subscription_id is present and Stripe confirms active, rate applies. KV keys in MCP_API_KEYS are interim only — do not build new features that depend on them long-term. Migration to OAuth scopes is the end state. rtopacks-api /v1/pathway is analytical, not operational — it does not belong on the operational API surface. Moves to MCP Professional tier only.
UCCA Inc · Auth Architecture v1.0 · 20 March 2026 · Living document — update on every auth decision