Context
Tier 1 of the agentic-engineering hardening has landed (lint policy in the manifest, clippy.toml,
rustfmt.toml, deny.toml + cargo-deny CI, #![forbid(unsafe_code)] on deckard-core, closed CI
gaps, CLAUDE.md/AGENTS.md). The full rationale and the deliberately-rejected rules are in
docs/AGENTIC-ENGINEERING.md.
This issue tracks the Tier 2 / Tier 3 backlog. Each item was researched against paradigm Rust
repos (reth, alloy, Zed) and adversarially challenged by a cross-model (codex GPT-5.5) review —
that verdict is recorded per item below.
⭐ Promoted to "do now" (highest leverage)
Both models rank these above the rest because they harden the wallet engine and make the Tier-1
unused_must_use = "deny" actually bite.
1. Restriction lints in deckard-core
Clippy rules that make the security engine's production code unable to .unwrap() / panic! on
bad input (tests still unwrap freely, via the allow-*-in-tests keys already in clippy.toml).
Two paths — pick one:
- Safe (zero code change, lands green):
# crates/deckard-core — via lib.rs inner attrs or a non-workspace [lints] block
unwrap_used = "deny" # clean: all real unwraps are in #[cfg(test)]
get_unwrap = "deny"
mem_forget = "deny"
expect_used = "allow" # 2 non-test expects in eth.rs
panic = "allow"
indexing_slicing = "allow"
- Hardened (codex-preferred, ~3 small edits): also
deny expect_used / panic /
indexing_slicing, and fix the real sites rather than blanket-allow — those sites (the keystore
byte-parser + RPC decode) are exactly where future agent-written indexing should be reviewed:
eth.rs:48 / eth.rs:97 — startup expect()s → documented fatal boundary or fallible spawn.
keystore.rs Reader (~492–505) — raw slice indexing → bounds-checked .get() + explicit error.
balances.rs:80 — results[0] → .first().ok_or(...)?.
codex verdict: MODIFY → PROMOTE. "Promote the corrected core lint set now, with expect_used,
panic, and indexing_slicing denied and the current indexing/expect sites fixed rather than exempted."
2. #[must_use] audit on secret types
Tag the secret-bearing types/methods so the compiler errors if a caller creates one and ignores it:
Vault, UnlockedVault, Vault::unlock, account_signer, account_address, primary_address,
reveal_phrase.
codex verdict: PROMOTE. Low churn, directly useful; unused_must_use = deny only fully bites
once these are annotated.
Tier 2 — high value, some effort
3. cargo-nextest
A faster, nicer test runner than cargo test (parallel, clear per-test output, per-test timeouts).
Add .config/nextest.toml, install via a pinned taiki-e/install-action, run
cargo nextest run --locked --workspace; keep a separate cargo test --locked --doc (nextest skips
doctests).
codex verdict: MODIFY — use retries = 0, NOT 2. Retries normalize flaky security tests,
which is dangerous for a wallet. fail-fast = false. Pin the install action version.
4. profile.dev tuning (faster debug crypto)
Make debug builds optimize the slow crypto so wallet create/unlock and tests aren't painful at
opt-level = 0.
codex verdict: MODIFY — do NOT optimize all deps (opt-level=2 for * slows the first
gpui/alloy compile and the agent feedback loop). Target just the crypto crates:
[profile.dev.package.argon2]
opt-level = 3
[profile.dev.package.blake2]
opt-level = 3
Drop [profile.dev.build-override] unless measured.
5. Dependency + spelling hygiene
cargo-machete — find unused dependencies. Start manual / non-blocking: it false-positives the
cfg-gated objc2* + gpui-component-assets, but it correctly flags that the app's root
Cargo.toml lists alloy-signer-local / alloy-primitives as direct deps it may not use directly
(they're re-exported from deckard-core) — worth investigating.
typos (crate-ci) in CI with a crypto-jargon allow-list + extend-exclude = ["Cargo.lock"].
lefthook pre-commit hooks (fmt/clippy/typos) — local convenience only, NOT a CI gate (agents
bypass with --no-verify; CI is the real gate).
codex verdict: MODIFY/SPLIT (as above).
6. Doctests + rustdoc warnings
RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps -p deckard-core
cargo test --locked --doc -p deckard-core
Catches broken intra-doc links and ensures any future doc examples compile.
codex verdict: KEEP — sensible, not urgent (no doc examples exist yet).
Tier 3 — revisit later
- Typed errors (
thiserror) for the keystore. Structured errors instead of anyhow.
codex verdict: MODIFY, do LAST. ⚠️ Keep one opaque UnlockFailed — distinguishing
"wrong passphrase" vs "tampered" is an attacker oracle (surfaced via short_err in
shell.rs). Only the keystore; keep network/provider errors as anyhow until there's real
programmatic handling.
- proptest round-trips for the keystore binary format (
to_bytes/from_bytes, wrong-passphrase
rejection). Reuse the existing KdfParams::FAST_TEST profile.
- MSRV / toolchain-drift CI job —
cargo +1.95.0 build --locked + rust-version = "1.95.0" in
both manifests, to catch a bump-gpui that silently needs a newer compiler.
- Automated monthly
bump-gpui PR bot + Dependabot for the registry deps (serde, alloy,
argon2, tray-icon); Dependabot/Renovate handle git deps poorly.
- Scheduled
cargo-audit cron (decouples the advisory time-signal from PR CI).
merge_group + a required aggregated check for branch protection (one-time repo-admin action).
- cargo-vet / cargo-semver-checks / coverage gates — deferred (heavy / premature for a pre-1.0 app
with no external consumer).
Deliberately NOT recommended
See the table in docs/AGENTIC-ENGINEERING.md:
forbid(unsafe_code) at the workspace root, clippy::pedantic/nursery/full restriction,
indexing_slicing = deny workspace-wide, edition 2024, nightly rustfmt/build flags, panic = abort,
multiple-versions = deny, mold/lld linker config (1.95 already defaults to the fast linkers).
Context
Tier 1 of the agentic-engineering hardening has landed (lint policy in the manifest,
clippy.toml,rustfmt.toml,deny.toml+ cargo-deny CI,#![forbid(unsafe_code)]ondeckard-core, closed CIgaps,
CLAUDE.md/AGENTS.md). The full rationale and the deliberately-rejected rules are indocs/AGENTIC-ENGINEERING.md.This issue tracks the Tier 2 / Tier 3 backlog. Each item was researched against paradigm Rust
repos (reth, alloy, Zed) and adversarially challenged by a cross-model (codex GPT-5.5) review —
that verdict is recorded per item below.
⭐ Promoted to "do now" (highest leverage)
Both models rank these above the rest because they harden the wallet engine and make the Tier-1
unused_must_use = "deny"actually bite.1. Restriction lints in
deckard-coreClippy rules that make the security engine's production code unable to
.unwrap()/panic!onbad input (tests still unwrap freely, via the
allow-*-in-testskeys already inclippy.toml).Two paths — pick one:
denyexpect_used/panic/indexing_slicing, and fix the real sites rather than blanket-allow — those sites (the keystorebyte-parser + RPC decode) are exactly where future agent-written indexing should be reviewed:
eth.rs:48/eth.rs:97— startupexpect()s → documented fatal boundary or fallible spawn.keystore.rsReader(~492–505) — raw slice indexing → bounds-checked.get()+ explicit error.balances.rs:80—results[0]→.first().ok_or(...)?.2.
#[must_use]audit on secret typesTag the secret-bearing types/methods so the compiler errors if a caller creates one and ignores it:
Vault,UnlockedVault,Vault::unlock,account_signer,account_address,primary_address,reveal_phrase.Tier 2 — high value, some effort
3. cargo-nextest
A faster, nicer test runner than
cargo test(parallel, clear per-test output, per-test timeouts).Add
.config/nextest.toml, install via a pinnedtaiki-e/install-action, runcargo nextest run --locked --workspace; keep a separatecargo test --locked --doc(nextest skipsdoctests).
4.
profile.devtuning (faster debug crypto)Make debug builds optimize the slow crypto so wallet create/unlock and tests aren't painful at
opt-level = 0.5. Dependency + spelling hygiene
cargo-machete— find unused dependencies. Start manual / non-blocking: it false-positives thecfg-gated
objc2*+gpui-component-assets, but it correctly flags that the app's rootCargo.tomllistsalloy-signer-local/alloy-primitivesas direct deps it may not use directly(they're re-exported from
deckard-core) — worth investigating.typos(crate-ci) in CI with a crypto-jargon allow-list +extend-exclude = ["Cargo.lock"].lefthookpre-commit hooks (fmt/clippy/typos) — local convenience only, NOT a CI gate (agentsbypass with
--no-verify; CI is the real gate).6. Doctests + rustdoc warnings
Catches broken intra-doc links and ensures any future doc examples compile.
Tier 3 — revisit later
thiserror) for the keystore. Structured errors instead ofanyhow.to_bytes/from_bytes, wrong-passphraserejection). Reuse the existing
KdfParams::FAST_TESTprofile.cargo +1.95.0 build --locked+rust-version = "1.95.0"inboth manifests, to catch a
bump-gpuithat silently needs a newer compiler.bump-gpuiPR bot + Dependabot for the registry deps (serde, alloy,argon2, tray-icon); Dependabot/Renovate handle git deps poorly.
cargo-auditcron (decouples the advisory time-signal from PR CI).merge_group+ a required aggregated check for branch protection (one-time repo-admin action).with no external consumer).
Deliberately NOT recommended
See the table in
docs/AGENTIC-ENGINEERING.md:forbid(unsafe_code)at the workspace root,clippy::pedantic/nursery/fullrestriction,indexing_slicing = denyworkspace-wide, edition 2024, nightly rustfmt/build flags,panic = abort,multiple-versions = deny, mold/lld linker config (1.95 already defaults to the fast linkers).