Files
nanny/Cargo.toml
T
grenadeandClaude Opus 5 7ff8f5c8fa feat: watch local agent harnesses for leaked credentials
nanny scans the stores that claude-code, opencode and pi write — session
transcripts, agent memories, cached pastes, shell snapshots, tool output,
opencode's SQLite database — plus shell history and repository working
trees, and records where and when a credential leaked into them.

Detection is by shape alone. nanny deliberately has no read access to any
credential store (~/.agents, ~/.ssh, each harness's own auth file), so the
monitor is not itself a process worth compromising. The cost is false
positives, managed with per-rule confidence, entropy floors and allow
patterns.

The central invariant is that a matched secret never leaves the scanner:
Secret<'a> borrows, does not clone into an owned form, does not serialise,
and Debugs as <redacted, N bytes>. What is stored is a salted keyed hash, a
length, and a preview with every matched span masked — so nanny's own
database cannot become the next spill.

Records and alerts only; it never edits a harness's files. Rules carry a
RotationHint as the seam for optional rotation later.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAqHWfdMAsYu1o36tgeima
2026-09-02 15:11:53 +03:00

61 lines
1.5 KiB
TOML

[workspace]
resolver = "3"
members = ["crates/nanny-entities", "crates/nanny-core", "crates/nanny-data", "crates/nanny-daemon", "crates/nanny-cli"]
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
license = "GPL-3.0-or-later"
authors = ["Rob Thijssen <rob@thijssen.email>"]
repository = "https://git.lair.cafe/grenade/nanny"
[workspace.dependencies]
# internal
nanny-entities = { path = "crates/nanny-entities", version = "=0.1.0" }
nanny-core = { path = "crates/nanny-core", version = "=0.1.0" }
nanny-data = { path = "crates/nanny-data", version = "=0.1.0" }
# runtime
tokio = { version = "1", features = ["full"] }
async-trait = "0.1"
futures = "0.3"
# types / serialisation
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"
time = { version = "0.3", features = ["serde-well-known", "macros", "formatting", "parsing", "local-offset"] }
# errors
thiserror = "2"
anyhow = "1"
# detection
regex = "1"
memchr = "2"
blake3 = "1"
ignore = "0.4"
globset = "0.4"
# persistence
sqlx = { version = "0.8", default-features = false, features = ["sqlite", "runtime-tokio-rustls", "macros", "migrate", "time"] }
# filesystem watching
notify = "8"
notify-debouncer-full = "0.5"
# config
figment = { version = "0.10", features = ["toml", "env"] }
directories = "6"
# observability
tracing = "0.1"
tempfile = "3"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
# binaries
clap = { version = "4", features = ["derive", "env"] }
ratatui = "0.29"
notify-rust = "4"