Skip to content

Agentic engineering: Tier 2 / Tier 3 backlog (lints, test runner, supply-chain, errors) #7

Description

@hellno

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:80results[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 jobcargo +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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions