Skip to main content

max / makenotwork

sando+bento: remediate ultra-fuzz Run 1 (CF1-5, serious, minors) Deploy-controller audit remediation across Sando, Bento, and shared ops-exec. Critical: tier-gate fail-closed + post-deploy gate runs; promote/rollback single-flight + atomic tier_state; atomic backup pull + pipefail/ON_ERROR_STOP restore; bearer-token auth on mutators (loopback-or-token bind); TUI panic terminal-restore guards. Serious: canary rollback of touched nodes; worktree HEAD validation; atomic symlink-swap-and-restart; Bento publish gated on supports()+step-success ledger and capability-scoped build hosts (no build-on-prod); 500->400 for unshipped targets; scp glob metachar-escaping; partial-deploy compensation surfaced via tier_state.partial_reason in /state + TUI. Minor: notarize JSON-parse / gatekeeper on-host sentinel; finalize_build backstop; publish non-empty-artifact guard; secret() per-component guard; manual_confirm freshness vs per-deploy clock; bounded log reads; tail() char-boundary; restore password via PGPASSWORD; agent /health pre-flight (Executor::preflight); TUI confirm modal + error-body surfacing.
Co-Authored-By
Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-06-12 21:29 UTC
Signed with PGP, not checked
Commit: bd8994851a0e0aa988b92097cd23481fe1d77f37
Parent: 722d138
31 files changed, +6251 insertions, -254 deletions
@@ -168,6 +168,7 @@
168 168 "metrics",
169 169 "metrics-exporter-prometheus",
170 170 "ops-core",
171 + "ops-exec",
171 172 "reqwest",
172 173 "rhai",
173 174 "semver",
@@ -552,6 +553,17 @@
552 553 source = "registry+https://github.com/rust-lang/crates.io-index"
553 554 checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
554 555
556 + [[package]]
557 + name = "futures-macro"
558 + version = "0.3.32"
559 + source = "registry+https://github.com/rust-lang/crates.io-index"
560 + checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
561 + dependencies = [
562 + "proc-macro2",
563 + "quote",
564 + "syn",
565 + ]
566 +
555 567 [[package]]
556 568 name = "futures-sink"
557 569 version = "0.3.32"
@@ -572,6 +584,7 @@
572 584 dependencies = [
573 585 "futures-core",
574 586 "futures-io",
587 + "futures-macro",
575 588 "futures-sink",
576 589 "futures-task",
577 590 "memchr",
@@ -1288,7 +1301,10 @@
1288 1301 dependencies = [
1289 1302 "anyhow",
1290 1303 "async-trait",
1304 + "futures-util",
1305 + "reqwest",
1291 1306 "serde",
1307 + "serde_json",
1292 1308 "thiserror",
1293 1309 "tokio",
1294 1310 "tracing",
@@ -1641,6 +1657,7 @@
1641 1657 "base64",
1642 1658 "bytes",
1643 1659 "futures-core",
1660 + "futures-util",
1644 1661 "http",
1645 1662 "http-body",
1646 1663 "http-body-util",
@@ -1660,12 +1677,14 @@
1660 1677 "sync_wrapper",
1661 1678 "tokio",
1662 1679 "tokio-rustls",
1680 + "tokio-util",
1663 1681 "tower",
1664 1682 "tower-http",
1665 1683 "tower-service",
1666 1684 "url",
1667 1685 "wasm-bindgen",
1668 1686 "wasm-bindgen-futures",
1687 + "wasm-streams",
1669 1688 "web-sys",
1670 1689 "webpki-roots",
1671 1690 ]
@@ -2414,6 +2433,19 @@
2414 2433 "tungstenite",
2415 2434 ]
2416 2435
2436 + [[package]]
2437 + name = "tokio-util"
2438 + version = "0.7.18"
2439 + source = "registry+https://github.com/rust-lang/crates.io-index"
2440 + checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
2441 + dependencies = [
2442 + "bytes",
2443 + "futures-core",
2444 + "futures-sink",
2445 + "pin-project-lite",
2446 + "tokio",
2447 + ]
2448 +
2417 2449 [[package]]
2418 2450 name = "toml"
2419 2451 version = "0.8.23"
@@ -2795,6 +2827,19 @@
2795 2827 "wasmparser",
2796 2828 ]
2797 2829
2830 + [[package]]
2831 + name = "wasm-streams"
2832 + version = "0.4.2"
2833 + source = "registry+https://github.com/rust-lang/crates.io-index"
2834 + checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
2835 + dependencies = [
2836 + "futures-util",
2837 + "js-sys",
2838 + "wasm-bindgen",
2839 + "wasm-bindgen-futures",
2840 + "web-sys",
2841 + ]
2842 +
2798 2843 [[package]]
2799 2844 name = "wasmparser"
2800 2845 version = "0.244.0"
@@ -10,6 +10,7 @@
10 10
11 11 [dependencies]
12 12 ops-core = { path = "../../shared/ops-core" }
13 + ops-exec = { path = "../../shared/ops-exec", features = ["rpc"] }
13 14 axum = { version = "0.8.8", features = ["macros", "ws"] }
14 15 tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread", "net", "signal", "fs", "process", "sync"] }
15 16 serde = { version = "1.0.228", features = ["derive"] }
@@ -3,7 +3,7 @@
3 3 version = "0.1.0"
4 4 edition = "2024"
5 5 license = "MIT"
6 - description = "Thin agent-driven release driver: runs the proven macOS recipe (build -> sign -> notarize -> staple -> verify) on a build host via the ops-exec executor, then pulls the artifact. The full bentod/TUI orchestrator is deferred (launchplan §J)."
6 + description = "Thin agent-driven release driver: runs the proven macOS recipe (build -> sign -> notarize -> staple -> verify) on a build host via the ops-exec executor, then pulls the artifact. A focused one-shot path; bentod (daemon + TUI) now runs the same recipes through the same ops-exec executors, including AgentRpc for the in-session macOS sign steps."
7 7
8 8 [[bin]]
9 9 name = "bento-release-macos"
@@ -209,10 +209,17 @@
209 209 install -m 0644 -o root -g root \
210 210 "$SANDO_REPO/sando.toml" \
211 211 /etc/sando/sando.toml
212 - # sando.env carries non-secret operator settings consumed by sandod and the
213 - # backup-fetch timer. Only write if missing — operator may have customized.
212 + # sando.env carries operator settings AND the deploy-API bearer token consumed
213 + # by sandod, the post-receive hook, and the backup-fetch timer. A token is
214 + # generated per host so a fresh install is authenticated by default — required
215 + # once the daemon binds a non-loopback address (it refuses to start otherwise).
216 + # 0640 root:sando keeps it readable by the daemon + hook, not world. Only write
217 + # if missing — operator may have customized.
214 218 if [[ ! -f /etc/sando/sando.env ]]; then
215 - echo "SANDO_DAEMON=$SANDO_DAEMON_URL" > /etc/sando/sando.env
219 + {
220 + echo "SANDO_DAEMON=$SANDO_DAEMON_URL"
221 + echo "SANDO_API_TOKEN=$(openssl rand -hex 32)"
222 + } > /etc/sando/sando.env
216 223 chown root:"$SANDO_USER" /etc/sando/sando.env
217 224 chmod 0640 /etc/sando/sando.env
218 225 fi