RPF-WP-0061-T03: ccr/* branch gate and CI workflow; first automated platform review on CCR-2026-0051
Some checks failed
CCR intake gate / gate (push) Failing after 25s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 306568@bnt-lap001
Assistant-Session: 8bdf8150-ea56-41e7-9132-13f04f6b0b91
This commit is contained in:
codex 2026-10-18 12:37:05 +02:00
parent b6148da443
commit 10fddbc98f
5 changed files with 191 additions and 7 deletions

View file

@ -220,6 +220,64 @@ def command_check_ids(args: argparse.Namespace, cc: Any) -> int:
return 1 if duplicates else 0
def tree_digests(root: Path) -> dict[str, str]:
return {
str(path.relative_to(root)): hashlib.sha256(path.read_bytes()).hexdigest()
for path in root.rglob("*")
if path.is_file() and ".git" not in path.relative_to(root).parts
and "__pycache__" not in path.parts
}
def branch_gate(main_root: Path, stem: str, cc: Any, profile_path: Path = DEFAULT_PROFILE) -> list[str]:
"""CI gate for a ccr/<stem> branch checked out at REPO_DIR (RPF-WP-0061-T03).
The branch may add exactly one new CCR and its new policy file, nothing
else; the CCR must be an in-profile submission from a listed submitter with
a policy-as-code review against the current profile digest.
"""
errors: list[str] = []
ccr_rel = f"credential-change-requests/{stem}.yaml"
path = REPO_DIR / ccr_rel
if not CCR_FILE_RE.match(path.name) or not path.exists():
return [f"branch ccr/{stem} must add {ccr_rel}"]
if (main_root / ccr_rel).exists():
errors.append(f"{ccr_rel} already exists on main")
ccr, validation_errors, _warnings = cc.validate_ccr(path)
errors.extend(f"validate: {item}" for item in validation_errors)
policy_rel = (ccr.get("openbao") or {}).get("policy_file")
allowed = {ccr_rel} | ({policy_rel} if policy_rel else set())
branch, main = tree_digests(REPO_DIR), tree_digests(main_root)
changed = {k for k in branch.keys() | main.keys() if branch.get(k) != main.get(k)}
for extra in sorted(changed - allowed):
errors.append(f"ccr branch may not change {extra}")
if policy_rel and policy_rel in main and main[policy_rel] != branch.get(policy_rel):
errors.append(f"{policy_rel} exists on main; a submission may not modify it")
if ccr.get("status") != "proposed":
errors.append(f"status must be proposed, got {ccr.get('status')}")
profile, digest = load_profile(profile_path)
if (ccr.get("requester") or {}).get("agent") not in profile["submitters"]:
errors.append(f"requester is not a listed submitter {profile['submitters']}")
errors.extend(standard_violations(ccr, profile, path.parent, cc))
comments = (ccr.get("review") or {}).get("comments") or []
if len(comments) != 1 or comments[0].get("decision") != "approved" or digest not in str(
comments[0].get("comment")
):
errors.append("review must hold exactly the policy-as-code approval for the current profile")
errors.extend(f"duplicate id: {k} {v}" for k, v in duplicate_ids(path.parent, cc).items())
return errors
def command_check_branch(args: argparse.Namespace, cc: Any) -> int:
stem = args.branch.removeprefix("refs/heads/").removeprefix("ccr/")
errors = branch_gate(Path(args.main_root).resolve(), stem, cc)
for item in errors:
print(f"[FAIL] ccr/{stem}: {item}")
if not errors:
print(f"[OK] ccr/{stem}: one in-profile CCR, nothing else changed")
return 1 if errors else 0
def git(*argv: str) -> None:
subprocess.run(["git", "-C", str(REPO_DIR), *argv], check=True)
@ -294,6 +352,13 @@ def add_parsers(sub: Any, cc: Any, state_hub_url: str) -> None:
check_ids = sub.add_parser("check-ids", help="Fail on duplicate CCR ids or id/file name mismatch")
check_ids.set_defaults(func=lambda args: command_check_ids(args, cc))
check_branch = sub.add_parser(
"check-branch", help="CI gate: a ccr/* branch adds exactly one in-profile CCR and its policy"
)
check_branch.add_argument("--branch", required=True, help="ccr/<id>-<slug> or refs/heads/ccr/...")
check_branch.add_argument("--main-root", required=True, help="tree of main to compare against")
check_branch.set_defaults(func=lambda args: command_check_branch(args, cc))
submit_p = sub.add_parser(
"submit",
help="File a client CCR draft under the next CCR id and run the standard review",