~200 lines of Rust. Every command: AC → exec → CR → CID. Usage: gsh --exec "echo hello" gsh --exec "hcloud server list" --json gsh --exec "ansible-playbook site.yml" --dry-run Flow: 1. SHA-256 hash the command 2. POST /governance/authorize/ → AC ID 3. exec(sh, -c, command) → capture stdout/stderr/exit 4. POST /governance/complete/ → receipt + Chronicle CID 5. Print stdout (passthrough) or JSON (structured) 6. Exit with command's exit code Environment: GSAP_BROKER_URL http://fastapi-gsap:8000 GSAP_AGENT_DID did:web:bxnet.../agent/platform-ops GSAP_TOKEN Bearer token (optional) GSAP_CORPUS_CID sha256:{image_digest} (optional) Tested against live fastapi-gsap Spoke broker on Hetzner: dry-run: AC only ✓ live exec: stdout passthrough + CID ✓ JSON mode: ac_id + cr_id + chronicle_cid ✓ exit code: 42 passed through ✓ The command_hash in the AC request means the broker knows WHAT will be executed before authorizing. Not just "was this agent allowed" but "was this exact command authorized." Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
20 lines
467 B
TOML
20 lines
467 B
TOML
[package]
|
|
name = "gsh"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
description = "Governed shell — GCAP-SPEC-SHELLBOUND-SDK-0001"
|
|
|
|
[[bin]]
|
|
name = "gsh"
|
|
path = "src/main.rs"
|
|
|
|
[dependencies]
|
|
reqwest = { version = "0.12", features = ["json", "blocking"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
clap = { version = "4", features = ["derive"] }
|
|
sha2 = "0.10"
|
|
hex = "0.4"
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
anyhow = "1"
|
|
chrono = "0.4"
|