Hub end-to-end v0 (Decision → Proof → Review → Approve → Proof)
This page is the minimal “DecisionOps loop” using local-only primitives.
0) Prepare a proposed bundle (no approvals)
Start from the shipped example bundle and strip approval receipts to create a “proposed” bundle:
rm -rf out/proposed_bundle
mkdir -p out
cp -R fixtures/hub_example_bundle_v1 out/proposed_bundle
rm -f out/proposed_bundle/receipts/approval_receipt_v1.json
./venv/bin/python - <<'PY'
import json
from pathlib import Path
p = Path("out/proposed_bundle/bundle_manifest_v1.json")
m = json.loads(p.read_text(encoding="utf-8"))
m.setdefault("receipts", {})["approval_receipt_digests"] = []
p.write_text(json.dumps(m, sort_keys=True, separators=(",", ":")) + "\n", encoding="utf-8")
PY
1) Verify and capture digests
helix hub verify bundle out/proposed_bundle --require-signatures
Record:
manifest: sha256:...(this is theproposed_bundle_digest)core: sha256:...(bundles with different receipts can share the same core digest)
2) Create a Decision (local store)
Pick a local hub root:
export HUB_ROOT=var/hub_demo
Note: --hub-root can appear anywhere inside helix hub ... commands. These are equivalent:
helix hub --hub-root "$HUB_ROOT" decision export --format json
helix hub decision --hub-root "$HUB_ROOT" export --format json
helix hub decision export --hub-root "$HUB_ROOT" --format json
If --hub-root is specified more than once, the CLI fails closed.
Extract the policy + backend fingerprint digests from the bundle manifest:
./venv/bin/python - <<'PY'
import json
from pathlib import Path
m = json.loads(Path("out/proposed_bundle/bundle_manifest_v1.json").read_text(encoding="utf-8"))
print("policy_digest=" + m["inputs"]["policy_digest"])
print("backend_fingerprint_digest=" + m["producer"]["backend_fingerprint_digest"])
PY
Create the Decision (replace PROPOSED_BUNDLE_DIGEST with the manifest: ... value from step 1):
helix hub --hub-root "$HUB_ROOT" decision create \
--decision-id DECISION123 \
--workspace-id ws_example \
--project-id proj_example \
--decision-kind crispr.guide_selection \
--subject '{"note":"synthetic"}' \
--proposed-bundle-digest PROPOSED_BUNDLE_DIGEST \
--policy-digest policy_digest_from_step_2 \
--backend-fingerprint-digest backend_fingerprint_digest_from_step_2
3) Cache the proposed bundle by digest
The --decision-id flows resolve bundles from:
$HUB_ROOT/bundles/<bundle_digest_hex>/
Copy the proposed bundle into the cache:
export BUNDLE_HEX="${PROPOSED_BUNDLE_DIGEST#sha256:}"
mkdir -p "$HUB_ROOT/bundles/$BUNDLE_HEX"
cp -R out/proposed_bundle/* "$HUB_ROOT/bundles/$BUNDLE_HEX/"
4) Render a Proof pack
helix hub --hub-root "$HUB_ROOT" proof render \
--decision-id DECISION123 \
--out out/proof_v0 \
--zip
Verify the included bundle:
cd out/proof_v0
helix hub verify bundle ./bundle --require-signatures
5) Render a Review pack
helix hub --hub-root "$HUB_ROOT" review render \
--decision-id DECISION123 \
--out out/review_v0
Open out/review_v0/index.html and inspect:
- The
approval_surface_digestand the surface JSON artifact it was computed from - The verifier status and mapped failure reasons (if any)
- The copy-pasteable
helix hub review approve ...command
6) Approve (emit receipt + updated bundle + update Decision)
helix hub --hub-root "$HUB_ROOT" review approve \
DECISION123 \
--bundle "$HUB_ROOT/bundles/$BUNDLE_HEX" \
--signing-key tests/fixtures/validation_verdict_vectors/publisher.ed25519 \
--key-id hub-test \
--approver-subject sub_example_reviewer \
--approver-email reviewer@example.com \
--approver-display-name "Example Reviewer" \
--attestation "Reviewed synthetic decision bundle; approval for demo."
Invariants:
- The original proposed bundle directory is never modified in place.
- Approval fails closed if the resulting approved bundle is not verifier-clean with
--require-signatures. - Running approve twice is idempotent: the second run is a no-op.
7) Render Proof again (now bound to the approved bundle)
helix hub --hub-root "$HUB_ROOT" proof render \
--decision-id DECISION123 \
--out out/proof_v0_approved
cd out/proof_v0_approved
helix hub verify bundle ./bundle --require-signatures
8) Export Decisions (procurement report)
Export “approved decisions in a window” as a single deterministic CSV (sorted by approved_at_utc, then decision_id):
helix hub --hub-root "$HUB_ROOT" decision export \
--format csv \
--state approved \
--approved-after 2026-01-01T00:00:00Z \
--approved-before 2026-04-01T00:00:00Z \
--out out/decisions_approved_q1.csv
Example CSV (truncated):
# helix.decision.export.v0
decision_id,decision_kind,state,created_at_utc,created_by_subject,...,approved_bundle_digest,policy_digest,backend_fingerprint_digest,approval_surface_digest,approval_receipt_digests,decision_digest
DECISION123,crispr.guide_selection,approved,2026-01-01T00:00:00Z,creator,...,sha256:<bundle>,sha256:<policy>,sha256:<backend>,sha256:<surface>,sha256:<receipt>,sha256:<decision>
Trust anchors:
approved_bundle_digest(the exact bundle bytes that were approved)approval_surface_digest+approval_receipt_digests(who approved what surface)decision_digest(stable Decision v1 identity)
If you store proof packs under $HUB_ROOT/proofs/by_bundle/<bundle_digest_hex>/, you can include proof pack resolution in the export:
helix hub --hub-root "$HUB_ROOT" decision export --format csv --state approved --include-proof --out out/decisions_approved_with_proof.csv
JSON export includes an explicit envelope with schema version + rows:
helix hub --hub-root "$HUB_ROOT" decision export --format json --state approved --out out/decisions_approved.json
9) Export a pilot evidence kit (single deliverable folder)
This emits a buyer-ready folder that contains:
README.md(verification instructions)decisions.csv+decisions.jsonproofs/<decision_id>.zipfor each approved decision in the window
helix hub --hub-root "$HUB_ROOT" pilot export \
--workspace ws_example \
--project proj_example \
--approved-after 2026-01-01T00:00:00Z \
--approved-before 2026-04-01T00:00:00Z \
--out out/pilot_evidence_kit \
--zip