-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
111 lines (100 loc) · 5.54 KB
/
Copy pathMakefile
File metadata and controls
111 lines (100 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
PY := .venv/bin/python
WARDLINE := /home/john/.local/bin/wardline
LEGIS := /home/john/.local/bin/legis
# plainweave is a live RUNNABLE tour member; the leg resolves it BIN-first via
# capability._tool. `make verify` requires it installed (a uv tool, like its
# siblings): uv tool install /home/john/plainweave
PLAINWEAVE := /home/john/.local/bin/plainweave
.PHONY: setup tour verify test scan cargo-check docs ci provision-posture
# Provision the demo's gitignored secrets + local ledgers so a fresh clone
# "just goes". Idempotent: never clobbers a hand-edited .env or an already-
# provisioned posture ledger.
setup: .env provision-posture
@echo "✓ demo secrets + posture ledger ready (gitignored). Next: make tour | make verify"
# Shared HMAC for the Wardline→Legis signed scan handshake. Generated locally,
# 0600, never committed (.env is gitignored). Both names carry the SAME value:
# wardline signs with WARDLINE_LEGIS_ARTIFACT_KEY, legis verifies with
# LEGIS_WARDLINE_ARTIFACT_KEY. Absent → the tour degrades to an UNSIGNED handshake.
#
# LEGIS_HMAC_KEY is a DISTINCT, independent secret (its own fresh value, NOT the
# artifact key): it enables the legis binding ledger / closure gate. Gitignored,
# 0600, never committed. The standing legis MCP server reads it from the shell
# env — export before launching Claude Code (see README); absent → the gate stays
# disabled (CELL_NOT_ENABLED).
#
# LEGIS_OPERATOR_KEY is the posture-floor operator key (64 hex). legis >= 1.1.0
# ADOPTS it as the GENESIS epoch key on `install --posture --insecure-key-in-env`
# (it no longer mints a throwaway), so provision-posture writes a floor that is
# actually owned by a key we hold. Absent → the install fails loud.
.env:
@umask 077; KEY=$$(python3 -c 'import secrets; print(secrets.token_hex(32))'); \
HMAC=$$(python3 -c 'import secrets; print(secrets.token_hex(32))'); \
OPK=$$(python3 -c 'import secrets; print(secrets.token_hex(32))'); \
{ \
echo "# Lacuna demo secrets — GITIGNORED, generated by 'make setup'. Never commit."; \
echo "# Regenerate: rm .env && make setup"; \
echo "WARDLINE_LEGIS_ARTIFACT_KEY=$$KEY"; \
echo "LEGIS_WARDLINE_ARTIFACT_KEY=$$KEY"; \
echo "LEGIS_HMAC_KEY=$$HMAC"; \
echo "LEGIS_OPERATOR_KEY=$$OPK"; \
} > .env
@echo "✓ generated .env (0600) with a fresh shared HMAC key + legis ledger + operator key"
# Write the signed posture-floor GENESIS into the local (gitignored) posture
# ledger so the demo shows a REAL signed floor. (An unprovisioned ledger no
# longer crashes the reads — legis >= 1.1.0 degrades posture_get / policy_list to
# a fail-closed `structured` floor instead of throwing `no such table:
# audit_log` — so this is about demonstrating a live signed floor, not avoiding a
# crash.) `install --posture --insecure-key-in-env` ADOPTS LEGIS_OPERATOR_KEY (from
# .env, sourced below) as the GENESIS epoch key — legis >= 1.1.0 no longer mints a
# throwaway, so the floor is owned by a key we hold — writes the GENESIS
# (floor=chill, the lowest cell — provisions + signs without overriding the
# policy/cells.toml routing showcase), and is idempotent (a second run no-ops on
# the existing epoch). READING the floor needs no key; raising it (`legis posture
# set`) needs an open operator session under that same LEGIS_OPERATOR_KEY.
# Guard: only provision when the ledger has no readable floor yet. We re-check the
# floor AFTER install and fail loud if none was written — `legis install` reports a
# missing-key custody gap as a non-fatal "deferred" success, so the post-check is
# what turns a silent no-op into a real failure (live-fire member: no false-green).
provision-posture: .env
@set -a; . ./.env; set +a; \
FLOOR=$$($(LEGIS) posture show 2>/dev/null); \
if echo "$$FLOOR" | grep -q '^posture floor:' && ! echo "$$FLOOR" | grep -q 'no ledger'; then \
echo "✓ posture ledger already provisioned ($$FLOOR)"; \
else \
$(LEGIS) install --posture --insecure-key-in-env --agent-id lacuna-demo >/dev/null; \
FLOOR2=$$($(LEGIS) posture show 2>/dev/null); \
if echo "$$FLOOR2" | grep -q '^posture floor:' && ! echo "$$FLOOR2" | grep -q 'no ledger'; then \
echo "✓ posture ledger provisioned — signed GENESIS ($$FLOOR2, gitignored)"; \
else \
echo "✗ posture provisioning FAILED — no signed GENESIS written (is LEGIS_OPERATOR_KEY a 64-hex key in .env?)" >&2; \
exit 1; \
fi; \
fi
tour: .env provision-posture
$(PY) -m tour tour
$(PY) -m tour.docs_gen
verify: .env provision-posture
$(PY) -m tour verify
test:
$(PY) -m pytest
scan:
# Trusted local checkout: the repo-owned baseline (deliberate planted
# specimen flaws) is allowed to clear the gate. CI-on-PR should instead
# scope to new findings with `--new-since <merge-base>`.
$(WARDLINE) scan . --fail-on ERROR --trust-suppressions
# Second pass: the Rust frontend over the same tree. Routed to a separate
# (gitignored) output so it never clobbers the Python findings.jsonl.
$(WARDLINE) scan . --lang rust --fail-on ERROR --trust-suppressions --output findings-rust.jsonl
# Compile gate for the Rust specimen — capability-gated: runs when a Rust
# toolchain is present, degrades with an honest note when not (mirrors the
# tour's tool detection). The crate is genuinely clean-cored; only the planted
# taint/archaeology lacunae are intentional.
cargo-check:
@if command -v cargo >/dev/null 2>&1; then \
(cd specimen-rs && cargo check -q) && echo "✓ specimen-rs compiles (cargo check)"; \
else \
echo "⚠ cargo not found — Rust compile check skipped (honest degrade)"; \
fi
docs:
$(PY) -m tour.docs_gen
ci: test scan verify cargo-check