feat(contract): deckard-contract crate + virtual Cargo workspace (freeze-first wire)#3
Merged
Merged
Conversation
Freeze the shared wire so the agent surface, custody/daemon, and test harness can build in parallel before the real signer daemon exists. New crate `crates/deckard-contract` (std + serde, zero key material): - Frozen types: Intent (carries chain_id; daemon owns the nonce), IntentKind, Decision, Policy, ApprovalMode, and the SignerRequest/ SignerResponse/ExecuteResult/ApprovalStatus/BalanceReport RPC enums. - A sync `Signer` trait + an in-memory `MockSigner`: deterministic and pinned (address 0x11.., tx_hash 0xAB.., request_ids 0x01,0x02,..), implementing the full policy decision matrix incl. the TOCTOU revoke guard at execute time. `Box<dyn Signer>` works. - Tests: serde_json + ciborium (CBOR) byte-stable round-trip per type; the decision matrix; and the daemon-free slice of 30-mcp-shape T1-T8. - Normal deps are only alloy-primitives + serde; ciborium/serde_json are dev-deps. id minting panics loudly on >255 proposals instead of wrapping. Workspace: root becomes a virtual manifest (members deckard-app/-core/ -contract, default-members deckard-app so `cargo run` still launches the GUI; [profile.release] + [workspace.dependencies] at the root). The app moves to `crates/deckard-app` via `git mv` (binary stays `deckard`). justfile + CI build/test `--workspace`; `just bundle` bundles the prebuilt icon.icns from crates/deckard-app/assets (cargo-bundle 0.11 can't convert the 1024px png, and resolves icon paths against the CWD).
These were authored via the /spec process but were only ever untracked working-tree files. deckard-contract's README and crate docs point at docs/build/30-mcp-shape.md as the contract's owner, so land the set the links resolve to: - docs/build/ — the parallelizable v1 build specs (30-mcp-shape owns the Intent/Decision/daemon-socket contract; 00/10/20 reference it). - docs/research/ — the research KB + v1-demo-plan the build specs cite. Additive markdown only. If another PR already owns these, drop this commit.
hellno
added a commit
that referenced
this pull request
Jun 6, 2026
…gun's EIP-1193 provider (T-Trustless #3) Proves the v1 seam end to end (against kohaku@618c53f): Helios's localhost JSON-RPC server (.rpc_address) is the EIP-1193 provider Railgun reads through. - IntoEip1193Provider is Kohaku's OWN 7-method trait (eip-1193-provider crate); an alloy DynProvider satisfies it via Kohaku's shipped Alloy adapter — no custom adapter for v1. Read/sync path = exactly eth_blockNumber + eth_getLogs + eth_call, all in Helios's served set. - One required fix: alloy's Provider::call defaults to the `pending` tag, which Helios (light client) can't serve; build the provider with ProviderBuilder::with_default_block(BlockId::latest()). One line, Deckard-side. - Tier-2 (default) drives the adapter + logs methods via a pass-through proxy; Tier-1 (--features railgun) links the full railgun ZK crate and drives the real RpcSyncer/RailgunBuilder through Helios (414 SyncEvents). railgun compiles standalone (retires 10's R1c). Loopback hop ~0.3 ms/call (release). Findings written into 20-helios-sidecar.md (Integration + Measured + open-questions).
hellno
pushed a commit
that referenced
this pull request
Jun 14, 2026
PR #52 resolved the dapp-connectivity exploration and created canonical issues (epic #44, PRD-01..05 #45-50) plus an issues-not-files convention. Reconcile this doc to a rubric + decision record, not a parallel tracker: - Replace the work-item sequencing backlog and the EIP-7702 spike brief (duplicated existing issue #33) with a Tracking & cross-references block - Fix the now-outdated connection-surface framing: #25 browser integration is planned/phased via the owned EIP-6963 bridge (ADR 0001), not 'no dapps'; #11 isolation maps to per-origin permissions (PRD-05 #48), not a wire token - Point #3 clear-signing at PRD-02 #46; note PRD-01 #45 resolver-auth - Update Stages + status notes to match
This was referenced Jun 14, 2026
hellno
added a commit
that referenced
this pull request
Jun 20, 2026
Inverts the signer daemon's auto-approval guardrail from fail-open (armed only on chain_id==1) to fail-safe default-deny (armed on every chain except an explicit exempt testnet/dev allowlist {Sepolia 11155111, anvil 31337}; unknown chain-ids guarded). mainnet_guardrail_active -> guardrail_active, mainnet_override -> autonomy_override (env var DECKARD_I_KNOW_THIS_IS_MAINNET unchanged, now disarms on any real-value chain, documented in THREAT-MODEL.md only). Adds Base-8453 + unknown-id classification tests, an exec-level not_approved test, and a structural pin that 1/8453/10/42161 are never exempt. Broadens README/THREAT-MODEL/CONTRIBUTING/STATUS + agent docs (kept honest: exempt-chain within-cap auto-allow is by-design, default policy still OverCap, residual-risk #3 narrowed not resolved). Guard-shape only; no policy fields, no new deps.
Closes #76. Reviewed via /autoplan (CEO + Eng dual-voice, Claude + Codex).
This was referenced Jul 2, 2026
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.
Closes #2.
Freezes the shared
Intent/Decision/Policytypes + signer-daemon RPC as a standalone crate with an in-memoryMockSigner, so T-Agent / T-UX / the test harness can build and run the acceptance scenario before the real daemon exists. Zero key material.main— adaptations I madeIssue #2 describes a single
deckcrate (0BSD, crates.io GPUI).mainhas since: renameddeck→deckard, switched to AGPL-3.0, moved GPUI to Zed-git deps, and already introduced a workspace (root app +crates/deckard-core), plusDESIGN.md/specs/. So I implemented the issue's intent against today'smain, deviating from the literal text where it conflicts:main)deckdeckard(renaming it back would be the regression)deckard-core)git mv src → crates/deckard-appzeroizeIf you'd rather I hadn't moved the app / kept it literal, easy to adjust.
What's here
crates/deckard-contract(std + serde): frozenIntent(carrieschain_id, no nonce),IntentKind,Decision,Policy,ApprovalMode, and theSignerRequest/SignerResponse/ExecuteResult/ApprovalStatus/BalanceReportRPC enums. A syncSignertrait + a deterministicMockSigner(address0x11.., tx_hash0xAB.., request_ids0x01,0x02,..) implementing the full decision matrix incl. the TOCTOU revoke guard.default-members = deckard-appsocargo runstill launches the GUI;[profile.release]+[workspace.dependencies]at the root). App moved tocrates/deckard-appviagit mv(pure renames, history preserved).--workspace.docs/build/+docs/research/(the specs the contract README points at — they were untracked working-tree files). Droppable if another PR owns them.Acceptance criteria — all green (verified locally)
cargo build --workspace(1m02s) +cargo test --workspace→ 45 pass / 0 fail (contract 32, core 13, app 0).cargo runbuilds/launches the app (target/debug/deckard);just bundle→Deckard.appwithResources/icon.icnsfromcrates/deckard-app/assets/+CFBundleIconFileset.cargo tree -p deckard-contractnormal deps = onlyalloy-primitives+serde;ciborium/serde_jsonare dev-deps.serde_jsonandciborium(CBOR) byte-stably.MockSigner: Signer;Box<dyn Signer>usable.crates/deckard-contract/src(grep clean;repeat_byteconsts, no 64-hex literals).docs/build/30-mcp-shape.md— do not redefine these types elsewhere."Bundle fix worth a look (AC#2)
cargo-bundle 0.11 resolves icon paths against the CWD (not the manifest) and its PNG→icns converter rejects the 1024px
icon.png(No matching IconType). Sojust bundlenowcds intocrates/deckard-appand bundles the prebuilticon.icnsdirectly. (main'scargo bundle --releasefrom root would hit the same converter error — this actually fixes it.)Review
Cross-checked by codex (GPT-5) cross-model review + a 5-agent adversarial workflow. Both found one real latent bug — the
MockSignerrequest-id counter was au8withwrapping_add(256th proposal silently collided, defeating idempotency). Fixed: keep the spec-pinnedrepeat_byte(n)ids, tracklast_iddirectly, and panic loudly on exhaustion. Added boundary + within-cap-TOCTOU + exhaustion tests.Out of scope (separate tickets, untouched)
Real
deckard-signerdUDS impl ·deckard-mcpserver · Railgun calldata · Helios · GPUI approval card · keystore/daemon key handling.