Repository navigation
feat(capy): add explicit OAuth reply permits for native bindings - #113
Conversation
Pre-merge checks:
|
There was a problem hiding this comment.
APPROVE on bdbda98 (review-only: I do not merge).
Contract check against issue #99 (comment 6792521034), all met:
- Separate permit row (
capy_grant_permits, migration 0046), not a grant id on the binding. Composite FKs target the existing UNIQUE onmcp_oauth_grants(0015, kept through the 0033 rename) and the new UNIQUE oncapy_bindings; live uniqueness per (grant, binding). - Created only by
bind_capy_threadunder the OAuth grant, insideconnection.lock(tx)plus the binding lock, for an already spawn-bound thread with same user/org/workspace,state='bound', owner/admin role and key-owner checks (viaaccess()incurrent()), name derived from the thread id. No provider or Relay call on bind. - Used for send only through the #110
capyActorpath; no participant row, join, pin or token exposure.assertActor/pin untouched; the only new branch inhostedActoris gated on OAuth +capyPermits+as !== approved persona, and a missing permit falls back to the original persona path (native Capy fallback still requires!managed && !oauth). - Revoked in the grant revocation transaction; fails closed on retire, generation bump, remote id or name change, key-owner change, role downgrade, expired/rotated bearer, and permit revocation between pre-send reads and the write.
- No custody transfer; unbound-thread grant bind stays out of scope; default-off (module not supplied by the app server, capability false).
Local checks (one worker, serial), head bdbda98: typecheck 0; test/capy-grant-permits.test.ts 13/13; test/capy-bindings.test.ts 23/23; test/capy-mcp-identity.test.ts 6/6.
Exact-head CI: run 43005455197 success on bdbda98.
🤖 Generated with Claude Code
|
Independent exact-head approval5857520055 verifies the permit contract and independently runs13 permit,23 binding and6 native-identity checks with clean typecheck. Required CI43005455197 is SUCCESS on bdbda98;0 unresolved threads. CodeRabbit's visible title/description assessments are inconclusive with no code finding or location; its check is skipped, so no rerun or hidden-review gate is inferred. Author validation is1,197 pass,0 fail/cancel,13 existing skips under Node22.23.2, clean typecheck/build, and nine named guard removals that each cause the intended regressions before exact restoration. These are source checks: the optional module remains unmounted and no provider runtime or E2E result is claimed. Remaining delivery/history/rehearsal work stays in #99. |
An OAuth connection cannot reply as a native Capy binding solely because the same person owns both. Add an explicit send permit:
bind_capy_thread(thread_id)returns an existing owned binding withalready_bound: trueand creates only an exact-grant permit. It refuses missing bindings. The binding retains its identity, conversations and native custody; the consented OAuth persona stays pinned independently.The optional module exposes bind/unbind only to OAuth MCP contexts. Only
send_relay_message as=<binding agent>resolves a permit; inbox, conversation, channel, join, launch and Desktop rights retain their existing actor checks.unbind_capy_threadrevokes only this connection's permit. Grant revocation revokes its permits in the same transaction, while native inbound delivery remains independent. Use checks live membership/key ownership, grant/bearer, binding generation, immutable remote ID/name and admitted Relay route/key, including a fresh fence after message metadata reads.This is an internal source slice for #99. The application does not mount the module; runtime capability remains false. Durable callbacks/subscriptions/delivery, history and real-account acceptance remain open. It changes neither generic OAuth
assertActor/pinnor provider identity custody. Provider credentials remain exclusively inremote_agent_connections.Migration
0046_capy_grant_permits.sqlhas tenant-bound foreign keys and one live permit per grant/binding. Fresh main4d4a427fends at0045; no other open Control PR reserved a migration immediately before this push. Completed native custody cleanup cascades only its permit records.Validation (Node22.23.2 through
aw-heavy, serial):node node_modules/typescript/bin/tsc -p tsconfig.json --noEmit: clean.node node_modules/typescript/bin/tsc -p tsconfig.build.json: clean.node --import tsx --test --test-concurrency=1 test/*.test.ts:1,197 pass,0 fail,0 cancelled,13 existing skips on Node22.23.2. Typecheck and build completed successfully immediately before this full run.Admission contract: #99 comment6792521034. Callback ownership is Control messaging; provider-file/integration intake remains with relayfile-control.
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.