Repository navigation
plan(confirm-sender): confirm an opencode sender by callback - #117
Merged
Merged
Conversation
…sender identity, does not make it unforgeable Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Design only — no code. Opens the change so the implementation has a reviewed shape to build against.
The problem
codec.tsdocuments the correct rule:from/fromNameare display only, and provenance must come from the authenticated connection, never these fields.lifecycle.ts:122passes the envelope field toresolveOpencodeSender. There is no third path, and both branches ofroute.tsare functions of a string the sender chose.So a peer writing
from = uds:opencode-skein:<another session>is attributed to that session, andverifyLeadgrants the lead's scopes off that match. Written up in #112 with a failing-test formulation; this change is the fix's design.Why callback, not credentials
No peer-credential primitive exists in the runtime. Probed on Bun 1.3.14 over a live unix socket:
Socketexposes nogetPeerName,getPeerCredentialsorgetPeerCert. The connection exposes nothing to read, so this is a platform constraint rather than a gap in this codebase.So identity comes from asking the claimed sender, which alone holds the answer. A forger cannot make the real session report a message it never sent.
Decisions
verifyLead(lead.ts:222-234) requiressender.sessionID === grant.lead.sessionID, so an unattributed sender cannot match a grant. Fail-open on delivery, fail-closed on authority — that asymmetry is the entire safety property.(msg_id, receiver_session_id), where the receiver is the target the sender dialed at send time, not the return path. A confirm on the right socket with the wrong receiver is a miss. This matters because the current frame carries no receiver identity at all (buildMessageFramehasmsg_idandfromand nothing else), so the binding has to be constructed here — and if it were derived from the return path the lookup would degrade to "did I ever send this msg_id" and D5 would collapse.Residual, stated not hidden
Against a same-user, shell-capable agent, nothing short of OS separation makes sender identity unforgeable. A process that can replace a registry entry or a socket can still answer for it. This bounds the claim; it does not make it absolute. That is why the surrounding controls are bounded claims — human-granted, scoped, expiring, never-listed.
Tests pinned before implementation
1.1 asserts both halves —
verifyLeaddenies a forgedfrom, and the delivery-attribution caller (lifecycle.ts:122) does not treat the unattributed result as authoritative.resolveOpencodeSenderhas two callers and only one of them is the lead check.🤖 Generated with Claude Code