bcx 0.4.0

Bifrost Causal Exchange protocol primitives for signed causal meaning and proof composition.
Documentation
#!/usr/bin/env python3
"""Record root PENTEST.md as a permanent release pentest report."""

from __future__ import annotations

import argparse
import hashlib
import re
import subprocess
import sys
from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
SCRATCH_REPORT = ROOT / "PENTEST.md"
COMMIT_HASH_PATTERN = r"^[0-9a-fA-F]{40}$"


def capture(command: list[str]) -> str:
    return subprocess.check_output(command, cwd=ROOT, text=True).strip()


def workspace_version() -> str:
    cargo_toml = ROOT / "Cargo.toml"
    for line in cargo_toml.read_text(encoding="utf-8").splitlines():
        if line.startswith("version = "):
            return line.split('"', 2)[1]
    raise RuntimeError("could not determine workspace version")


def sha256_digest(data: bytes) -> str:
    return hashlib.sha256(data).hexdigest()


def display_path(path: Path) -> str:
    try:
        return str(path.relative_to(ROOT))
    except ValueError:
        return str(path)


def validate_report_arg(name: str, value: str, pattern: str = r"^[^\n\r]+$") -> str:
    if re.fullmatch(pattern, value) is None:
        raise ValueError(f"--{name} contains invalid characters: {value!r}")
    return value


def build_report(
    *,
    version: str,
    status: str,
    tester: str,
    scope: str,
    date: str,
    commit: str,
    input_digest: str,
    scratch_text: str,
) -> str:
    tag = f"v{version}"
    return f"""# BCX {tag} Pentest Report

Tag: {tag}
Commit: {commit}
Status: {status}
Tester: {tester}
Date: {date}
Scope: {scope}

## Summary

This report records the release pentest result for BCX `{tag}`. The root
`PENTEST.md` scratch input was reviewed, remediated where release-scope fixes
were required, and then captured here by digest before deletion.

Input-Digest: sha256:{input_digest}

## Scratch Report

```text
{scratch_text.rstrip()}
```
"""


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Record root PENTEST.md under security/pentest/."
    )
    parser.add_argument(
        "--version",
        default=workspace_version(),
        help="Release version without leading v. Defaults to workspace version.",
    )
    parser.add_argument("--status", default="PASS", help="Pentest status.")
    parser.add_argument(
        "--tester",
        required=True,
        help="Tester or review role to record in the permanent report.",
    )
    parser.add_argument("--scope", required=True, help="Pentest scope.")
    parser.add_argument(
        "--date",
        required=True,
        help="Pentest date in YYYY-MM-DD format.",
    )
    parser.add_argument(
        "--commit",
        default=capture(["git", "rev-parse", "HEAD"]),
        help="Exact 40-character commit hash that was pentested. Defaults to HEAD.",
    )
    parser.add_argument(
        "--output",
        help="Override output path. Defaults to security/pentest/v<version>.md.",
    )
    args = parser.parse_args()

    if not SCRATCH_REPORT.is_file():
        print("missing root PENTEST.md scratch report", file=sys.stderr)
        return 1

    tester = validate_report_arg("tester", args.tester)
    scope = validate_report_arg("scope", args.scope)
    date = validate_report_arg("date", args.date, r"^[0-9]{4}-[0-9]{2}-[0-9]{2}$")
    status = validate_report_arg("status", args.status, r"^[A-Z]+$")
    commit = validate_report_arg("commit", args.commit, COMMIT_HASH_PATTERN)

    scratch_bytes = SCRATCH_REPORT.read_bytes()
    scratch_text = scratch_bytes.decode("utf-8")
    input_digest = sha256_digest(scratch_bytes)
    output = (
        ROOT / args.output
        if args.output
        else ROOT / "security" / "pentest" / f"v{args.version}.md"
    )

    report = build_report(
        version=args.version,
        status=status,
        tester=tester,
        scope=scope,
        date=date,
        commit=commit,
        input_digest=input_digest,
        scratch_text=scratch_text,
    )
    output.parent.mkdir(parents=True, exist_ok=True)
    output.write_text(report, encoding="utf-8")

    print(f"wrote {display_path(output)}")
    print(f"Input-Digest: sha256:{input_digest}")
    print("Delete root PENTEST.md after reviewing the permanent report.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())