- bounded-executor/prepare_admission.py: the live admission from the pilot example, pins read from the image's commit, window <= 2 h (audit-core's declared bound), validated. - executor-lanes.py window-open/window-close: CCR-2026-0058's window-scoped write role, created for one admitted open window under attended platform-admin and deleted afterwards (idempotent). - security-cases/nk-bind-executor-approval.yaml: the case of record, proposed (founder acceptance). - docs/evidence/2026-11-04-nk56-t15-audit-sender: 8 checks against audit-core 876c3f6. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 523928@bnt-lap001 Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350
92 lines
4.4 KiB
Python
92 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Prepare the live pilot admission (NK-WP-0056-T06) from the pilot example.
|
|
|
|
The executor checks every pinned file against the copy inside its image (source_root /app), so the pins are taken
|
|
from the commit the pinned image was built from (`--commit`, read with `git show`), not from the working tree.
|
|
The window opens at `--not-before` and lasts `--hours`. The budget, plan, checks and scope ceiling are the
|
|
example's, so the admission stays inside the executor's declared grants (make bounded-executor-test).
|
|
|
|
python3 bounded-executor/prepare_admission.py --id BEA-2026-0002 --commit 9bd7bf0 \\
|
|
--not-before 2026-11-05T09:00:00Z --hours 2 --out admissions/BEA-2026-0002.yaml
|
|
|
|
Prints the admission and plan digests. Writes nothing else and contacts nothing.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import datetime as dt
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import pathlib
|
|
import subprocess
|
|
import sys
|
|
|
|
import yaml
|
|
|
|
HERE = pathlib.Path(__file__).resolve().parent
|
|
REPO = HERE.parent
|
|
EXAMPLE = REPO / "examples/bounded-execution-admission/bind-rotation-svc-authelia.yaml"
|
|
_spec = importlib.util.spec_from_file_location("bea_validate_prepare", REPO / "tools/bounded-execution-admission/validate.py")
|
|
bea = importlib.util.module_from_spec(_spec)
|
|
_spec.loader.exec_module(bea)
|
|
|
|
|
|
def _git(*args: str) -> bytes:
|
|
return subprocess.run(["git", "-C", str(REPO), *args], capture_output=True, check=True).stdout
|
|
|
|
|
|
def _z(t: dt.datetime) -> str:
|
|
return t.astimezone(dt.UTC).isoformat(timespec="seconds").replace("+00:00", "Z")
|
|
|
|
|
|
def prepare(admission_id: str, commit: str, not_before: dt.datetime, hours: float) -> dict:
|
|
full = _git("rev-parse", "--verify", commit + "^{commit}").decode().strip()
|
|
doc = bea.load(EXAMPLE)
|
|
spec = doc["spec"]
|
|
spec.update(id=admission_id, work_ref="NK-WP-0056-T06",
|
|
title="Rotate the svc-authelia directory bind (live pilot, one consumer)")
|
|
spec["window"] = {"not_before": _z(not_before), "not_after": _z(not_before + dt.timedelta(hours=hours))}
|
|
files = [{"path": f["path"], "sha256": hashlib.sha256(_git("show", f"{full}:{f['path']}")).hexdigest()}
|
|
for f in spec["plan"]["source"]["files"]]
|
|
spec["plan"]["source"].update(commit=full[:12], files=files)
|
|
pins = {f["path"]: f["sha256"] for f in files}
|
|
for check in spec["checks"]:
|
|
check["sha256"] = pins[check["ref"]]
|
|
spec["plan_digest"] = bea.plan_digest(doc)
|
|
report = bea.evaluate(doc, json.loads(bea.SCHEMA.read_text()), as_of=not_before)
|
|
if not report["valid"]:
|
|
raise ValueError("admission invalid: " + ",".join(sorted({f["rule"] for f in report["findings"]})))
|
|
return doc
|
|
|
|
|
|
def main(argv=None) -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__.split("\n", 1)[0])
|
|
parser.add_argument("--id", required=True)
|
|
parser.add_argument("--commit", required=True, help="the commit the pinned executor image was built from")
|
|
parser.add_argument("--not-before", required=True, help="window start, RFC 3339 with offset")
|
|
parser.add_argument("--hours", type=float, default=2.0)
|
|
parser.add_argument("--out", required=True, type=pathlib.Path)
|
|
args = parser.parse_args(argv)
|
|
if args.out.exists():
|
|
raise SystemExit("output exists; admissions are immutable, choose a new id")
|
|
if not 0 < args.hours <= 2:
|
|
raise SystemExit("--hours must be in (0, 2]: audit-core's declared bound for a run without receipt is 2 h")
|
|
try:
|
|
doc = prepare(args.id, args.commit, dt.datetime.fromisoformat(args.not_before.replace("Z", "+00:00")),
|
|
args.hours)
|
|
except (ValueError, subprocess.CalledProcessError) as error:
|
|
print(f"refused: {error}" if isinstance(error, ValueError) else "refused: unknown commit or path",
|
|
file=sys.stderr)
|
|
return 4
|
|
args.out.parent.mkdir(parents=True, exist_ok=True)
|
|
args.out.write_text("# NK-WP-0056-T06 live pilot admission. Immutable once requested: a change is a new id.\n"
|
|
+ yaml.safe_dump(doc, sort_keys=False, width=120))
|
|
print(json.dumps({"admission": args.id, "admission_digest": bea.admission_digest(doc),
|
|
"plan_digest": doc["spec"]["plan_digest"], "window": doc["spec"]["window"],
|
|
"pinned_commit": doc["spec"]["plan"]["source"]["commit"]}, indent=2))
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|