feat BREAKING oauth feat/companion-app #5 / 15
aaronrene · 2 days ago · Jun 6, 2026 · Diff

feat(oauth): implement server-side OAuth C1-C6 for native companion client

C1: native-client authorization path minting web-session JWTs (issueToken shape), scopes bound to scopesForRole(role); mcp_access path left untouched. C2: native refresh backed by refresh-token-core (rotation + reuse→family-revoke); token in response body (no cookie); reason codes aligned to auth-session.mjs. C3: emit iss = issuer identifier on loopback redirect in both completeMcpAuthorization and completeNativeAuthorization, equal to discovery metadata issuer. C4: durable pending auth codes in native-as-store.mjs (atomic JSON, survives restart); native refresh tokens via shared createGatewayRefreshStore(). C5: redirect_uri validated at token exchange (RFC 6749 §4.1.3); loopback-only URIs enforced at registration (RFC 8252 §7.3); SDK v1.27.1 variable-port loopback verified. C6: applyScopeCeiling() guards every token-mint path; unknown role → member ceiling; applied at code exchange and on every refresh rotation.

86/86 tests green across 7 tiers (unit, integration, e2e, stress, data-integrity, performance, security). Gate doc §6 updated to mark all Cx implemented.

sha256:318515b93ac360aca1898df0968e5dff8c416434a091b5da372ce632745f705a sha
+65 ~7 symbols
777 changed · 777 in snapshot files
sha256:432c9394228cbbab93e609b9fccdba19981a5105e4d71fd0582c8a4bad15f29a snapshot
+65
symbols added
~7
symbols modified
777
files changed
777
files in snapshot
0
dead code introduced
Semantic Changes 72 symbols
~ hub/gateway/native-as-store.mjs .mjs 9 symbols added
+ _nativeCodePath function function _nativeCodePath L61–64
+ _normalizeCodes function function _normalizeCodes L89–106
+ _pruneExpired function function _pruneExpired L72–80
+ _readCodes function async_function _readCodes L112–121
+ _writeCodes function async_function _writeCodes L129–141
+ bindUserToCode function async_function bindUserToCode L180–187
+ consumePendingCode function async_function consumePendingCode L197–204
+ pruneExpiredCodes function async_function pruneExpiredCodes L210–216
+ savePendingCode function async_function savePendingCode L157–170
~ hub/gateway/native-oauth-provider.mjs .mjs 10 symbols added
+ NativeClientStore class class NativeClientStore L156–221
+ constructor method method constructor L157–160
+ getClient method method getClient L166–168
+ registerClient method method registerClient L178–220
+ _nativeRefreshError function function _nativeRefreshError L107–118
+ _sha256Base64url function function _sha256Base64url L95–97
+ applyScopeCeiling function function applyScopeCeiling L137–140
+ completeNativeAuthorization function async_function completeNativeAuthorization L565–599
+ createNativeOAuthRouter function function createNativeOAuthRouter L245–602
+ isLoopbackUri function function isLoopbackUri L76–88
+ applyScopeCeiling function function applyScopeCeiling L120–123
+ grantedScopes function function grantedScopes L117–119
+ sha256b64url function function sha256b64url L21–23
~ test/native-oauth-c1-c6-e2e.test.mjs .mjs 10 symbols added
+ fetch method async_method fetch L50–70
+ grantedScopes function function grantedScopes L96–100
+ issueAccessToken function function issueAccessToken L88–94
+ json method method json L176–176
+ redirect method method redirect L177–177
+ sha256b64url function function sha256b64url L26–28
+ start method method start L38–46
+ status method method status L175–175
+ stop method method stop L47–49
+ testClient function function testClient L33–72
+ cookie method method cookie L144–144
+ end method method end L143–143
+ grantedScopes function function grantedScopes L88–92
+ issue function async_function issue L34–40
+ issueAccessToken function function issueAccessToken L81–87
+ json method method json L233–233
+ makeRequest function function makeRequest L123–151
+ mockRefreshStore function function mockRefreshStore L31–68
+ redirect method method redirect L234–234
+ revoke function async_function revoke L60–65
+ rotate function async_function rotate L42–58
+ runFullFlow function async_function runFullFlow L153–177
+ set method method set L139–139
+ sha256b64url function function sha256b64url L27–29
+ status method method status L232–232
+ applyScopeCeiling function function applyScopeCeiling L92–95
+ elapsed function function elapsed L29–32
+ run function async_function run L126–141
+ sha256b64url function function sha256b64url L25–27
+ fetch method async_method fetch L46–63
+ grantedScopes function function grantedScopes L86–89
+ issueAccessToken function function issueAccessToken L78–84
+ json method method json L454–454
+ redirect method method redirect L455–455
+ sha256b64url function function sha256b64url L27–29
+ start method method start L35–42
+ status method method status L453–453
+ stop method method stop L43–45
+ testClient function function testClient L31–65
+ sha256b64url function function sha256b64url L19–21
~ test/native-oauth-c1-c6-unit.test.mjs .mjs 3 symbols added
+ roleForSub function function roleForSub L88–90
+ scopesForRole function function scopesForRole L84–87
+ sha256b64url function function sha256b64url L26–28
Files Changed
+777
777 in snapshot
+ .env.example .example
+ .gitignore .gitignore
+ .gitleaks.toml .toml
+ .museattributes .museattributes
+ .museignore .museignore
+ .nvmrc .nvmrc
+ AGENTS.md .md
+ README.md .md
+ backups/.gitignore .gitignore
+ cli/index.mjs .mjs
+ docs/SPEC.md .md
+ hub/roles.mjs .mjs
+ lib/air.mjs .mjs
+ lib/chunk.mjs .mjs
+ lib/vault.mjs .mjs
+ lib/write.mjs .mjs
+ netlify.toml .toml
+ package.json .json
+ public/.gitkeep .gitkeep
+ vault/meta/.gitkeep .gitkeep
+ web/index.html .html

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:318515b93ac360aca1898df0968e5dff8c416434a091b5da372ce632745f705a --body "your comment"