Repository navigation
feat(linux): reverse-attach grants survive a daemon restart (#12) - #42
Merged
Merged
Conversation
Live grants are written to a mode-600 JSON file (MCP_GRANTS_FILE, default $XDG_STATE_HOME/oab-instance-mcp/grants.json, 'off' disables) on create, replace, DELETE and terminal end. At startup every grant still inside its deadline is re-dialled under its original id; a runtime that forgot it answers 401 and the grant ends through the normal disposition. Atomic replace, dir 0700, a widened file is narrowed before being read. The secret is stored at the same trust level as the bearer token file and never appears in GET /attach.
chaodu-agent
marked this pull request as ready for review
September 29, 2026 23:42
This was referenced Sep 29, 2026
Merged
jinwei-pikmin
added a commit
to jinwei-pikmin/instance-mcp
that referenced
this pull request
Sep 30, 2026
…e frames Parity with Swift openabdev#43 and the upstream Linux PoC openabdev#42: - attach/store.rs: live grants (not ended, not expired) in $XDG_STATE_HOME/oab-instance-mcp/grants.json — 0600 in a 0700 dir, narrowed again if widened, atomic replace, secret included (never in GET /attach). Saved on create, replace, revoke, sweep and when a dial loop ends for good (client exit hook), so revoked or runtime-ended grants are not resumed. - AttachManager::resume() at start re-dials each persisted grant still inside its deadline under its original id, profile resolved again (a custom profile that is gone is skipped and logged) and the remaining TTL carried over; the file is rewritten without expired or unresumable entries. - --no-grant-persistence keeps grants in memory only (Swift flag name). - On a Close frame from the runtime, flush tungstenite's echoing Close before leaving, so the runtime sees a clean close handshake instead of a bare EOF (the mock runtime reported close_echo_missing; upstream fixed the same). Tests: saved privately and dropped on revoke; a simulated restart redials the same id with the saved secret (the fake runtime 401s any other); expired and undefined-profile grants are not resumed; a runtime-revoked grant leaves the file. 73 pass. Live with upstream's mock_runtime.py (CLOSES=4006): the same grant id resumed across two real daemon restarts with the TTL carried over, and close_echo_missing dropped to 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Linux side of #12: reverse-attach grants survive a daemon restart.
attach/store.rs: live grants →MCP_GRANTS_FILE(default$XDG_STATE_HOME/oab-instance-mcp/grants.json;offdisables). Mode 600 in a 0700 dir, atomic replace, a widened file is narrowed before being read, expired/malformed entries dropped on load.DELETEand terminal end (set_ended), so revoked/ended grants are never resumed.GET /attach.Tests: 4 unit tests (round trip + perms, expiry/malformed, narrowing, missing file). Smoke adds 8 checks: file 600, grant present, secret not in API,
kill -9→ restart → redial on its own, same id, resume logged,DELETEremoves it, revoked grant not resumed — 46/46 on amd64 + arm64.Live: on black (CI-built binary), lent to
kiro-1040sessionmac,systemctl --user restart: runtime showsattached: trueagain on a new socket (peer :47434 → :47478) under the same grant id, no human action.Swift side (Keychain + UserDefaults per the issue) is still to do; #12 stays open for it.