Bootstrap cross-person trust with a one-time connection code, optionally PGP-signed - #191
Merged
Merged
Conversation
Adds loadConnectionCodeLedger/saveConnectionCodeLedger to identity-store.ts, mirroring the existing loadGatewayTrust/saveGatewayTrust sibling-file pattern. Tracks two independent maps per slot: codes this slot has issued (so an outstanding code survives a restart between generation and hand-off) and nonces this slot has redeemed (so a single-use code can't be redeemed twice across a restart within its own short validity window). Also adds openpgp as a dependency, needed by the connection-code signature verification this ledger will back (agent-comms#188).
…nd redemption Implements the always-checked nonce/expiry half and the optional PGP-signature half of a ConnectionCode artifact (agent-comms#188): generate() mints a fresh single-use code vouching for a device-id, optionally signed with a caller-supplied armored PGP private key; redeem() validates freshness, single-use, and (only when a signature is present) verifies it against a caller-supplied public key, optionally pinned to an already-trusted fingerprint. PGP key material is never generated or stored by this module -- signing and verification both take key material supplied per call, the same way invoking gpg directly would, rather than agent-comms managing a persisted PGP identity of its own. Adds ConnectionCodeSchema and the gateway_generate_connection_code/gateway_redeem_connection_code CommsAction variants to types.ts, ahead of wiring them into MeshStore and CommsTool.
fetchPgpPublicKeyByFingerprint (agent-comms#188) fetches an armored public key from keys.openpgp.org's VKS API by fingerprint -- the convenience path a connection-code redeemer takes when they know the signer's fingerprint but weren't handed the armored key block directly. The keyserver is never a trust anchor: the caller already independently trusts the fingerprint they supply, and ConnectionCodeLedger.redeem's own expectedFingerprint check is what defends against a compromised or buggy keyserver returning the wrong key, not this fetch itself.
…connection_code MeshStore now constructs a ConnectionCodeLedger alongside GatewayTrust, sharing the same per-slot identity so both persist to the same bridge instance's own storage. generateConnectionCode mints a code vouching for this store's own peerId; redeemConnectionCode validates a candidate and, only on success, feeds its deviceId into gatewayTrust.add -- the actual point of the bootstrap. CommsTool gains the matching MeshOnlyFeatures methods and a fetchPgpPublicKeyByFingerprintImpl dependency (defaulting to the real keys.openpgp.org lookup, injectable for tests), used by gateway_redeem_connection_code when a caller supplies a fingerprint but not the key text itself. The two handlers live in a new connection-code-tool.ts rather than as CommsTool methods, since they take no CommsContext (unlike every other action) and keeping them out of tool.ts's own class body is what keeps that file under its existing max-lines budget. bridge.ts's MCP_TOOL_PARAMS and buildAction gain the new actions' fields (ttlMs, privateKey, passphrase for generation; code, expiresAt, signature, publicKey, fingerprint for redemption, reusing the existing device field for the code's own embedded deviceId).
…_connection_code end to end Exercises CommsTool.handle -> MeshStore -> ConnectionCodeLedger for both actions, mirroring gateway-trust-tool.test.ts's own pattern: an issuer store generates a code vouching for its own peerId, a separate redeemer store redeems it and ends up trusting that exact device via gatewayTrust. Covers the bare, PGP-signed, pasted-public-key, and keyserver-fingerprint-lookup paths, plus buildAction parsing and required-field validation for both actions.
Adds a Gateway trust and connection codes section covering the existing gateway_trust/gateway_untrust/gateway_list_trusted actions (previously undocumented) alongside the new gateway_generate_connection_code/gateway_redeem_connection_code pair, with usage examples for the bare, PGP-signed, pasted-public-key, and keyserver-fingerprint paths.
Mearman
force-pushed
the
feat/connection-code-trust-bootstrap
branch
from
September 18, 2026 08:47
aa7eebb to
692262c
Compare
Mearman
marked this pull request as ready for review
September 18, 2026 08:49
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
🎉 This PR is included in version 3.16.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
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.
Implements a single ConnectionCode artifact (nonce + expiry + deviceId + optional PGP signature) with one generation flow and one redemption flow, bootstrapping GatewayTrust without an existing mesh connection between the two devices.
Work in progress; will flip to ready once complete and green.
Closes #188