NET-WP-0020 finished: attended-ceremony + auto-unseal-transit profiles, greenfield init/unseal proof

T2: greenfield live proof against a fresh uninitialized OpenBao 2.5.5 —
caught and fixed 'bao operator unseal -' not reading stdin (now
'bao write sys/unseal key=-'); init and reseal-replay paths proven.
T3: attended-ceremony selectable — runbook, non-secret ceremony-record
template + validator, and a lab/production deployment profile that blocks
sops-held-automation in console selection, gates, and the init script.
T4: console gate + evidence flags for auto-unseal-transit (Helm seal stanza
prepared in railiance-platform).
Also: SCOPE.md refreshed to current repo state; adhoc fix for the broken
check-secrets Make target (unescaped $).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 22:08:33 +02:00
parent 60b9d7037d
commit 85a781b7a4
10 changed files with 564 additions and 69 deletions

View File

@@ -36,15 +36,82 @@ def test_openbao_unseal_custody_model_gate_automation_default():
assert init_gate.status == "automation"
def test_openbao_unseal_custody_planned_models_blocked():
def test_openbao_unseal_custody_production_models_selectable():
for model in ("attended-ceremony", "auto-unseal-transit"):
data = console.metadata_template()
data["openbao_unseal_custody_model"] = model
gate = console.openbao_unseal_custody_model_gate(data)
assert gate.status == "blocked"
assert "not yet implemented" in gate.reason.lower()
init_gate = console.openbao_init_ceremony_gate(data)
assert init_gate.status == "blocked"
assert gate.status == "done"
def test_attended_ceremony_init_gate_is_human_with_runbook():
data = console.metadata_template()
data["openbao_unseal_custody_model"] = "attended-ceremony"
init_gate = console.openbao_init_ceremony_gate(data)
assert init_gate.status == "human"
assert "openbao-attended-ceremony-runbook" in init_gate.reason
def test_auto_unseal_transit_init_gate_requires_evidence():
data = console.metadata_template()
data["openbao_unseal_custody_model"] = "auto-unseal-transit"
gate = console.openbao_init_ceremony_gate(data)
assert gate.status == "blocked"
assert "openbao_transit_seal_configured" in gate.reason
data["openbao_transit_seal_configured"] = True
gate = console.openbao_init_ceremony_gate(data)
assert gate.status == "blocked"
assert "openbao_auto_unseal_verified" in gate.reason
data["openbao_auto_unseal_verified"] = True
gate = console.openbao_init_ceremony_gate(data)
assert gate.status == "human"
def test_production_profile_blocks_sops_held_automation():
data = console.metadata_template()
data["deployment_profile"] = "production"
gate = console.openbao_unseal_custody_model_gate(data)
assert gate.status == "blocked"
assert "production profile" in gate.reason.lower()
init_gate = console.openbao_init_ceremony_gate(data)
assert init_gate.status == "blocked"
data["openbao_unseal_custody_model"] = "attended-ceremony"
assert console.openbao_unseal_custody_model_gate(data).status == "done"
def test_openbao_ceremony_record_template_and_validation(tmp_path):
tmpl = console.openbao_ceremony_record_template()
for key in (
"attended_init_completed",
"unseal_shares_escrowed_out_of_band",
"root_token_retired_or_escrowed",
"post_unseal_verified",
"no_secret_material_recorded",
):
assert key in tmpl
# a filled-in, non-secret record validates cleanly
record = dict(tmpl)
record.update(
evidence_date="2026-07-02",
ceremony_scope="Attended init on Railiance ThreePhoenix.",
unseal_share_escrow_disposition="Shares to roster holders, offline packets.",
root_token_disposition="revoked after configure-initial",
witness="recovery-custodian",
attended_init_completed=True,
unseal_shares_escrowed_out_of_band=True,
root_token_retired_or_escrowed=True,
post_unseal_verified=True,
no_secret_material_recorded=True,
)
path = tmp_path / "record.json"
path.write_text(json.dumps(record))
_, errors = console.load_evidence_json(path, "openbao-ceremony")
assert errors == []
# a record leaking a token marker is refused
record["root_token_disposition"] = "hvs.deadbeef"
path.write_text(json.dumps(record))
_, errors = console.load_evidence_json(path, "openbao-ceremony")
assert any("secret-looking" in e for e in errors)
def test_onboarding_dry_run_template_has_required_fields():
tmpl = console.onboarding_dry_run_template()