assay-cli 6.2.0

Policy-as-code gate for MCP agent tool calls, with verifiable evidence and Linux kernel enforcement.
[package]
name = "assay-cli"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
readme = "README.md"
description = "Policy-as-code gate for MCP agent tool calls, with verifiable evidence and Linux kernel enforcement."
keywords = ["mcp", "ai-agents", "agent-security", "policy-as-code", "evidence"]
categories = ["command-line-utilities", "development-tools::testing"]
# Kept out of the published tarball because it reaches outside this package: it includes
# `crates/assay-mcp-server/tests/jsonrpc_conn/mod.rs` by `#[path]`, and `cargo package` copies only
# this package's files. Shipping it would put a test target in the crate that cannot compile at all
# — `couldn't read tests/../../assay-mcp-server/...` — which is worse than its absence for anyone
# running `cargo test` on the crates.io source (distro packagers, `cargo vendor` consumers). It
# could never run from a tarball anyway: it shells out to `cargo build -p assay-mcp-server`, which
# needs the workspace. `cargo publish`'s own verification builds lib and bins only, so this was not
# a release blocker either way — it is the downstream `cargo test` that this protects.
exclude = [
    "tests/e2e_mcp_wrap_assert_cmd.rs",
    "tests/mcp_wrap_authorize_forward.rs",
    # Workspace-only contract: reads generated docs and shared test support outside this package.
    "tests/agent_golden_path_contract.rs",
    # Workspace-only contract: imports shared test support outside this package.
    "tests/agent_plugin_package_contract.rs",
    # Workspace-only contracts: use the shared bounded-process helper outside this package.
    "tests/policy_validate_machine_contract.rs",
    "tests/config_recovery_argv_contract.rs",
    "tests/explicit_config_class_contract.rs",
    "tests/doctor_config_check_contract.rs",
    "tests/init_stdout_contract.rs",
    "tests/doctor_exit_class_contract.rs",
    "tests/doctor_argument_contract.rs",
    "tests/doctor_text_render_contract.rs",
    "tests/cli_describe_contract.rs",
    "tests/stdout_json_write_contract.rs",
    "tests/evidence_verify_attestation_cli.rs",
    "tests/mcp_preflight_contract.rs",
    "tests/recovery_argv_publisher_parity.rs",
]

[lints]
workspace = true

[[bin]]
name = "assay"
path = "src/main.rs"

[features]
default = ["tui", "sim", "runner"]
experimental = ["assay-core/experimental"]
profile-test-hook = []
tui = ["dep:ratatui", "dep:crossterm"]
sim = ["dep:assay-sim"]
# Internal Assay-Runner Phase 1 spike command (`assay runner-spike`).
# Gated behind a feature because the underlying `assay-runner-{core,schema,linux}`
# crates are `publish = false`; cargo publish of `assay-cli` must therefore use
# `--no-default-features --features tui,sim` so the optional runner deps are not
# required to resolve from crates.io. Workspace builds and binary releases keep
# the default features (`runner` included) so behaviour for repo/CI consumers is
# unchanged from v3.11.0.
runner = [
    "dep:assay-runner-core",
    "dep:assay-runner-schema",
    "dep:assay-runner-linux",
]

[dependencies]
anyhow.workspace = true
async-trait.workspace = true
serde = { workspace = true, features = ["std"] }
serde_json = { workspace = true, features = ["std"] }
jsonschema = { workspace = true }
clap.workspace = true
tracing.workspace = true
env_logger = "0.11"
tokio.workspace = true

# Internal (Inherited from workspace)
assay-canonical = { workspace = true }
assay-core.workspace = true
assay-monitor.workspace = true
assay-common = { workspace = true, features = ["std"] }
assay-policy = { workspace = true }
assay-metrics = { workspace = true }
assay-evidence = { workspace = true }
assay-registry = { workspace = true }
assay-mcp-server = { workspace = true }
assay-runner-core = { workspace = true, optional = true }
assay-runner-schema = { workspace = true, optional = true }
assay-runner-linux = { workspace = true, optional = true }
assay-sim = { workspace = true, optional = true }

dialoguer = "0.12"
similar = "3"
serde_yaml.workspace = true
chrono = { workspace = true, features = ["std", "clock"] }
sha2 = { workspace = true }
hex = { workspace = true }
dirs = "6.0"

# Tool signing
ed25519-dalek = { version = "3.0", features = ["pkcs8", "pem", "rand_core"] }
getrandom = { version = "0.4", features = ["sys_rng"] }
rand = "0.8"
pkcs8 = { version = "0.11", features = ["pem"] }
base64 = "0.22"
sysinfo = "0.30"
humantime = "2"
tokio-stream = "0.1"
futures = "0.3"
globset = "0.4"
libc = "0.2"
semver = "1"
once_cell = "1.21"
nix = { version = "0.27", features = ["signal", "process", "fs", "ioctl"] }
ratatui = { workspace = true, optional = true }
crossterm = { workspace = true, optional = true }

[target.'cfg(target_os = "linux")'.dependencies]
landlock = "=0.4.7"



[[bench]]
name = "suite_run_worstcase"
path = "benches/suite_run_worstcase.rs"
harness = false

[[bench]]
name = "profile_store_harness"
path = "benches/profile_store_harness.rs"
harness = false

[dev-dependencies]
tempfile = "3"
regex = "1"
assert_cmd = "2.2.2"
predicates = "3.1.4"
proptest = "1.10"
serial_test = "3.5.0"
criterion = "0.8"
flate2 = { workspace = true }
tar = { workspace = true }

[target.'cfg(unix)'.dev-dependencies]
process-wrap = { workspace = true, features = ["process-group", "std"] }

[target.'cfg(windows)'.dev-dependencies]
process-wrap = { workspace = true, features = ["job-object", "std"] }