#!/usr/bin/env bash
# converting-demo.sh — the 90-second "verify, don't trust" demo.
#
# Four beats: clean attests · OpenClaw bypass refused · FORGED verdict caught ·
# CI gate. The money beat is #3 — an independent recompute catches a forged
# claim that a *signed log* would wave through. That is the line between
# "we have receipts too" and verifiable evidence.
#
# Runs against the PUBLISHED package by default (the real install story):
#   bash examples/converting-demo.sh
# Use the local build instead (no network):
#   pnpm build && LOCAL=1 bash examples/converting-demo.sh
# Pacing for screen-recording (pause between beats):
#   PAUSE=1 bash examples/converting-demo.sh
#
# Requires: node, and (default mode) npx with network. Trace fixtures are the
# real output of crates/nucleus-policy/examples/emit_toolproxy_trace.rs.

set -u
HERE="$(cd "$(dirname "$0")" && pwd)"
CLEAN_TRACE="$HERE/sample-toolproxy-trace.clean.json"
# Beat 2 uses the OpenClaw impersonation trace (principal mismatch under an
# allowlisted display name). sample-toolproxy-trace.bypass.json (a tool-not-
# allowed git_push) is the other refusal mode, gated by verify-gate.yml.
BYPASS_TRACE="$HERE/sample-toolproxy-trace.openclaw.json"
PRINCIPAL="spiffe://acme.example/agent/billing-assistant"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

if [ "${LOCAL:-0}" = "1" ]; then
  DIST="$HERE/../dist"
  ATTEST=(node "$DIST/producer-cli.js")
  VERIFY=(node "$DIST/cli.js")
  SRC="local build ($DIST)"
else
  PKG="@coproduct_inc/verify@${VERIFY_VERSION:-latest}"
  ATTEST=(npx --yes -p "$PKG" nucleus-attest)
  VERIFY=(npx --yes -p "$PKG" nucleus-verify)
  SRC="published npm package $PKG"
fi

bold() { printf "\033[1m%s\033[0m\n" "$*"; }
dim()  { printf "\033[2m%s\033[0m\n" "$*"; }
ok()   { printf "\033[32m%s\033[0m\n" "$*"; }
bad()  { printf "\033[31m%s\033[0m\n" "$*"; }
beat() { echo; bold "── $* ──"; [ "${PAUSE:-0}" = "1" ] && read -r -p "  (enter)…" _ || true; }

echo
bold "@coproduct_inc/verify — verify, don't trust"
dim  "source: $SRC"
dim  "An agent run's tool-call trace + a declared capability boundary →"
dim  "a signed, OFFLINE-verifiable in-bounds attestation. We don't trust the"
dim  "issuer's verdict — we recompute it."

# ── Beat 1: a clean run attests ──────────────────────────────────────────────
beat "1/4  Clean run → ATTESTS (exit 0)"
dim "nucleus-attest < clean-trace  →  nucleus-verify"
"${ATTEST[@]}" "$CLEAN_TRACE" > "$TMP/clean.json" 2> "$TMP/clean.err"
if "${VERIFY[@]}" "$TMP/clean.json" --expect-principal "$PRINCIPAL"; then
  ok "  → exit 0. Auditor-grade evidence the agent stayed inside its boundary."
else
  bad "  unexpected: clean run did not verify"; exit 1
fi

# ── Beat 2: the OpenClaw bypass is refused ───────────────────────────────────
beat "2/4  OpenClaw bypass (display-name match, principal mismatch) → REFUSED (exit 1)"
dim "An injected call wears the allowlisted display name but a different SPIFFE id."
"${ATTEST[@]}" "$BYPASS_TRACE" > "$TMP/bypass.json" 2> "$TMP/bypass.err"
if "${VERIFY[@]}" "$TMP/bypass.json"; then
  bad "  unexpected: bypass verified (should refuse)"; exit 1
else
  ok "  → exit 1. CVE-2026-25253's failure class, ruled out by construction"
  ok "    (the boundary is keyed on the cryptographic principal, never the name)."
fi

# ── Beat 3: the money beat — a forged verdict is caught ───────────────────────
beat "3/4  FORGE the verdict (claim inBounds:true) → CAUGHT"
dim "A signed LOG would trust this. We recompute the verdict independently."
node -e '
  const fs = require("fs");
  const r = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
  r.verdict.inBounds = true;
  r.verdict.events = r.verdict.events.map(e => ({...e, inBounds:true, code:"ok", detail:"in bounds"}));
  fs.writeFileSync(process.argv[2], JSON.stringify(r));
' "$TMP/bypass.json" "$TMP/forged.json"
"${VERIFY[@]}" "$TMP/forged.json" --json > "$TMP/forged.report.json" 2>/dev/null || true
SIG=$(node -e 'console.log(require(process.argv[1]).signatureOk)' "$TMP/forged.report.json")
CONS=$(node -e 'console.log(require(process.argv[1]).verdictConsistentOk)' "$TMP/forged.report.json")
OKV=$(node -e 'console.log(require(process.argv[1]).ok)' "$TMP/forged.report.json")
echo "  signatureOk=$SIG  verdictConsistentOk=$CONS  ok=$OKV"
if [ "$OKV" = "false" ] && [ "$CONS" = "false" ]; then
  ok "  → REJECTED two independent ways: the recompute disagrees with the claim,"
  ok "    AND the signature (taken over the honest verdict) no longer verifies."
  ok "    THIS is verifiable evidence, not a signed log you have to trust."
else
  bad "  unexpected: forged receipt was not caught"; exit 1
fi

# ── Beat 4: it's a CI merge gate, not a dashboard ────────────────────────────
beat "4/4  It's a merge gate, not a dashboard"
dim "Drop the Action in a PR; an out-of-bounds run fails the build:"
cat <<'YAML'
  - uses: coproduct-private/spiffy/packages/nucleus-verify@main
    with:
      receipt: ./agent-run-receipt.json
      expect-principal: spiffe://acme/agent/billing-assistant
YAML
ok "  clean → check passes · out-of-bounds → check fails. Exit codes are the gate."

echo
bold "Summary"
echo "  • Works above ANY runtime/guardrail (incl. Microsoft AGT) — neutral verifier."
echo "  • Offline, zero runtime deps (node:crypto). 30-second npx drop-in."
echo "  • The verdict logic is backed by machine-checked theorems (IFC noninterference)."
echo "  • Honest scope: attests the DECLARED boundary over the OBSERVED trace —"
echo "    completeness of trace capture is the runtime's job."
ok "DEMO OK ✓"
