diff --git a/README.md b/README.md index a20d36d..84f3e43 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,16 @@ model's behavior: see what each result means, and the detection ceiling, below. *Socair* (SUH-ker) is Irish for "at ease, settled, secure". +

+ A terminal session. A repository shaped like the October 2026 Hugging Face miner campaign is scanned: promotion withheld, with a Remote code LEAD naming the module its config tells the loader to import. Qwen/Qwen3-0.6B is pulled through the airlock at a pinned commit and scanned: every row PASS, promotion authorized. Both reports are signed with an operator key. The airlock refuses the first, promotes the second into the clean store, and the attestation verifies offline. +

+ +*Two models through the same intake. The withheld one is the detection +benchmark's defanged copy of the campaign's layout: its stand-in payload only +builds a string. Recorded at v0.1.0-rc.8 with +[scripts/record-demo.sh](scripts/record-demo.sh); the 1.5 GB download is +shortened.* + ## What it checks Each check returns **PASS**, **FAIL**, **LEAD**, or **NOT_TESTED**: diff --git a/docs/demo/intake.gif b/docs/demo/intake.gif new file mode 100644 index 0000000..37b2a68 Binary files /dev/null and b/docs/demo/intake.gif differ diff --git a/scripts/record-demo.sh b/scripts/record-demo.sh new file mode 100755 index 0000000..da51945 --- /dev/null +++ b/scripts/record-demo.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# Record the README's terminal demo as a GIF. +# +# scripts/record-demo.sh [] (default docs/demo/intake.gif) +# +# Two models go through the same intake: +# qwen2-tiny the detection benchmark's dir-remote-code-tiny-qwen2 +# case, shaped like the October 2026 Hugging Face miner +# campaign: a repo posing as a tiny Qwen2 checkpoint whose +# auto_map names a module that runs at import. Defanged: +# its stand-in payload only builds a string. The benchmark +# test writes it (SOCAIR_BENCHMARK_CORPUS), so the demo +# scans the benchmark's own bytes. +# Qwen/Qwen3-0.6B pulled through the airlock at a pinned commit (about +# 1.5 GB, the only network use). +# Both reports are signed with a fresh demo key; the first is refused at +# promotion, the second is promoted and verified. +# +# Needs go, jq, asciinema 3, and agg. Everything else lands in a temp dir. +# The recording caps idle time at 4 seconds, so the download is shortened. +# SOCAIR_DEMO_FONT_DIR points agg at a font directory (the GIF in the repo +# uses JetBrains Mono). +set -euo pipefail + +revision=c1899de289a04d12100db370d81485cdf75e47ca +digest=fbb2e51d2156914d13091c694e8ac226bedc3022c587f31f72ca8831304fb199 + +# The recorded commands are shown as typed, $D included; eval expands them. +# shellcheck disable=SC2016 +if [ "${1:-}" = "--play" ]; then + # The recorded session: runs in the work dir, with socair on PATH. + say() { + printf '\033[90m# %s\033[0m\n' "$@" + sleep 1.5 + } + run() { + local cmd=$1 pause=${2:-1.5} i + printf '\033[32m$\033[0m ' + for ((i = 0; i < ${#cmd}; i++)); do + printf '%s' "${cmd:i:1}" + sleep 0.015 + done + sleep 0.5 + printf '\n' + eval "$cmd" || true + sleep "$pause" + } + cls() { printf '\033[2J\033[H'; } + + cls + say "A repo shaped like the October 2026 Hugging Face miner campaign: it poses as a tiny" \ + "Qwen2 checkpoint, and its config tells the loader to import its Python. Defanged, from" \ + "Socair's detection benchmark." + run 'ls qwen2-tiny' + run 'socair scan qwen2-tiny > tiny.json' 3 + run "jq -r '.checks[] | select(.status == \"LEAD\") | .evidence' tiny.json" 4 + + cls + say "A real model, pulled through the airlock at a pinned commit." + run "socair airlock pull --repo Qwen/Qwen3-0.6B --revision $revision" 3 + run "D=$digest" 0.5 + run 'SOCAIR_PROVENANCE=airlock/incoming/$D/provenance.json socair scan airlock/incoming/$D/Qwen3-0.6B > qwen.json' 0.5 + run "jq -r '(.checks[] | \"\\(.status) \\(.name)\"), \"promotion: \\(.promotion_authorization.state)\"' qwen.json" 4 + + cls + say "Sign both reports with your own key, and trust it at the airlock." + run 'socair key gen --out operator --issuer "Acme ML Platform" && socair airlock trust add operator.pub' 1 + run 'socair sign --key operator.key --report tiny.json && socair sign --key operator.key --report qwen.json' 2 + + cls + say "Promote both. Only one crosses into the clean store, and anyone can verify it offline." + run 'socair airlock promote qwen2-tiny --attestation tiny.dsse.json' 4 + run 'socair airlock promote airlock/incoming/$D/Qwen3-0.6B --attestation qwen.dsse.json' 2 + run 'socair verify qwen.dsse.json --trusted operator.pub --artifact airlock/clean/$D/Qwen3-0.6B' 3 + exit 0 +fi + +root=$(cd "$(dirname "$0")/.." && pwd) +out=${1:-$root/docs/demo/intake.gif} +case "$out" in /*) ;; *) out=$PWD/$out ;; esac +for tool in go jq asciinema agg; do + command -v "$tool" >/dev/null || { echo "record-demo: $tool is required" >&2; exit 1; } +done + +work=$(mktemp -d) +trap 'rm -rf "$work"' EXIT +mkdir -p "$work/bin" "$work/demo" +(cd "$root" && go build -o "$work/bin/socair" ./cmd/socair) +(cd "$root" && SOCAIR_BENCHMARK_CORPUS="$work/corpus" go test ./internal/benchmark -run '^TestDetectionBenchmark$' -count=1 >/dev/null) +cp -R "$work/corpus/dir-remote-code-tiny-qwen2/model" "$work/demo/qwen2-tiny" + +cd "$work/demo" +export PATH="$work/bin:$PATH" SOCAIR_STORE=airlock +socair airlock init >/dev/null +asciinema rec --quiet --headless --window-size 100x26 --idle-time-limit 4 \ + -c "bash $root/scripts/record-demo.sh --play" "$work/demo.cast" + +# The demo must show what its caption says. The cast's output events, joined, +# are the session's output stream. +tail -n +2 "$work/demo.cast" | jq -j 'select(.[1] == "o") | .[2]' > "$work/demo.out" +for want in 'promotion: withheld' 'imported with trust_remote_code' 'promotion: authorized' \ + 'promotion refused' "promoted $digest" 'verified: issued by Acme ML Platform'; do + grep -qF "$want" "$work/demo.out" || { echo "record-demo: the recording does not show: $want" >&2; exit 1; } +done + +theme=0f2333,e7eef1,0b1a26,f2877a,4cd3ae,e9b65a,7fb3e0,c9a0dc,7fd6d0,e7eef1,8fa3af,f6a499,6ee0c0,f0c97e,9cc6ea,d8b8e6,9fe3de,f4f7f8 +font_args=(--font-family "JetBrains Mono,Menlo,DejaVu Sans Mono") +[ -n "${SOCAIR_DEMO_FONT_DIR:-}" ] && font_args+=(--font-dir "$SOCAIR_DEMO_FONT_DIR") +mkdir -p "$(dirname "$out")" +agg --quiet --theme "$theme" "${font_args[@]}" --font-size 16 --idle-time-limit 4 --last-frame-duration 8 \ + "$work/demo.cast" "$out" +echo "wrote $out"