From b051aa3981e52a56b45a3078fcbf32ac34a99f92 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Wed, 22 Jul 2026 18:34:50 -0500 Subject: [PATCH 001/116] ci: verify seven-repository convergence --- .../workflows/command-center-invariants.yml | 93 ++++++++++++++++++- governance/COMMAND_CENTER_INVARIANTS.json | 14 ++- scripts/verify-command-center-invariants.py | 85 +++++++++++++++++ 3 files changed, 190 insertions(+), 2 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 9e2db4b..3abe177 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -11,6 +11,7 @@ on: - ".github/pull_request_template.md" - ".github/workflows/command-center-invariants.yml" - "scripts/verify-command-center-invariants.py" + - "governance/COMMAND_CENTER_INVARIANTS.json" push: branches: - main @@ -23,6 +24,7 @@ on: - ".github/pull_request_template.md" - ".github/workflows/command-center-invariants.yml" - "scripts/verify-command-center-invariants.py" + - "governance/COMMAND_CENTER_INVARIANTS.json" permissions: contents: read @@ -35,4 +37,93 @@ jobs: uses: actions/checkout@v4 - name: Verify command-center invariants - run: python scripts/verify-command-center-invariants.py + run: python scripts/verify-command-center-invariants.py --self-test + + seven-repository-convergence: + runs-on: ubuntu-latest + env: + REQUESTED_REF: ${{ github.event.pull_request.head.ref || github.ref_name }} + steps: + - name: Checkout workflow authority + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Checkout exact seven-repository source set read-only + shell: bash + run: | + set -euo pipefail + mkdir -p source-set verification-artifacts + repos=( + .github + hawkinsoperations-detections + hawkinsoperations-validation + hawkinsoperations-platform + hawkinsoperations-proof + hawkinsoperations-website + hoxline + ) + : > verification-artifacts/source-revisions.txt + for repo in "${repos[@]}"; do + url="https://github.com/HawkinsOperations/${repo}.git" + ref="main" + if git ls-remote --exit-code --heads "$url" "$REQUESTED_REF" >/dev/null 2>&1; then + ref="$REQUESTED_REF" + fi + git clone --quiet --branch "$ref" "$url" "source-set/$repo" + sha="$(git -C "source-set/$repo" rev-parse HEAD)" + printf '%s ref=%s sha=%s\n' "$repo" "$ref" "$sha" >> verification-artifacts/source-revisions.txt + done + + - name: Install bounded verifier dependencies + run: python -m pip install --disable-pip-version-check -e source-set/hoxline + + - name: Verify source and validation contracts + shell: bash + run: | + set -euo pipefail + python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract.py | tee verification-artifacts/detections.txt + python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix.py | tee -a verification-artifacts/detections.txt + python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry.py | tee verification-artifacts/validation.txt + python -B source-set/hawkinsoperations-validation/scripts/verify_all_validation_packages.py | tee -a verification-artifacts/validation.txt + + - name: Verify proof and platform convergence + shell: bash + run: | + set -euo pipefail + python -B source-set/hawkinsoperations-proof/scripts/verify_detection_proof_status_index.py | tee verification-artifacts/proof.txt + python -B source-set/hawkinsoperations-platform/scripts/ho_factory.py hoxline-case-growth-convergence-verify --repo-root source-set --format json | tee verification-artifacts/platform-convergence.json + + - name: Verify Hoxline case growth and website projection + shell: bash + env: + PYTHONPATH: source-set/hoxline/src + run: | + set -euo pipefail + python -B -m hoxline.cli case-growth verify --repo-root source-set --snapshot source-set/hoxline/examples/case-growth/current-case-growth-index.json | tee verification-artifacts/hoxline-convergence.txt + npm ci --prefix source-set/hawkinsoperations-website + npm --prefix source-set/hawkinsoperations-website run public-status:verify | tee verification-artifacts/website.txt + + - name: Sanitize convergence diagnostics + id: sanitize + if: always() + shell: bash + run: | + set -euo pipefail + find verification-artifacts -type f -exec sed -i -E 's#(/home/runner/[^ ]+|[A-Za-z]:\\[^ ]+)#[local-path-redacted]#g' {} + + if grep -R -E '(github[_]pat_|g[h]p_|BEGIN (RSA |OPENSSH )?PRIVATE KEY)' verification-artifacts; then + echo "Unsafe diagnostic marker detected; artifact upload blocked." + exit 1 + fi + + - name: Upload sanitized convergence diagnostics + if: always() && steps.sanitize.outcome == 'success' + uses: actions/upload-artifact@v4 + with: + name: seven-repository-convergence-${{ github.run_id }} + path: verification-artifacts/ + if-no-files-found: error + retention-days: 14 diff --git a/governance/COMMAND_CENTER_INVARIANTS.json b/governance/COMMAND_CENTER_INVARIANTS.json index dbcb12d..58f6644 100644 --- a/governance/COMMAND_CENTER_INVARIANTS.json +++ b/governance/COMMAND_CENTER_INVARIANTS.json @@ -13,7 +13,18 @@ "governance/PR_REVIEW_AUTHORITY.md", "governance/CROSS_REPO_PROMOTION_MAP.md", "wiki/11_ORG_SYSTEM_MAP.md", - ".github/pull_request_template.md" + ".github/pull_request_template.md", + ".github/workflows/command-center-invariants.yml", + "scripts/verify-command-center-invariants.py" + ], + "cross_repo_repositories": [ + ".github", + "hawkinsoperations-detections", + "hawkinsoperations-validation", + "hawkinsoperations-platform", + "hawkinsoperations-proof", + "hawkinsoperations-website", + "hoxline" ], "invariants": { "github_repo_role": ".github is reviewer routing and governance shell only", @@ -26,6 +37,7 @@ "ledger_public_safe_status": "NOT_PUBLIC_SAFE", "reviewer_metrics_pipeline": "Reviewer metrics pipeline keeps Lifetime Governed Cases separate from detection activity, validation cases, proof records, blocked claims, and Project Board reconciliation status", "reviewer_metrics_counts": "Reviewer metrics values are authority-owned snapshots in proof/platform records; front-door text must route to those records instead of copying changing counts", + "cross_repo_convergence": "Read-only verification checks exactly seven repositories, prefers the same branch ref when available, records source revisions, fails closed on drift, and does not write main, merge, mutate the Lifetime Case Ledger, or promote proof/public status", "ho_det_001_public_ceiling": "CONTROLLED_TEST_VALIDATED", "runtime_signal_public_promotions": "runtime-active, signal-observed, evidence-linked public proof, public-safe, production-ready, fleet-wide, AWS-live, Cribl-routed, Wazuh-routed, autonomous SOC, AI-approved, AI-decided, analyst-approved, and live Splunk claims remain blocked unless separately proven and approved", "standing_controls": ".github#8 and .github#10 remain standing controls", diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index e25af3b..3167f0b 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -11,7 +11,17 @@ ROOT = Path(__file__).resolve().parents[1] MANIFEST_PATH = ROOT / "governance" / "COMMAND_CENTER_INVARIANTS.json" +WORKFLOW_PATH = ROOT / ".github" / "workflows" / "command-center-invariants.yml" TEXT_SCOPES = ["README.md", "profile", "architecture", "governance", "wiki", ".github"] +EXACT_REPOSITORIES = [ + ".github", + "hawkinsoperations-detections", + "hawkinsoperations-validation", + "hawkinsoperations-platform", + "hawkinsoperations-proof", + "hawkinsoperations-website", + "hoxline", +] REQUIRED_TEXT = { "README.md": [ @@ -161,6 +171,78 @@ def check_required_files(manifest: dict, errors: list[str]) -> None: fail(f"missing required route file: {item}", errors) +def unsafe_workflow_findings(text: str) -> list[str]: + patterns = { + "contents write permission": r"contents:\s*write", + "pull-request write permission": r"pull-requests:\s*write", + "direct git push": r"\bgit\s+push\b", + "git commit mutation": r"\bgit\s+commit\b", + "PR create or merge mutation": r"\bgh\s+pr\s+(?:create|merge)\b", + "auto-merge mutation": r"\bauto-merge\b", + "Lifetime Case Ledger mutation": r"ho_factory[^\n]*(?:lifetime|ledger)[^\n]*(?:append|correct|mutate)", + } + return [label for label, pattern in patterns.items() if re.search(pattern, text, re.IGNORECASE)] + + +def extract_workflow_repositories(text: str) -> list[str]: + match = re.search(r"^\s*repos=\(\s*$([\s\S]*?)^\s*\)\s*$", text, re.MULTILINE) + if not match: + return [] + return [line.strip() for line in match.group(1).splitlines() if line.strip() and not line.lstrip().startswith("#")] + + +def check_cross_repo_workflow(manifest: dict, errors: list[str]) -> None: + workflow = read_text(WORKFLOW_PATH, errors) + declared = manifest.get("cross_repo_repositories") + if declared != EXACT_REPOSITORIES: + fail("manifest cross_repo_repositories must list the exact seven repositories in canonical order", errors) + required_fragments = [ + "permissions:\n contents: read", + "seven-repository-convergence:", + "REQUESTED_REF:", + "git ls-remote --exit-code --heads", + 'ref="main"', + "actions/setup-python@v5", + "pip install --disable-pip-version-check -e source-set/hoxline", + "source-revisions.txt", + "hoxline-case-growth-convergence-verify", + "case-growth verify", + "public-status:verify", + "Sanitize convergence diagnostics", + "[local-path-redacted]", + "actions/upload-artifact@v4", + "if: always()", + "if: always() && steps.sanitize.outcome == 'success'", + ] + for fragment in required_fragments: + if fragment not in workflow: + fail(f"cross-repo workflow missing required behavior: {fragment}", errors) + workflow_repositories = extract_workflow_repositories(workflow) + if workflow_repositories != EXACT_REPOSITORIES: + fail("cross-repo workflow checkout array must equal the exact ordered seven-repository set with no duplicates", errors) + for finding in unsafe_workflow_findings(workflow): + fail(f"cross-repo workflow permits unsafe behavior: {finding}", errors) + + +def check_workflow_hostile_self_test(errors: list[str]) -> None: + hostile_cases = { + "contents write": "permissions:\n contents: write", + "direct main push": "run: git push origin main", + "commit mutation": "run: git commit -m unsafe", + "PR merge": "run: gh pr merge 1", + "ledger append": "run: python ho_factory.py lifetime-ledger-append", + } + for name, hostile in hostile_cases.items(): + if not unsafe_workflow_findings(hostile): + fail(f"workflow hostile self-test failed to detect {name}", errors) + missing_repo = "repos=(\n .github\n hoxline\n)" + duplicate_repo = "repos=(\n .github\n .github\n hoxline\n)" + if extract_workflow_repositories(missing_repo) == EXACT_REPOSITORIES: + fail("workflow hostile self-test accepted a missing-repository checkout set", errors) + if len(set(extract_workflow_repositories(duplicate_repo))) == len(extract_workflow_repositories(duplicate_repo)): + fail("workflow hostile self-test did not recognize a duplicate-repository checkout set", errors) + + def check_required_text(errors: list[str]) -> None: for rel, needles in REQUIRED_TEXT.items(): text = read_text(ROOT / rel, errors) @@ -276,6 +358,9 @@ def main() -> int: errors: list[str] = [] manifest = load_manifest(errors) check_required_files(manifest, errors) + check_cross_repo_workflow(manifest, errors) + if "--self-test" in sys.argv: + check_workflow_hostile_self_test(errors) check_required_text(errors) text_files = iter_text_files() From 6e6763a81d6af09c2e4588462b56117ce82c2f88 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Wed, 22 Jul 2026 23:58:05 -0500 Subject: [PATCH 002/116] fix(command-center): enforce immutable seven-repo checks --- .../workflows/command-center-invariants.yml | 232 +++- .gitignore | 2 + governance/COMMAND_CENTER_INVARIANTS.json | 5 +- governance/CONVERGENCE_SOURCE_MANIFEST.json | 57 + scripts/verify-command-center-invariants.py | 1106 +++++++++++++++-- tests/test_command_center_workflow_safety.py | 339 +++++ 6 files changed, 1596 insertions(+), 145 deletions(-) create mode 100644 .gitignore create mode 100644 governance/CONVERGENCE_SOURCE_MANIFEST.json create mode 100644 tests/test_command_center_workflow_safety.py diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 3abe177..b9710ca 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -11,7 +11,6 @@ on: - ".github/pull_request_template.md" - ".github/workflows/command-center-invariants.yml" - "scripts/verify-command-center-invariants.py" - - "governance/COMMAND_CENTER_INVARIANTS.json" push: branches: - main @@ -24,7 +23,9 @@ on: - ".github/pull_request_template.md" - ".github/workflows/command-center-invariants.yml" - "scripts/verify-command-center-invariants.py" - - "governance/COMMAND_CENTER_INVARIANTS.json" + workflow_dispatch: {} + schedule: + - cron: "23 7 * * 1" permissions: contents: read @@ -33,97 +34,210 @@ jobs: command-center-invariants: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - name: Checkout command-center authority + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + with: + persist-credentials: false + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 + with: + python-version: "3.12" + + - name: Install structural verifier dependency + run: python -m pip install --disable-pip-version-check PyYAML==6.0.2 - name: Verify command-center invariants run: python scripts/verify-command-center-invariants.py --self-test + - name: Run hostile command-center unit tests + run: python -B -m unittest discover -s tests + + - name: Verify patch whitespace + run: git diff --check + seven-repository-convergence: runs-on: ubuntu-latest env: - REQUESTED_REF: ${{ github.event.pull_request.head.ref || github.ref_name }} + PYTHONDONTWRITEBYTECODE: "1" steps: - - name: Checkout workflow authority - uses: actions/checkout@v4 + - name: Checkout workflow authority at the event revision + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + path: source-set/.github + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 with: python-version: "3.12" - - name: Checkout exact seven-repository source set read-only + - name: Set up Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 + with: + node-version: "20" + + - name: Install bounded verifier dependencies + run: python -m pip install --disable-pip-version-check PyYAML==6.0.2 pytest==8.3.5 + + - name: Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json shell: bash run: | set -euo pipefail - mkdir -p source-set verification-artifacts - repos=( - .github - hawkinsoperations-detections - hawkinsoperations-validation - hawkinsoperations-platform - hawkinsoperations-proof - hawkinsoperations-website - hoxline - ) - : > verification-artifacts/source-revisions.txt - for repo in "${repos[@]}"; do - url="https://github.com/HawkinsOperations/${repo}.git" - ref="main" - if git ls-remote --exit-code --heads "$url" "$REQUESTED_REF" >/dev/null 2>&1; then - ref="$REQUESTED_REF" - fi - git clone --quiet --branch "$ref" "$url" "source-set/$repo" - sha="$(git -C "source-set/$repo" rev-parse HEAD)" - printf '%s ref=%s sha=%s\n' "$repo" "$ref" "$sha" >> verification-artifacts/source-revisions.txt - done + mkdir -p verification-work verification-artifacts + python -B source-set/.github/scripts/verify-command-center-invariants.py \ + --emit-source-manifest verification-work/resolved-source-manifest.json \ + --event-sha "${{ github.event.pull_request.head.sha || github.sha }}" - - name: Install bounded verifier dependencies - run: python -m pip install --disable-pip-version-check -e source-set/hoxline + - name: Checkout six immutable sibling revisions without credentials + shell: bash + run: | + set -euo pipefail + python - verification-work/resolved-source-manifest.json > verification-work/sibling-revisions.tsv <<'PY' + import json + import sys - - name: Verify source and validation contracts + value = json.load(open(sys.argv[1], encoding="utf-8")) + for entry in value["repositories"]: + if entry["repository"] != ".github": + print(f'{entry["repository"]}\t{entry["revision"]}') + PY + while IFS=$'\t' read -r repo revision; do + test -n "$repo" + test -n "$revision" + mkdir "source-set/$repo" + git -C "source-set/$repo" init --quiet + git -C "source-set/$repo" remote add origin "https://github.com/HawkinsOperations/$repo.git" + git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision" + git -C "source-set/$repo" checkout --quiet --detach "$revision" + test "$(git -C "source-set/$repo" rev-parse HEAD)" = "$revision" + done < verification-work/sibling-revisions.tsv + + - name: Verify the exact clean detached source set shell: bash run: | set -euo pipefail - python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract.py | tee verification-artifacts/detections.txt - python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix.py | tee -a verification-artifacts/detections.txt - python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry.py | tee verification-artifacts/validation.txt - python -B source-set/hawkinsoperations-validation/scripts/verify_all_validation_packages.py | tee -a verification-artifacts/validation.txt + python -B source-set/.github/scripts/verify-command-center-invariants.py \ + --verify-source-set source-set \ + --resolved-manifest verification-work/resolved-source-manifest.json \ + --source-revisions-output verification-artifacts/source-revisions.json + proof_sha="$(python - verification-work/resolved-source-manifest.json <<'PY' + import json + import sys + + value = json.load(open(sys.argv[1], encoding="utf-8")) + by_repo = {entry["repository"]: entry["revision"] for entry in value["repositories"]} + print(by_repo["hawkinsoperations-proof"]) + PY + )" + printf 'HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA=%s\n' "$proof_sha" >> "$GITHUB_ENV" - - name: Verify proof and platform convergence + - name: Detect durable sibling main-content drift + if: github.event_name != 'pull_request' + run: >- + python -B source-set/.github/scripts/verify-command-center-invariants.py + --verify-remote-main-content source-set + --resolved-manifest verification-work/resolved-source-manifest.json + + - name: Verify detection authority and hostile paths + shell: bash + run: | + set -euo pipefail + python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract.py + python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix.py + python -B -m unittest discover -s source-set/hawkinsoperations-detections/tests + + - name: Verify validation authority and fail-closed parity shell: bash run: | set -euo pipefail - python -B source-set/hawkinsoperations-proof/scripts/verify_detection_proof_status_index.py | tee verification-artifacts/proof.txt - python -B source-set/hawkinsoperations-platform/scripts/ho_factory.py hoxline-case-growth-convergence-verify --repo-root source-set --format json | tee verification-artifacts/platform-convergence.json + python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry.py + python -B source-set/hawkinsoperations-validation/scripts/verify_all_validation_packages.py + python -B source-set/hawkinsoperations-validation/scripts/verify_validation_contract.py + python -B source-set/hawkinsoperations-validation/scripts/verify_wazuh_logtest_registry.py + python -B source-set/hawkinsoperations-validation/scripts/verify_ho_lab_wazuh_001.py + python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests - - name: Verify Hoxline case growth and website projection + - name: Verify proof authority and reverse inventory shell: bash - env: - PYTHONPATH: source-set/hoxline/src run: | set -euo pipefail - python -B -m hoxline.cli case-growth verify --repo-root source-set --snapshot source-set/hoxline/examples/case-growth/current-case-growth-index.json | tee verification-artifacts/hoxline-convergence.txt - npm ci --prefix source-set/hawkinsoperations-website - npm --prefix source-set/hawkinsoperations-website run public-status:verify | tee verification-artifacts/website.txt + python -B source-set/hawkinsoperations-proof/scripts/verify_detection_proof_status_index.py + python -B source-set/hawkinsoperations-proof/scripts/verify_proof_integrity.py + python -B -m unittest discover -s source-set/hawkinsoperations-proof/tests - - name: Sanitize convergence diagnostics - id: sanitize - if: always() + - name: Verify platform source contract and seven-source convergence shell: bash run: | set -euo pipefail - find verification-artifacts -type f -exec sed -i -E 's#(/home/runner/[^ ]+|[A-Za-z]:\\[^ ]+)#[local-path-redacted]#g' {} + - if grep -R -E '(github[_]pat_|g[h]p_|BEGIN (RSA |OPENSSH )?PRIVATE KEY)' verification-artifacts; then - echo "Unsafe diagnostic marker detected; artifact upload blocked." - exit 1 - fi - - - name: Upload sanitized convergence diagnostics - if: always() && steps.sanitize.outcome == 'success' - uses: actions/upload-artifact@v4 + python -B source-set/hawkinsoperations-platform/scripts/verify-public-status-source-contract.py --format json + python -B source-set/hawkinsoperations-platform/scripts/ho_factory.py \ + hoxline-case-growth-convergence-verify --repo-root source-set --format json + python -B -m unittest discover -s source-set/hawkinsoperations-platform/tests + + - name: Install Hoxline from the checked immutable source + run: python -m pip install --disable-pip-version-check -e source-set/hoxline + + - name: Verify Hoxline Case Growth pair and replay integrity + shell: bash + run: | + set -euo pipefail + python -B -m compileall -q source-set/hoxline/src source-set/hoxline/tests + python -B -m unittest discover -s source-set/hoxline/tests + python -B -m pytest -q source-set/hoxline/tests + python -B -m hoxline.cli case-growth index \ + --repo-root source-set \ + --format json \ + --paired-output-base verification-work/current-case-growth-index + python -B -m hoxline.cli case-growth verify \ + --repo-root source-set \ + --snapshot verification-work/current-case-growth-index.json + python -B -m hoxline review batch run \ + --index source-set/hoxline/examples/review/multi-artifact-review-index-v1.json \ + --output verification-work/batch \ + --force \ + --format json + python -B -m hoxline review batch verify \ + --run verification-work/batch/batch-machine-state.json + + - name: Install Website dependencies from the checked lockfile + run: npm ci --prefix source-set/hawkinsoperations-website + + - name: Verify Website rendering-only status plane and static build + shell: bash + run: | + set -euo pipefail + npm --prefix source-set/hawkinsoperations-website run public-status:generate:check + npm --prefix source-set/hawkinsoperations-website run public-status:verify + npm --prefix source-set/hawkinsoperations-website run public-status:self-test + npm --prefix source-set/hawkinsoperations-website run public-status:owner-self-test + npm --prefix source-set/hawkinsoperations-website run public-status:source-checkout-test + npm --prefix source-set/hawkinsoperations-website run public-status:freshness-reachability-test + npm --prefix source-set/hawkinsoperations-website run public-status:nested-claim-test + npm --prefix source-set/hawkinsoperations-website run public-status:eol-self-test + npm --prefix source-set/hawkinsoperations-website run check:site + npm --prefix source-set/hawkinsoperations-website run typecheck + npm --prefix source-set/hawkinsoperations-website run build + + - name: Write closed-schema verification summary + run: >- + python -B source-set/.github/scripts/verify-command-center-invariants.py + --write-verification-summary + verification-artifacts/verification-summary.json + + - name: Validate upload artifacts + run: >- + python -B source-set/.github/scripts/verify-command-center-invariants.py + --validate-artifacts + verification-artifacts + + - name: Upload sanitized convergence records + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: seven-repository-convergence-${{ github.run_id }} - path: verification-artifacts/ + path: | + verification-artifacts/source-revisions.json + verification-artifacts/verification-summary.json if-no-files-found: error retention-days: 14 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43ae0e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.py[cod] diff --git a/governance/COMMAND_CENTER_INVARIANTS.json b/governance/COMMAND_CENTER_INVARIANTS.json index 58f6644..623e3f9 100644 --- a/governance/COMMAND_CENTER_INVARIANTS.json +++ b/governance/COMMAND_CENTER_INVARIANTS.json @@ -15,7 +15,8 @@ "wiki/11_ORG_SYSTEM_MAP.md", ".github/pull_request_template.md", ".github/workflows/command-center-invariants.yml", - "scripts/verify-command-center-invariants.py" + "scripts/verify-command-center-invariants.py", + "governance/CONVERGENCE_SOURCE_MANIFEST.json" ], "cross_repo_repositories": [ ".github", @@ -37,7 +38,7 @@ "ledger_public_safe_status": "NOT_PUBLIC_SAFE", "reviewer_metrics_pipeline": "Reviewer metrics pipeline keeps Lifetime Governed Cases separate from detection activity, validation cases, proof records, blocked claims, and Project Board reconciliation status", "reviewer_metrics_counts": "Reviewer metrics values are authority-owned snapshots in proof/platform records; front-door text must route to those records instead of copying changing counts", - "cross_repo_convergence": "Read-only verification checks exactly seven repositories, prefers the same branch ref when available, records source revisions, fails closed on drift, and does not write main, merge, mutate the Lifetime Case Ledger, or promote proof/public status", + "cross_repo_convergence": "Read-only verification checks exactly seven repositories at an explicit immutable PR-head matrix, records and verifies every checked revision, fails closed on drift, and does not write main, merge, mutate the Lifetime Case Ledger, or promote proof/public status", "ho_det_001_public_ceiling": "CONTROLLED_TEST_VALIDATED", "runtime_signal_public_promotions": "runtime-active, signal-observed, evidence-linked public proof, public-safe, production-ready, fleet-wide, AWS-live, Cribl-routed, Wazuh-routed, autonomous SOC, AI-approved, AI-decided, analyst-approved, and live Splunk claims remain blocked unless separately proven and approved", "standing_controls": ".github#8 and .github#10 remain standing controls", diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json new file mode 100644 index 0000000..68f9585 --- /dev/null +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -0,0 +1,57 @@ +{ + "schema": "hawkinsoperations-convergence-source-manifest-v1", + "manifest_id": "HAWKINSOPERATIONS_SEVEN_SOURCE_PR_HEAD_MATRIX_V1", + "repositories": [ + { + "repository": ".github", + "canonical_repository": "HawkinsOperations/.github", + "revision_source": "github_event_sha", + "tree_source": "github_event_tree" + }, + { + "repository": "hawkinsoperations-detections", + "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", + "revision": "c2790ab007279faff6130a60dc68818343c255ee", + "reviewed_tree_sha": "e1d7cae30165f21ebfb7ed701f8e854888bfded9" + }, + { + "repository": "hawkinsoperations-validation", + "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", + "revision": "d150cf172a4cb6065fd54c19c59beb9b581ba629", + "reviewed_tree_sha": "b8597f5154f021c6159210af9335ff17e1bf6a2e" + }, + { + "repository": "hawkinsoperations-platform", + "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", + "revision": "d1ea495f2b010fbaefc2dccf22986526958ba424", + "reviewed_tree_sha": "fc487801ba4fdae44a85ea52761fb446b69c421e" + }, + { + "repository": "hawkinsoperations-proof", + "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", + "revision": "042a918ad4a8473cd5abcfd575072fc094639682", + "reviewed_tree_sha": "bedaa1e461556f9c9dced6aac2854594f7baf0cd" + }, + { + "repository": "hawkinsoperations-website", + "canonical_repository": "HawkinsOperations/hawkinsoperations-website", + "revision": "ef7ad97279c06634e153be6e8ecee1959b9f7d78", + "reviewed_tree_sha": "150a6af5df3c2df8cb9b7f3f08b1217a8ad7d7b8" + }, + { + "repository": "hoxline", + "canonical_repository": "HawkinsOperations/hoxline", + "revision": "f2ebea13f5b19fcca348b5359bc9372a7b893962", + "reviewed_tree_sha": "b5ad30a8d7ebbc5bd796ea0bfc58f5317fea5f87" + } + ], + "constraints": { + "exact_repository_count": 7, + "read_only": true, + "default_branch_fallback": false, + "require_detached_exact_revision": true, + "record_checked_revisions": true, + "consumer_outputs_are_not_authority": true, + "proof_ceiling": "CONTROLLED_REPO_CONVERGENCE_AND_LOCAL_FIXTURE_REVIEW_ONLY" + } +} diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 3167f0b..0c70c3c 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -1,16 +1,27 @@ #!/usr/bin/env python3 -"""Fail-closed checks for the HawkinsOperations .github command center.""" +"""Fail-closed checks for the HawkinsOperations command-center workflow.""" from __future__ import annotations +import argparse +import hashlib import json import re +import subprocess import sys -from pathlib import Path +from pathlib import Path, PurePosixPath, PureWindowsPath +from typing import Any +from urllib.parse import unquote + +try: + import yaml +except ImportError: # pragma: no cover - reported as a deterministic verifier failure + yaml = None ROOT = Path(__file__).resolve().parents[1] MANIFEST_PATH = ROOT / "governance" / "COMMAND_CENTER_INVARIANTS.json" +SOURCE_MANIFEST_PATH = ROOT / "governance" / "CONVERGENCE_SOURCE_MANIFEST.json" WORKFLOW_PATH = ROOT / ".github" / "workflows" / "command-center-invariants.yml" TEXT_SCOPES = ["README.md", "profile", "architecture", "governance", "wiki", ".github"] EXACT_REPOSITORIES = [ @@ -22,6 +33,18 @@ "hawkinsoperations-website", "hoxline", ] +CANONICAL_ORIGINS = { + repository: f"https://github.com/HawkinsOperations/{repository}.git" + for repository in EXACT_REPOSITORIES +} +PINNED_ACTIONS = { + "actions/checkout": "11d5960a326750d5838078e36cf38b85af677262", + "actions/setup-python": "a26af69be951a213d495a4c3e4e4022e16d87065", + "actions/setup-node": "49933ea5288caeca8642d1e84afbd3f7d6820020", + "actions/upload-artifact": "ea165f8d65b6e75b540449e92b4886f43607fa02", +} +EXPECTED_ARTIFACT_FILES = {"source-revisions.json", "verification-summary.json"} +PROOF_CEILING = "CONTROLLED_REPO_CONVERGENCE_AND_LOCAL_FIXTURE_REVIEW_ONLY" REQUIRED_TEXT = { "README.md": [ @@ -81,7 +104,6 @@ "analyst-approved", "live Splunk", ] - BOUNDARY_WORDS = ( "blocked", "blocked_claim", @@ -115,6 +137,10 @@ ) +class ValidationError(ValueError): + """Raised when a machine-readable control fails closed.""" + + def fail(message: str, errors: list[str]) -> None: errors.append(message) @@ -123,7 +149,11 @@ def read_text(path: Path, errors: list[str]) -> str: if not path.exists(): fail(f"missing file: {path.relative_to(ROOT).as_posix()}", errors) return "" - return path.read_text(encoding="utf-8") + try: + return path.read_text(encoding="utf-8") + except (OSError, UnicodeError) as exc: + fail(f"cannot read {path.relative_to(ROOT).as_posix()}: {exc}", errors) + return "" def iter_text_files() -> list[Path]: @@ -134,21 +164,92 @@ def iter_text_files() -> list[Path]: files.append(path) elif path.is_dir(): files.extend( - p - for p in path.rglob("*") - if p.is_file() and p.suffix.lower() in {".md", ".json", ".yml", ".yaml"} + candidate + for candidate in path.rglob("*") + if candidate.is_file() + and candidate.suffix.lower() in {".md", ".json", ".yml", ".yaml"} ) return sorted(set(files)) -def load_manifest(errors: list[str]) -> dict: - text = read_text(MANIFEST_PATH, errors) - if not text: - return {} +def reject_duplicate_object_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]: + result: dict[str, Any] = {} + normalized: set[str] = set() + for key, value in pairs: + if not isinstance(key, str): + raise ValidationError("JSON object keys must be strings") + folded = key.casefold() + if folded in normalized: + raise ValidationError(f"duplicate JSON key: {key}") + normalized.add(folded) + result[key] = value + return result + + +def load_json_strict(path: Path) -> dict[str, Any]: + try: + value = json.loads( + path.read_text(encoding="utf-8"), + object_pairs_hook=reject_duplicate_object_pairs, + ) + except (OSError, UnicodeError, json.JSONDecodeError, ValidationError) as exc: + raise ValidationError(f"{path.name}: invalid JSON: {exc}") from exc + if not isinstance(value, dict): + raise ValidationError(f"{path.name}: top-level value must be an object") + return value + + +def load_yaml_strict(text: str) -> dict[str, Any]: + if yaml is None: + raise ValidationError("PyYAML is required for structural workflow validation") + + class UniqueKeyLoader(yaml.SafeLoader): + pass + + # GitHub uses YAML 1.2 semantics for the ``on`` key. PyYAML's legacy 1.1 + # boolean resolver would otherwise turn it into True. + for initial, resolvers in list(UniqueKeyLoader.yaml_implicit_resolvers.items()): + UniqueKeyLoader.yaml_implicit_resolvers[initial] = [ + resolver + for resolver in resolvers + if resolver[0] != "tag:yaml.org,2002:bool" + ] + + def construct_mapping( + loader: UniqueKeyLoader, node: Any, deep: bool = False + ) -> dict[str, Any]: + pairs = loader.construct_pairs(node, deep=deep) + result: dict[str, Any] = {} + normalized: set[str] = set() + for key, value in pairs: + if not isinstance(key, str): + raise ValidationError("workflow mapping keys must be strings") + folded = key.casefold() + if folded in normalized: + raise ValidationError(f"duplicate workflow key: {key}") + normalized.add(folded) + result[key] = value + return result + + UniqueKeyLoader.add_constructor( + yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping + ) try: - manifest = json.loads(text) - except json.JSONDecodeError as exc: - fail(f"manifest JSON parse failed: {exc}", errors) + value = yaml.load(text, Loader=UniqueKeyLoader) + except ValidationError: + raise + except yaml.YAMLError as exc: + raise ValidationError(f"workflow YAML parse failed: {exc}") from exc + if not isinstance(value, dict): + raise ValidationError("workflow top-level value must be an object") + return value + + +def load_manifest(errors: list[str]) -> dict[str, Any]: + try: + manifest = load_json_strict(MANIFEST_PATH) + except ValidationError as exc: + fail(str(exc), errors) return {} if manifest.get("schema") != "hawkinsoperations-command-center-invariants-v1": fail("manifest schema mismatch", errors) @@ -157,90 +258,830 @@ def load_manifest(errors: list[str]) -> dict: return manifest -def check_required_files(manifest: dict, errors: list[str]) -> None: +def validate_source_manifest(value: dict[str, Any]) -> list[str]: + errors: list[str] = [] + allowed_root = {"schema", "manifest_id", "repositories", "constraints"} + if set(value) != allowed_root: + errors.append( + f"source manifest root keys must be exactly {sorted(allowed_root)}" + ) + if value.get("schema") != "hawkinsoperations-convergence-source-manifest-v1": + errors.append("source manifest schema mismatch") + if value.get("manifest_id") != "HAWKINSOPERATIONS_SEVEN_SOURCE_PR_HEAD_MATRIX_V1": + errors.append("source manifest ID mismatch") + entries = value.get("repositories") + if not isinstance(entries, list): + return [*errors, "source manifest repositories must be an ordered list"] + if len(entries) != 7: + errors.append("source manifest must contain exactly seven entries") + seen: set[str] = set() + observed: list[str] = [] + for index, entry in enumerate(entries): + if not isinstance(entry, dict): + errors.append(f"source manifest entry {index} must be an object") + continue + repository = entry.get("repository") + if not isinstance(repository, str): + errors.append(f"source manifest entry {index} repository must be a string") + continue + folded = repository.casefold() + if folded in seen: + errors.append(f"source manifest repository duplicated: {repository}") + seen.add(folded) + observed.append(repository) + expected_full = f"HawkinsOperations/{repository}" + if entry.get("canonical_repository") != expected_full: + errors.append(f"source manifest canonical owner mismatch: {repository}") + if repository == ".github": + if set(entry) != { + "repository", + "canonical_repository", + "revision_source", + "tree_source", + }: + errors.append(".github source entry has an unsupported shape") + if entry.get("revision_source") != "github_event_sha": + errors.append(".github source entry must use github_event_sha") + if entry.get("tree_source") != "github_event_tree": + errors.append(".github source entry must use github_event_tree") + else: + if set(entry) != { + "repository", + "canonical_repository", + "revision", + "reviewed_tree_sha", + }: + errors.append(f"source manifest entry has an unsupported shape: {repository}") + if re.fullmatch(r"[0-9a-f]{40}", str(entry.get("revision", ""))) is None: + errors.append(f"source manifest revision is not immutable: {repository}") + if re.fullmatch( + r"[0-9a-f]{40}", str(entry.get("reviewed_tree_sha", "")) + ) is None: + errors.append(f"source manifest reviewed tree is not immutable: {repository}") + if observed != EXACT_REPOSITORIES: + errors.append("source manifest repositories must equal the exact canonical order") + constraints = value.get("constraints") + expected_constraints = { + "exact_repository_count": 7, + "read_only": True, + "default_branch_fallback": False, + "require_detached_exact_revision": True, + "record_checked_revisions": True, + "consumer_outputs_are_not_authority": True, + "proof_ceiling": PROOF_CEILING, + } + if constraints != expected_constraints: + errors.append("source manifest constraints do not match the fail-closed contract") + return errors + + +def load_source_manifest(errors: list[str]) -> dict[str, Any]: + try: + manifest = load_json_strict(SOURCE_MANIFEST_PATH) + except ValidationError as exc: + fail(str(exc), errors) + return {} + for error in validate_source_manifest(manifest): + fail(error, errors) + return manifest + + +def check_required_files(manifest: dict[str, Any], errors: list[str]) -> None: required = manifest.get("required_route_files", []) if not isinstance(required, list) or not required: fail("manifest required_route_files must be a non-empty list", errors) return + if "governance/CONVERGENCE_SOURCE_MANIFEST.json" not in required: + fail("command-center manifest must require the convergence source manifest", errors) for item in required: - rel = Path(str(item)) - if rel.is_absolute() or ".." in rel.parts: + rel = PurePosixPath(str(item)) + if rel.is_absolute() or ".." in rel.parts or "\\" in str(item): fail(f"invalid required route path: {item}", errors) continue - if not (ROOT / rel).is_file(): + if not (ROOT / Path(*rel.parts)).is_file(): fail(f"missing required route file: {item}", errors) +def walk(value: Any, path: tuple[str, ...] = ()): + yield path, value + if isinstance(value, dict): + for key, nested in value.items(): + yield from walk(nested, (*path, str(key))) + elif isinstance(value, list): + for index, nested in enumerate(value): + yield from walk(nested, (*path, str(index))) + + +def scalar_is_false(value: Any) -> bool: + return value is False or (isinstance(value, str) and value.casefold() == "false") + + def unsafe_workflow_findings(text: str) -> list[str]: - patterns = { - "contents write permission": r"contents:\s*write", - "pull-request write permission": r"pull-requests:\s*write", - "direct git push": r"\bgit\s+push\b", - "git commit mutation": r"\bgit\s+commit\b", - "PR create or merge mutation": r"\bgh\s+pr\s+(?:create|merge)\b", - "auto-merge mutation": r"\bauto-merge\b", - "Lifetime Case Ledger mutation": r"ho_factory[^\n]*(?:lifetime|ledger)[^\n]*(?:append|correct|mutate)", - } - return [label for label, pattern in patterns.items() if re.search(pattern, text, re.IGNORECASE)] + findings: list[str] = [] + try: + workflow = load_yaml_strict(text) + except ValidationError as exc: + return [str(exc)] + allowed_root_keys = {"name", "on", "permissions", "jobs"} + if set(workflow) != allowed_root_keys: + findings.append("workflow root shape is not closed") + triggers = workflow.get("on") + if not isinstance(triggers, dict): + findings.append("workflow trigger declaration must be an object") + else: + allowed_triggers = {"pull_request", "push", "workflow_dispatch", "schedule"} + if set(triggers) != allowed_triggers: + findings.append("workflow triggers differ from the approved read-only set") + if "pull_request_target" in triggers: + findings.append("pull_request_target is forbidden") + schedule = triggers.get("schedule") + if not isinstance(schedule, list) or not schedule: + findings.append("scheduled drift detection is required") + if not isinstance(triggers.get("workflow_dispatch"), dict): + findings.append("manual read-only dispatch is required") -def extract_workflow_repositories(text: str) -> list[str]: - match = re.search(r"^\s*repos=\(\s*$([\s\S]*?)^\s*\)\s*$", text, re.MULTILINE) - if not match: - return [] - return [line.strip() for line in match.group(1).splitlines() if line.strip() and not line.lstrip().startswith("#")] + if workflow.get("permissions") != {"contents": "read"}: + findings.append("root permissions must be exactly contents: read") + jobs = workflow.get("jobs") + if not isinstance(jobs, dict) or set(jobs) != { + "command-center-invariants", + "seven-repository-convergence", + }: + findings.append("workflow jobs must be the exact approved pair") + checkout_count = 0 + source_set_checkout = False + upload_count = 0 + for path, value in walk(workflow): + key = path[-1].casefold() if path else "" + if key == "continue-on-error": + findings.append("continue-on-error is forbidden") + if key == "permissions": + if path != ("permissions",): + findings.append("job or step permission override is forbidden") + if key in {"contents", "actions", "checks", "issues", "packages", "pages", + "pull-requests", "security-events", "statuses", "id-token"}: + if isinstance(value, str) and value.casefold() == "write": + findings.append(f"write permission is forbidden at {'/'.join(path)}") + if key == "if" and isinstance(value, str): + if re.search(r"\balways\s*\(\s*\)", value, re.IGNORECASE): + findings.append("always() is forbidden because it can neutralize failure ordering") + if key == "run" and isinstance(value, str) and "\n" in value: + if "set -euo pipefail" not in value: + findings.append("multiline shell steps must enable strict exit propagation") + if key == "uses" and isinstance(value, str): + match = re.fullmatch(r"([^@]+)@([0-9a-f]{40})", value) + if match is None: + findings.append(f"action must be pinned to an immutable SHA: {value}") + elif PINNED_ACTIONS.get(match.group(1)) != match.group(2): + findings.append(f"action SHA is not allowlisted: {value}") + if value.startswith("actions/checkout@"): + checkout_count += 1 + step_path = path[:-1] + step: Any = workflow + for component in step_path: + step = step[int(component)] if isinstance(step, list) else step[component] + checkout_with = step.get("with") if isinstance(step, dict) else None + if not isinstance(checkout_with, dict) or not scalar_is_false( + checkout_with.get("persist-credentials") + ): + findings.append("checkout must set persist-credentials: false") + if isinstance(checkout_with, dict) and checkout_with.get("path") == "source-set/.github": + source_set_checkout = True + expected_ref = "${{ github.event.pull_request.head.sha || github.sha }}" + if checkout_with.get("ref") != expected_ref: + findings.append( + "source-set .github checkout must use the immutable event SHA" + ) + if value.startswith("actions/upload-artifact@"): + upload_count += 1 + step_path = path[:-1] + step = workflow + for component in step_path: + step = step[int(component)] if isinstance(step, list) else step[component] + upload_with = step.get("with") if isinstance(step, dict) else None + expected_paths = ( + "verification-artifacts/source-revisions.json\n" + "verification-artifacts/verification-summary.json\n" + ) + if ( + not isinstance(upload_with, dict) + or upload_with.get("path") != expected_paths + or upload_with.get("if-no-files-found") != "error" + ): + findings.append( + "artifact upload must use the exact sanitized two-file allowlist" + ) + + if checkout_count != 2: + findings.append( + "workflow must perform exactly one credential-bounded checkout in each job" + ) + if not source_set_checkout: + findings.append("seven-source job must checkout .github under source-set/.github") + if upload_count != 1: + findings.append("workflow must contain exactly one sanitized artifact upload") + + forbidden_text_patterns = { + "pull_request_target": r"(?m)^\s*pull_request_target\s*:", + "direct push": r"\bgit\s+push\b", + "remote mutation": r"\bgit\s+(?:commit|tag)\b", + "PR mutation": r"\b(?:gh\s+pr\s+(?:create|merge|ready|review)|gh\s+api[^\n]*(?:POST|PATCH|PUT|DELETE))\b", + "HTTP PR mutation": r"\bcurl\b[^\n]*(?:-X|--request)\s*(?:POST|PATCH|PUT|DELETE)[^\n]*(?:api\.github\.com|/pulls\b)", + "auto-merge": r"\bauto-merge\b", + "ledger mutation": r"\b(?:lifetime|ledger)[^\n]*(?:append|correct|mutate|write)\b", + "runtime mutation": r"\b(?:runtime|endpoint|wazuh|splunk|cribl)[^\n]*(?:mutate|deploy|configure|restart|write)\b", + "proof promotion": r"\b(?:proof|public.safe)[^\n]*(?:promote|publish|approve)\b", + "swallowed failure": r"(?:\|\|\s*true\b|\bset\s+\+e\b|\btrap\b[^\n]*\bexit\s+0\b)", + "backgrounded command": r"(?m)(? None: - workflow = read_text(WORKFLOW_PATH, errors) - declared = manifest.get("cross_repo_repositories") - if declared != EXACT_REPOSITORIES: - fail("manifest cross_repo_repositories must list the exact seven repositories in canonical order", errors) required_fragments = [ - "permissions:\n contents: read", "seven-repository-convergence:", - "REQUESTED_REF:", - "git ls-remote --exit-code --heads", - 'ref="main"', - "actions/setup-python@v5", - "pip install --disable-pip-version-check -e source-set/hoxline", - "source-revisions.txt", + "governance/CONVERGENCE_SOURCE_MANIFEST.json", + "--emit-source-manifest", + "--verify-source-set", + "--verify-remote-main-content", + "while IFS=$'\\t' read -r repo revision", + 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 'git -C "source-set/$repo" checkout --quiet --detach "$revision"', + "source-revisions.json", + "HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA", + "verify_detection_contract.py", + "verify_detection_promotion_matrix.py", + "verify_validation_registry.py", + "verify_all_validation_packages.py", + "verify_validation_contract.py", + "verify_detection_proof_status_index.py", + "verify_proof_integrity.py", + "verify-public-status-source-contract.py", "hoxline-case-growth-convergence-verify", + "case-growth index", "case-growth verify", + "review batch run", + "review batch verify", + "public-status:generate:check", "public-status:verify", - "Sanitize convergence diagnostics", - "[local-path-redacted]", - "actions/upload-artifact@v4", - "if: always()", - "if: always() && steps.sanitize.outcome == 'success'", + "public-status:self-test", + "public-status:owner-self-test", + "public-status:source-checkout-test", + "public-status:freshness-reachability-test", + "public-status:nested-claim-test", + "public-status:eol-self-test", + "git diff --check", + "--write-verification-summary", + "--validate-artifacts", + "verification-artifacts/source-revisions.json", + "verification-artifacts/verification-summary.json", ] for fragment in required_fragments: - if fragment not in workflow: - fail(f"cross-repo workflow missing required behavior: {fragment}", errors) - workflow_repositories = extract_workflow_repositories(workflow) - if workflow_repositories != EXACT_REPOSITORIES: - fail("cross-repo workflow checkout array must equal the exact ordered seven-repository set with no duplicates", errors) - for finding in unsafe_workflow_findings(workflow): + if fragment not in text: + findings.append(f"workflow missing required behavior: {fragment}") + return sorted(set(findings)) + + +def check_cross_repo_workflow( + manifest: dict[str, Any], + source_manifest: dict[str, Any], + errors: list[str], +) -> None: + workflow_text = read_text(WORKFLOW_PATH, errors) + declared = manifest.get("cross_repo_repositories") + if declared != EXACT_REPOSITORIES: + fail( + "manifest cross_repo_repositories must list the exact seven repositories in canonical order", + errors, + ) + if [entry.get("repository") for entry in source_manifest.get("repositories", [])] != EXACT_REPOSITORIES: + fail("source manifest and invariant repository order disagree", errors) + for finding in unsafe_workflow_findings(workflow_text): fail(f"cross-repo workflow permits unsafe behavior: {finding}", errors) def check_workflow_hostile_self_test(errors: list[str]) -> None: + base = WORKFLOW_PATH.read_text(encoding="utf-8") hostile_cases = { - "contents write": "permissions:\n contents: write", - "direct main push": "run: git push origin main", - "commit mutation": "run: git commit -m unsafe", - "PR merge": "run: gh pr merge 1", - "ledger append": "run: python ho_factory.py lifetime-ledger-append", + "write permission": base.replace("contents: read", "issues: write", 1), + "pull_request_target": base.replace("pull_request:", "pull_request_target:", 1), + "continue-on-error": base.replace( + "run: python scripts/verify-command-center-invariants.py --self-test", + "continue-on-error: true\n run: python scripts/verify-command-center-invariants.py --self-test", + 1, + ), + "persisted credentials": base.replace( + "persist-credentials: false", "persist-credentials: true", 1 + ), + "mutable action": base.replace( + f"actions/checkout@{PINNED_ACTIONS['actions/checkout']}", + "actions/checkout@v4", + 1, + ), + "swallowed failure": base.replace("set -euo pipefail", "set -euo pipefail\n false || true", 1), + "direct push": base.replace("set -euo pipefail", "set -euo pipefail\n git push origin main", 1), + "always step": base.replace( + "- name: Validate upload artifacts", + "- name: Validate upload artifacts\n if: always()", + 1, + ), } for name, hostile in hostile_cases.items(): if not unsafe_workflow_findings(hostile): - fail(f"workflow hostile self-test failed to detect {name}", errors) - missing_repo = "repos=(\n .github\n hoxline\n)" - duplicate_repo = "repos=(\n .github\n .github\n hoxline\n)" - if extract_workflow_repositories(missing_repo) == EXACT_REPOSITORIES: - fail("workflow hostile self-test accepted a missing-repository checkout set", errors) - if len(set(extract_workflow_repositories(duplicate_repo))) == len(extract_workflow_repositories(duplicate_repo)): - fail("workflow hostile self-test did not recognize a duplicate-repository checkout set", errors) + fail(f"workflow hostile self-test accepted {name}", errors) + + try: + source = load_json_strict(SOURCE_MANIFEST_PATH) + except ValidationError as exc: + fail(f"source-manifest hostile self-test precondition failed: {exc}", errors) + return + for name, mutate in { + "missing repository": lambda value: value["repositories"].pop(), + "duplicate repository": lambda value: value["repositories"].append( + dict(value["repositories"][0]) + ), + "mutable revision": lambda value: value["repositories"][1].update( + {"revision": "main"} + ), + "owner spoof": lambda value: value["repositories"][1].update( + {"canonical_repository": "NotHawkinsOperations/hawkinsoperations-detections"} + ), + "fallback enabled": lambda value: value["constraints"].update( + {"default_branch_fallback": True} + ), + }.items(): + candidate = json.loads(json.dumps(source)) + mutate(candidate) + if not validate_source_manifest(candidate): + fail(f"source-manifest hostile self-test accepted {name}", errors) + + +def canonical_origin(value: str) -> str: + normalized = value.strip().rstrip("/").casefold() + if normalized.startswith("git@github.com:"): + normalized = "https://github.com/" + normalized.removeprefix("git@github.com:") + elif normalized.startswith("ssh://git@github.com/"): + normalized = "https://github.com/" + normalized.removeprefix( + "ssh://git@github.com/" + ) + if not normalized.endswith(".git"): + normalized += ".git" + return normalized + + +def git(repo: Path, *args: str) -> str: + result = subprocess.run( + ["git", "-C", str(repo), *args], + check=False, + capture_output=True, + text=True, + ) + if result.returncode: + raise ValidationError( + f"{repo.name}: git {' '.join(args)} failed: {result.stderr.strip()}" + ) + return result.stdout.strip() + + +def resolved_source_manifest( + manifest: dict[str, Any], event_sha: str, event_tree_sha: str | None = None +) -> dict[str, Any]: + if re.fullmatch(r"[0-9a-f]{40}", event_sha) is None: + raise ValidationError("event SHA must be a lowercase 40-character Git SHA") + if validate_source_manifest(manifest): + raise ValidationError("cannot resolve an invalid source manifest") + if event_tree_sha is None: + event_tree_sha = git(ROOT, "rev-parse", f"{event_sha}^{{tree}}") + if re.fullmatch(r"[0-9a-f]{40}", event_tree_sha) is None: + raise ValidationError("event tree SHA must be a lowercase 40-character Git SHA") + entries = [] + for entry in manifest["repositories"]: + revision = event_sha if entry["repository"] == ".github" else entry["revision"] + reviewed_tree = ( + event_tree_sha + if entry["repository"] == ".github" + else entry["reviewed_tree_sha"] + ) + entries.append( + { + "repository": entry["repository"], + "canonical_repository": entry["canonical_repository"], + "revision": revision, + "reviewed_tree_sha": reviewed_tree, + } + ) + payload = { + "schema": "hawkinsoperations-resolved-convergence-source-set-v1", + "manifest_id": manifest["manifest_id"], + "repositories": entries, + "constraints": manifest["constraints"], + } + payload["manifest_sha256"] = hashlib.sha256( + json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8") + ).hexdigest() + return payload + + +def validate_resolved_manifest(value: dict[str, Any]) -> list[str]: + errors: list[str] = [] + allowed = { + "schema", + "manifest_id", + "repositories", + "constraints", + "manifest_sha256", + } + if set(value) != allowed: + errors.append("resolved source manifest has unsupported fields") + return errors + if value.get("schema") != "hawkinsoperations-resolved-convergence-source-set-v1": + errors.append("resolved source manifest schema mismatch") + repositories = value.get("repositories") + if not isinstance(repositories, list) or len(repositories) != 7: + errors.append("resolved source manifest must contain exactly seven entries") + return errors + observed: list[str] = [] + for entry in repositories: + if not isinstance(entry, dict) or set(entry) != { + "repository", + "canonical_repository", + "revision", + "reviewed_tree_sha", + }: + errors.append("resolved source entry has unsupported shape") + continue + repository = entry.get("repository") + observed.append(str(repository)) + if entry.get("canonical_repository") != f"HawkinsOperations/{repository}": + errors.append(f"resolved source owner mismatch: {repository}") + if re.fullmatch(r"[0-9a-f]{40}", str(entry.get("revision", ""))) is None: + errors.append(f"resolved source revision invalid: {repository}") + if re.fullmatch( + r"[0-9a-f]{40}", str(entry.get("reviewed_tree_sha", "")) + ) is None: + errors.append(f"resolved source reviewed tree invalid: {repository}") + if observed != EXACT_REPOSITORIES or len(set(observed)) != 7: + errors.append("resolved source repositories differ from exact canonical set") + if value.get("constraints") != { + "exact_repository_count": 7, + "read_only": True, + "default_branch_fallback": False, + "require_detached_exact_revision": True, + "record_checked_revisions": True, + "consumer_outputs_are_not_authority": True, + "proof_ceiling": PROOF_CEILING, + }: + errors.append("resolved source constraints mismatch") + unsigned = {key: nested for key, nested in value.items() if key != "manifest_sha256"} + expected = hashlib.sha256( + json.dumps(unsigned, sort_keys=True, separators=(",", ":")).encode("utf-8") + ).hexdigest() + if value.get("manifest_sha256") != expected: + errors.append("resolved source manifest digest mismatch") + return errors + + +def verify_source_set( + source_set: Path, resolved: dict[str, Any] +) -> tuple[list[dict[str, Any]], list[str]]: + errors = validate_resolved_manifest(resolved) + if errors: + return [], errors + if not source_set.is_dir() or source_set.is_symlink(): + return [], ["source-set root must be a real directory"] + actual_names = sorted( + path.name + for path in source_set.iterdir() + if path.is_dir() and not path.is_symlink() + ) + if actual_names != sorted(EXACT_REPOSITORIES): + errors.append("source-set directory inventory must equal exactly seven repositories") + return [], errors + records: list[dict[str, Any]] = [] + for entry in resolved["repositories"]: + repository = entry["repository"] + repo_path = source_set / repository + try: + if repo_path.resolve().parent != source_set.resolve(): + raise ValidationError(f"{repository}: repository path escapes source-set root") + head = git(repo_path, "rev-parse", "HEAD") + if head != entry["revision"]: + raise ValidationError( + f"{repository}: checked HEAD {head} differs from manifest {entry['revision']}" + ) + tree = git(repo_path, "rev-parse", "HEAD^{tree}") + if tree != entry["reviewed_tree_sha"]: + raise ValidationError( + f"{repository}: checked tree {tree} differs from reviewed content " + f"{entry['reviewed_tree_sha']}" + ) + branch = git(repo_path, "rev-parse", "--abbrev-ref", "HEAD") + if branch != "HEAD": + raise ValidationError(f"{repository}: checkout must be detached at exact revision") + origin = git(repo_path, "remote", "get-url", "origin") + if canonical_origin(origin) != canonical_origin(CANONICAL_ORIGINS[repository]): + raise ValidationError(f"{repository}: canonical origin mismatch") + status = git(repo_path, "status", "--porcelain=v1", "--untracked-files=all") + if status: + raise ValidationError(f"{repository}: source checkout is dirty") + records.append( + { + "repository": repository, + "canonical_repository": entry["canonical_repository"], + "checked_sha": head, + "checked_tree_sha": tree, + "detached": True, + "clean": True, + } + ) + except ValidationError as exc: + errors.append(str(exc)) + return records, errors + + +def compare_observed_main_trees( + resolved: dict[str, Any], observed: dict[str, str] +) -> list[str]: + errors = validate_resolved_manifest(resolved) + if errors: + return errors + expected = { + entry["repository"]: entry["reviewed_tree_sha"] + for entry in resolved["repositories"] + if entry["repository"] != ".github" + } + if set(observed) != set(expected): + return ["remote main observations must cover exactly the six sibling repositories"] + for repository, expected_tree in expected.items(): + actual_tree = observed.get(repository) + if actual_tree != expected_tree: + errors.append( + f"{repository}: current main content tree {actual_tree} differs from " + f"reviewed tree {expected_tree}; refresh the reviewed source matrix" + ) + return errors + + +def verify_remote_main_content( + source_set: Path, resolved: dict[str, Any] +) -> list[str]: + errors = validate_resolved_manifest(resolved) + if errors: + return errors + observed: dict[str, str] = {} + for entry in resolved["repositories"]: + repository = entry["repository"] + if repository == ".github": + continue + url = CANONICAL_ORIGINS[repository] + result = subprocess.run( + ["git", "ls-remote", "--exit-code", url, "refs/heads/main"], + check=False, + capture_output=True, + text=True, + ) + fields = result.stdout.strip().split() + if result.returncode != 0 or len(fields) != 2 or fields[1] != "refs/heads/main": + errors.append(f"{repository}: current main observation is unavailable") + continue + main_sha = fields[0] + if re.fullmatch(r"[0-9a-f]{40}", main_sha) is None: + errors.append(f"{repository}: current main observation is malformed") + continue + repo_path = source_set / repository + fetch = subprocess.run( + ["git", "-C", str(repo_path), "fetch", "--quiet", "--depth=1", "origin", main_sha], + check=False, + capture_output=True, + text=True, + ) + if fetch.returncode: + errors.append(f"{repository}: current main content cannot be fetched") + continue + try: + observed[repository] = git(repo_path, "rev-parse", f"{main_sha}^{{tree}}") + except ValidationError as exc: + errors.append(str(exc)) + if errors: + return errors + return compare_observed_main_trees(resolved, observed) + + +def is_private_scalar(value: str) -> bool: + decoded = value + for _ in range(3): + next_value = unquote(decoded) + if next_value == decoded: + break + decoded = next_value + variants = {value, decoded, decoded.replace("\\", "/")} + for candidate in variants: + lowered = candidate.casefold() + if ( + PureWindowsPath(candidate).is_absolute() + or PurePosixPath(candidate).is_absolute() + or re.match(r"^[a-z]:[^/\\]", lowered) + or lowered.startswith(("\\\\", "//", "file:", "~", "$home", "${home}")) + or "../" in lowered + or "/users/" in lowered + or "/home/" in lowered + or "/raylee/" in lowered + ): + return True + if re.search( + r"(?:github[_-]?pat_|ghp_|begin (?:rsa |openssh )?private key|" + r"\b(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}\b|" + r"\b172\.(?:1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}\b|" + r"\b192\.168\.\d{1,3}\.\d{1,3}\b|" + r"@[a-z0-9.-]+\.[a-z]{2,}\b|" + r"\b(?:customer|mufg)\b)", + lowered, + ): + return True + return False + + +def validate_artifact_payloads(directory: Path) -> list[str]: + errors: list[str] = [] + if not directory.is_dir() or directory.is_symlink(): + return ["artifact path must be a real directory"] + files = {path.name for path in directory.iterdir() if path.is_file()} + if files != EXPECTED_ARTIFACT_FILES: + errors.append( + f"artifact file set must be exactly {sorted(EXPECTED_ARTIFACT_FILES)}" + ) + return errors + for path in directory.iterdir(): + if path.is_symlink() or not path.is_file(): + errors.append(f"artifact directory contains unsupported entry: {path.name}") + payloads: dict[str, dict[str, Any]] = {} + for name in EXPECTED_ARTIFACT_FILES: + try: + payloads[name] = load_json_strict(directory / name) + except ValidationError as exc: + errors.append(str(exc)) + revisions = payloads.get("source-revisions.json") + if revisions is not None: + resolved_fields = { + key: value + for key, value in revisions.items() + if key != "checked_repositories" + } + for error in validate_resolved_manifest(resolved_fields): + errors.append(f"source-revisions.json: {error}") + checked = revisions.get("checked_repositories") + expected_by_repo = { + entry["repository"]: entry["revision"] + for entry in revisions.get("repositories", []) + if isinstance(entry, dict) + } + if not isinstance(checked, list) or len(checked) != 7: + errors.append("source-revisions.json: checked_repositories must contain seven records") + else: + observed_checked: list[str] = [] + for entry in checked: + if not isinstance(entry, dict) or set(entry) != { + "repository", + "canonical_repository", + "checked_sha", + "checked_tree_sha", + "detached", + "clean", + }: + errors.append( + "source-revisions.json: checked repository record has unsupported fields" + ) + continue + repository = entry.get("repository") + observed_checked.append(str(repository)) + if entry.get("canonical_repository") != f"HawkinsOperations/{repository}": + errors.append( + f"source-revisions.json: checked owner mismatch: {repository}" + ) + if entry.get("checked_sha") != expected_by_repo.get(str(repository)): + errors.append( + f"source-revisions.json: checked SHA mismatch: {repository}" + ) + reviewed_trees = { + item["repository"]: item.get("reviewed_tree_sha") + for item in revisions.get("repositories", []) + if isinstance(item, dict) + } + if entry.get("checked_tree_sha") != reviewed_trees.get(str(repository)): + errors.append( + f"source-revisions.json: checked tree mismatch: {repository}" + ) + if entry.get("detached") is not True or entry.get("clean") is not True: + errors.append( + f"source-revisions.json: checked state is not clean and detached: {repository}" + ) + if observed_checked != EXACT_REPOSITORIES: + errors.append( + "source-revisions.json: checked repositories differ from exact order" + ) + summary = payloads.get("verification-summary.json") + if summary is not None: + allowed = { + "schema", + "status", + "repository_count", + "repositories", + "checks", + "mutation_boundary", + "proof_ceiling", + } + if set(summary) != allowed: + errors.append("verification summary has unsupported fields") + if summary.get("schema") != "hawkinsoperations-convergence-verification-summary-v1": + errors.append("verification summary schema mismatch") + if summary.get("status") != "PASS": + errors.append("verification summary status must be PASS") + if summary.get("repository_count") != 7: + errors.append("verification summary repository count must be seven") + if summary.get("repositories") != EXACT_REPOSITORIES: + errors.append("verification summary repository set mismatch") + checks = summary.get("checks") + if not isinstance(checks, list) or len(checks) != len(set(checks)) or len(checks) < 20: + errors.append("verification summary check list is missing or duplicated") + if summary.get("mutation_boundary") != { + "repository_writes": False, + "pull_request_mutation": False, + "merge": False, + "ledger_mutation": False, + "runtime_mutation": False, + "proof_promotion": False, + }: + errors.append("verification summary mutation boundary mismatch") + if summary.get("proof_ceiling") != PROOF_CEILING: + errors.append("verification summary proof ceiling mismatch") + for name, payload in payloads.items(): + for path, value in walk(payload): + if isinstance(value, str) and is_private_scalar(value): + errors.append( + f"{name}: private or unsafe scalar at {'/'.join(path) or ''}" + ) + return errors + + +def write_json_atomic(path: Path, value: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + temporary = path.with_name(path.name + ".tmp") + temporary.write_text( + json.dumps(value, indent=2, sort_keys=False) + "\n", encoding="utf-8", newline="\n" + ) + temporary.replace(path) + + +def write_verification_summary(path: Path) -> None: + checks = [ + "command_center_invariants", + "command_center_hostile_workflow_tests", + "exact_seven_source_checkout", + "detection_contract", + "detection_promotion_matrix", + "detection_reverse_inventory_and_hostile_tests", + "validation_registry", + "validation_package_sweep", + "validation_source_and_report_parity", + "validation_claim_boundary", + "proof_status_index", + "proof_reverse_inventory", + "proof_integrity", + "platform_public_status_source_contract", + "platform_case_growth_convergence", + "platform_mutation_boundary", + "hoxline_case_growth_pair", + "hoxline_expanded_batch", + "hoxline_replay", + "hoxline_hostile_tests", + "website_source_owner_and_freshness", + "website_nested_claim_and_eol_tests", + "website_static_build", + ] + write_json_atomic( + path, + { + "schema": "hawkinsoperations-convergence-verification-summary-v1", + "status": "PASS", + "repository_count": 7, + "repositories": EXACT_REPOSITORIES, + "checks": checks, + "mutation_boundary": { + "repository_writes": False, + "pull_request_mutation": False, + "merge": False, + "ledger_mutation": False, + "runtime_mutation": False, + "proof_promotion": False, + }, + "proof_ceiling": PROOF_CEILING, + }, + ) def check_required_text(errors: list[str]) -> None: @@ -267,7 +1108,6 @@ def check_project_boundaries(all_text: str, errors: list[str]) -> None: for needle in required: if needle.lower() not in lowered: fail(f"missing project boundary wording: {needle}", errors) - forbidden = [ r"Project #1\s+is\s+an\s+active\s+reviewer\s+route", r"Project #1.{0,80}canonical", @@ -294,7 +1134,6 @@ def check_ceiling_boundaries(all_text: str, errors: list[str]) -> None: for needle in required: if needle.lower() not in lowered: fail(f"missing proof-boundary wording: {needle}", errors) - forbidden_patterns = [ r"\brendering\s+is\s+proof\b", r"\bGitHub rendering\s+is\s+proof\b", @@ -311,19 +1150,30 @@ def check_standing_controls(all_text: str, errors: list[str]) -> None: for issue in ("#8", "#10"): if issue not in all_text: fail(f"missing standing control issue reference: {issue}", errors) - if "Do not close unless Raylee explicitly approves replacing the standing-control role" not in all_text: + required = ( + "Do not close unless Raylee explicitly approves replacing " + "the standing-control role" + ) + if required not in all_text: fail("missing explicit replacement-approval boundary for .github#8/#10", errors) def check_exposure(text_files: list[Path], errors: list[str]) -> None: token_prefixes = ["AK" + "IA", "ghp" + "_", "github" + "_pat" + "_"] - private_ip = re.compile(r"\b(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})\b") + private_ip = re.compile( + r"\b(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|" + r"172\.(?:1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}|" + r"192\.168\.\d{1,3}\.\d{1,3})\b" + ) drive_path = re.compile(r"\b[A-Za-z]:\\") private_key = re.compile(r"BEGIN (?:RSA |OPENSSH )?PRIVATE KEY") for path in text_files: rel = path.relative_to(ROOT).as_posix() text = path.read_text(encoding="utf-8", errors="ignore") for line_no, line in enumerate(text.splitlines(), start=1): + # Defensive test literals in this verifier are never uploaded or public data. + if rel == "scripts/verify-command-center-invariants.py": + continue if drive_path.search(line): fail(f"{rel}:{line_no} exposes a local Windows path", errors) if private_ip.search(line): @@ -335,50 +1185,138 @@ def check_exposure(text_files: list[Path], errors: list[str]) -> None: fail(f"{rel}:{line_no} exposes a token-looking prefix", errors) -def check_identity_and_claim_context(text_files: list[Path], errors: list[str]) -> None: +def check_identity_and_claim_context( + text_files: list[Path], errors: list[str] +) -> None: for path in text_files: rel = path.relative_to(ROOT).as_posix() lines = path.read_text(encoding="utf-8", errors="ignore").splitlines() for line_no, line in enumerate(lines, start=1): lowered = line.lower() - if "hawkinsops" in lowered and not any(marker in lowered for marker in ("legacy", "reference", "v1", "prior", "not current")): - fail(f"{rel}:{line_no} uses HawkinsOps outside legacy/reference context", errors) + if "hawkinsops" in lowered and not any( + marker in lowered + for marker in ("legacy", "reference", "v1", "prior", "not current") + ): + fail( + f"{rel}:{line_no} uses HawkinsOps outside legacy/reference context", + errors, + ) for phrase in BLOCKED_CLAIMS: - phrase_pattern = re.compile(rf"(? int: +def run_full_verification(self_test: bool) -> list[str]: errors: list[str] = [] manifest = load_manifest(errors) + source_manifest = load_source_manifest(errors) check_required_files(manifest, errors) - check_cross_repo_workflow(manifest, errors) - if "--self-test" in sys.argv: + check_cross_repo_workflow(manifest, source_manifest, errors) + if self_test: check_workflow_hostile_self_test(errors) check_required_text(errors) - text_files = iter_text_files() - all_text = "\n".join(path.read_text(encoding="utf-8", errors="ignore") for path in text_files) + all_text = "\n".join( + path.read_text(encoding="utf-8", errors="ignore") for path in text_files + ) check_project_boundaries(all_text, errors) check_ceiling_boundaries(all_text, errors) check_standing_controls(all_text, errors) check_exposure(text_files, errors) check_identity_and_claim_context(text_files, errors) + return errors + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser() + parser.add_argument("--self-test", action="store_true") + parser.add_argument("--emit-source-manifest", type=Path) + parser.add_argument("--event-sha") + parser.add_argument("--verify-source-set", type=Path) + parser.add_argument("--verify-remote-main-content", type=Path) + parser.add_argument("--resolved-manifest", type=Path) + parser.add_argument("--source-revisions-output", type=Path) + parser.add_argument("--write-verification-summary", type=Path) + parser.add_argument("--validate-artifacts", type=Path) + return parser.parse_args() + + +def main() -> int: + args = parse_args() + errors: list[str] = [] + + if args.emit_source_manifest is not None: + try: + source_manifest = load_json_strict(SOURCE_MANIFEST_PATH) + resolved = resolved_source_manifest(source_manifest, str(args.event_sha or "")) + write_json_atomic(args.emit_source_manifest, resolved) + except ValidationError as exc: + errors.append(str(exc)) + elif args.verify_source_set is not None: + if args.resolved_manifest is None or args.source_revisions_output is None: + errors.append( + "--verify-source-set requires --resolved-manifest and --source-revisions-output" + ) + else: + try: + resolved = load_json_strict(args.resolved_manifest) + records, source_errors = verify_source_set(args.verify_source_set, resolved) + errors.extend(source_errors) + if not errors: + output = dict(resolved) + output["checked_repositories"] = records + # The uploaded source-revisions artifact deliberately omits origins + # and local paths; only canonical owner and immutable revisions remain. + write_json_atomic(args.source_revisions_output, output) + except ValidationError as exc: + errors.append(str(exc)) + elif args.verify_remote_main_content is not None: + if args.resolved_manifest is None: + errors.append("--verify-remote-main-content requires --resolved-manifest") + else: + try: + resolved = load_json_strict(args.resolved_manifest) + errors.extend( + verify_remote_main_content(args.verify_remote_main_content, resolved) + ) + except ValidationError as exc: + errors.append(str(exc)) + elif args.write_verification_summary is not None: + write_verification_summary(args.write_verification_summary) + elif args.validate_artifacts is not None: + errors.extend(validate_artifact_payloads(args.validate_artifacts)) + else: + errors.extend(run_full_verification(args.self_test)) if errors: print("COMMAND_CENTER_INVARIANTS=FAIL") for error in errors: print(f"- {error}") return 1 - print("COMMAND_CENTER_INVARIANTS=PASS") - print(f"checked_files={len(text_files)}") + if args.emit_source_manifest: + print("resolved_source_manifest=written") + elif args.verify_source_set: + print("checked_repositories=7") + elif args.verify_remote_main_content: + print("reviewed_main_content=6") + elif args.write_verification_summary: + print("verification_summary=written") + elif args.validate_artifacts: + print("sanitized_artifacts=2") + else: + print(f"checked_files={len(iter_text_files())}") return 0 diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py new file mode 100644 index 0000000..072d529 --- /dev/null +++ b/tests/test_command_center_workflow_safety.py @@ -0,0 +1,339 @@ +from __future__ import annotations + +import importlib.util +import json +import subprocess +import tempfile +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[1] +MODULE_PATH = REPO_ROOT / "scripts" / "verify-command-center-invariants.py" +SPEC = importlib.util.spec_from_file_location("command_center_invariants", MODULE_PATH) +assert SPEC is not None and SPEC.loader is not None +VERIFIER = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(VERIFIER) + + +class WorkflowSafetyTests(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.workflow = VERIFIER.WORKFLOW_PATH.read_text(encoding="utf-8") + cls.source_manifest = VERIFIER.load_json_strict(VERIFIER.SOURCE_MANIFEST_PATH) + + def assert_rejected(self, value: str, label: str) -> None: + self.assertTrue( + VERIFIER.unsafe_workflow_findings(value), + f"hostile workflow was accepted: {label}", + ) + + def test_current_workflow_is_structurally_safe(self) -> None: + self.assertEqual([], VERIFIER.unsafe_workflow_findings(self.workflow)) + + def test_permission_trigger_credential_and_action_attacks_fail(self) -> None: + mutations = { + "repository write token": self.workflow.replace( + "contents: read", "contents: write", 1 + ), + "issues write token": self.workflow.replace( + "contents: read", "issues: write", 1 + ), + "pull_request_target": self.workflow.replace( + "pull_request:", "pull_request_target:", 1 + ), + "persisted credentials": self.workflow.replace( + "persist-credentials: false", "persist-credentials: true", 1 + ), + "mutable action": self.workflow.replace( + f"actions/checkout@{VERIFIER.PINNED_ACTIONS['actions/checkout']}", + "actions/checkout@v4", + 1, + ), + } + for label, value in mutations.items(): + with self.subTest(label=label): + self.assert_rejected(value, label) + + def test_mutation_and_exit_neutralization_attacks_fail(self) -> None: + marker = "set -euo pipefail" + hostile_lines = { + "direct push": "git push origin main", + "PR creation": "gh pr create --title unsafe", + "HTTP PR creation": "curl -X POST https://api.github.com/repos/x/y/pulls", + "merge": "gh pr merge 1", + "ledger mutation": "python ho_factory.py lifetime-ledger-append", + "runtime mutation": "python tool.py runtime mutate", + "proof promotion": "python tool.py proof promote", + "swallowed failure": "false || true", + "set plus e": "set +e", + "unconditional success": "exit 0", + "backgrounded command": "python unsafe.py &", + } + for label, hostile in hostile_lines.items(): + with self.subTest(label=label): + self.assert_rejected( + self.workflow.replace(marker, f"{marker}\n {hostile}", 1), + label, + ) + self.assert_rejected( + self.workflow.replace( + "run: python scripts/verify-command-center-invariants.py --self-test", + "continue-on-error: true\n run: python scripts/verify-command-center-invariants.py --self-test", + 1, + ), + "continue-on-error", + ) + self.assert_rejected( + self.workflow.replace( + "- name: Validate upload artifacts", + "- name: Validate upload artifacts\n if: always()", + 1, + ), + "always", + ) + + def test_duplicate_yaml_key_fails_closed(self) -> None: + hostile = self.workflow.replace( + "permissions:\n contents: read", + "permissions:\n contents: read\npermissions:\n issues: write", + 1, + ) + findings = VERIFIER.unsafe_workflow_findings(hostile) + self.assertTrue(any("duplicate workflow key" in value for value in findings)) + + def test_missing_checkout_or_unsanitized_upload_fails(self) -> None: + self.assert_rejected( + self.workflow.replace( + 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 'printf "%s\\n" "$revision"', + 1, + ), + "missing sibling fetch", + ) + self.assert_rejected( + self.workflow.replace( + "verification-artifacts/source-revisions.json\n" + " verification-artifacts/verification-summary.json", + "verification-artifacts/", + 1, + ), + "broad upload", + ) + + def test_source_manifest_is_exact_closed_and_immutable(self) -> None: + self.assertEqual( + [], VERIFIER.validate_source_manifest(self.source_manifest) + ) + attacks = [] + missing = json.loads(json.dumps(self.source_manifest)) + missing["repositories"].pop() + attacks.append(missing) + duplicate = json.loads(json.dumps(self.source_manifest)) + duplicate["repositories"].append(dict(duplicate["repositories"][0])) + attacks.append(duplicate) + mutable = json.loads(json.dumps(self.source_manifest)) + mutable["repositories"][1]["revision"] = "main" + attacks.append(mutable) + malformed_tree = json.loads(json.dumps(self.source_manifest)) + malformed_tree["repositories"][1]["reviewed_tree_sha"] = "not-a-tree" + attacks.append(malformed_tree) + spoofed = json.loads(json.dumps(self.source_manifest)) + spoofed["repositories"][1]["canonical_repository"] = ( + "HawkinsOperations/hawkinsoperations-detections-suffix" + ) + attacks.append(spoofed) + fallback = json.loads(json.dumps(self.source_manifest)) + fallback["constraints"]["default_branch_fallback"] = True + attacks.append(fallback) + unknown = json.loads(json.dumps(self.source_manifest)) + unknown["repositories"][1]["extension"] = "laundered" + attacks.append(unknown) + for candidate in attacks: + with self.subTest(candidate=candidate): + self.assertTrue(VERIFIER.validate_source_manifest(candidate)) + + def test_resolved_manifest_digest_rejects_tampering(self) -> None: + resolved = VERIFIER.resolved_source_manifest( + self.source_manifest, "1" * 40, "2" * 40 + ) + self.assertEqual([], VERIFIER.validate_resolved_manifest(resolved)) + resolved["repositories"][1]["revision"] = "2" * 40 + self.assertIn( + "resolved source manifest digest mismatch", + VERIFIER.validate_resolved_manifest(resolved), + ) + + def test_main_content_observation_is_tree_bound_not_commit_bound(self) -> None: + resolved = VERIFIER.resolved_source_manifest( + self.source_manifest, "1" * 40, "2" * 40 + ) + observed = { + entry["repository"]: entry["reviewed_tree_sha"] + for entry in resolved["repositories"] + if entry["repository"] != ".github" + } + self.assertEqual([], VERIFIER.compare_observed_main_trees(resolved, observed)) + observed["hoxline"] = "3" * 40 + errors = VERIFIER.compare_observed_main_trees(resolved, observed) + self.assertTrue(any("hoxline" in error for error in errors)) + + def test_duplicate_json_key_fails_closed(self) -> None: + with tempfile.TemporaryDirectory() as temp: + path = Path(temp) / "duplicate.json" + path.write_text('{"schema":"one","SCHEMA":"two"}\n', encoding="utf-8") + with self.assertRaises(VERIFIER.ValidationError): + VERIFIER.load_json_strict(path) + + +class SourceSetTests(unittest.TestCase): + def run_git(self, repo: Path, *args: str) -> str: + result = subprocess.run( + ["git", "-C", str(repo), *args], + check=True, + capture_output=True, + text=True, + ) + return result.stdout.strip() + + def create_source_set(self, root: Path) -> dict: + entries = [] + for repository in VERIFIER.EXACT_REPOSITORIES: + repo = root / repository + repo.mkdir() + self.run_git(repo, "init", "--quiet") + self.run_git(repo, "config", "user.name", "Command Center Test") + self.run_git(repo, "config", "user.email", "test@invalid.example") + (repo / "authority.txt").write_text(repository + "\n", encoding="utf-8") + self.run_git(repo, "add", "authority.txt") + self.run_git(repo, "commit", "--quiet", "-m", "fixture") + sha = self.run_git(repo, "rev-parse", "HEAD") + tree = self.run_git(repo, "rev-parse", "HEAD^{tree}") + self.run_git( + repo, "remote", "add", "origin", VERIFIER.CANONICAL_ORIGINS[repository] + ) + self.run_git(repo, "checkout", "--quiet", "--detach", sha) + entries.append( + { + "repository": repository, + "canonical_repository": f"HawkinsOperations/{repository}", + "revision": sha, + "reviewed_tree_sha": tree, + } + ) + payload = { + "schema": "hawkinsoperations-resolved-convergence-source-set-v1", + "manifest_id": "HAWKINSOPERATIONS_SEVEN_SOURCE_PR_HEAD_MATRIX_V1", + "repositories": entries, + "constraints": { + "exact_repository_count": 7, + "read_only": True, + "default_branch_fallback": False, + "require_detached_exact_revision": True, + "record_checked_revisions": True, + "consumer_outputs_are_not_authority": True, + "proof_ceiling": VERIFIER.PROOF_CEILING, + }, + } + payload["manifest_sha256"] = VERIFIER.hashlib.sha256( + json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8") + ).hexdigest() + return payload + + def test_exact_clean_detached_source_set_passes(self) -> None: + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + records, errors = VERIFIER.verify_source_set(root, resolved) + self.assertEqual([], errors) + self.assertEqual(7, len(records)) + + def test_dirty_wrong_origin_branch_and_missing_repo_fail(self) -> None: + for attack in ("dirty", "origin", "branch", "missing", "extra"): + with self.subTest(attack=attack), tempfile.TemporaryDirectory() as temp: + root = Path(temp) / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + target = root / "hawkinsoperations-detections" + if attack == "dirty": + (target / "untracked.txt").write_text("dirty\n", encoding="utf-8") + elif attack == "origin": + self.run_git( + target, + "remote", + "set-url", + "origin", + "https://github.com/Other/hawkinsoperations-detections.git", + ) + elif attack == "branch": + self.run_git(target, "switch", "--quiet", "-c", "main") + elif attack == "missing": + target.rename(root / "missing") + else: + (root / "eighth-repository").mkdir() + _, errors = VERIFIER.verify_source_set(root, resolved) + self.assertTrue(errors) + + +class ArtifactSanitizerTests(unittest.TestCase): + def create_valid_artifacts(self, root: Path) -> None: + source = VERIFIER.resolved_source_manifest( + VERIFIER.load_json_strict(VERIFIER.SOURCE_MANIFEST_PATH), + "1" * 40, + "2" * 40, + ) + source["checked_repositories"] = [ + { + "repository": entry["repository"], + "canonical_repository": entry["canonical_repository"], + "checked_sha": entry["revision"], + "checked_tree_sha": entry["reviewed_tree_sha"], + "detached": True, + "clean": True, + } + for entry in source["repositories"] + ] + VERIFIER.write_json_atomic(root / "source-revisions.json", source) + VERIFIER.write_verification_summary(root / "verification-summary.json") + + def test_closed_sanitized_artifact_pair_passes(self) -> None: + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + self.create_valid_artifacts(root) + self.assertEqual([], VERIFIER.validate_artifact_payloads(root)) + + def test_private_and_unsupported_artifacts_fail(self) -> None: + hostile_values = [ + r"C:\private\output", + r"\\server\share\output", + "/home/operator/output", + "%2fhome%2foperator%2foutput", + "ghp_example", + "192.168.1.12", + "private@example.com", + "customer evidence", + ] + for hostile in hostile_values: + with self.subTest(hostile=hostile), tempfile.TemporaryDirectory() as temp: + root = Path(temp) + self.create_valid_artifacts(root) + path = root / "verification-summary.json" + value = json.loads(path.read_text(encoding="utf-8")) + value["checks"][0] = hostile + VERIFIER.write_json_atomic(path, value) + self.assertTrue(VERIFIER.validate_artifact_payloads(root)) + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + self.create_valid_artifacts(root) + (root / "raw.log").write_text("not approved\n", encoding="utf-8") + self.assertTrue(VERIFIER.validate_artifact_payloads(root)) + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + self.create_valid_artifacts(root) + (root / "verification-summary.json").write_text("{", encoding="utf-8") + self.assertTrue(VERIFIER.validate_artifact_payloads(root)) + + +if __name__ == "__main__": + unittest.main() From fee75e7a88c0b623590786e02f69d4297a0e10b4 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 00:21:15 -0500 Subject: [PATCH 003/116] fix(command-center): reject workflow neutralization --- .../workflows/command-center-invariants.yml | 2 + scripts/verify-command-center-invariants.py | 203 +++++++++++++++--- tests/test_command_center_workflow_safety.py | 90 ++++++++ 3 files changed, 264 insertions(+), 31 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index b9710ca..6253a7d 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -11,6 +11,7 @@ on: - ".github/pull_request_template.md" - ".github/workflows/command-center-invariants.yml" - "scripts/verify-command-center-invariants.py" + - "tests/**" push: branches: - main @@ -23,6 +24,7 @@ on: - ".github/pull_request_template.md" - ".github/workflows/command-center-invariants.yml" - "scripts/verify-command-center-invariants.py" + - "tests/**" workflow_dispatch: {} schedule: - cron: "23 7 * * 1" diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 0c70c3c..48ce7b1 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -45,6 +45,55 @@ } EXPECTED_ARTIFACT_FILES = {"source-revisions.json", "verification-summary.json"} PROOF_CEILING = "CONTROLLED_REPO_CONVERGENCE_AND_LOCAL_FIXTURE_REVIEW_ONLY" +EXPECTED_VERIFICATION_CHECKS = [ + "command_center_invariants", + "command_center_hostile_workflow_tests", + "exact_seven_source_checkout", + "detection_contract", + "detection_promotion_matrix", + "detection_reverse_inventory_and_hostile_tests", + "validation_registry", + "validation_package_sweep", + "validation_source_and_report_parity", + "validation_claim_boundary", + "proof_status_index", + "proof_reverse_inventory", + "proof_integrity", + "platform_public_status_source_contract", + "platform_case_growth_convergence", + "platform_mutation_boundary", + "hoxline_case_growth_pair", + "hoxline_expanded_batch", + "hoxline_replay", + "hoxline_hostile_tests", + "website_source_owner_and_freshness", + "website_nested_claim_and_eol_tests", + "website_static_build", +] +EXPECTED_MANIFEST_ROOT_KEYS = { + "schema", + "scope", + "required_route_files", + "cross_repo_repositories", + "invariants", +} +EXPECTED_INVARIANT_KEYS = { + "github_repo_role", + "project_2_role", + "project_1_boundary", + "project_metadata_boundary", + "rendering_boundary", + "proof_authority_repo", + "command_center_proof_ceiling", + "ledger_public_safe_status", + "reviewer_metrics_pipeline", + "reviewer_metrics_counts", + "cross_repo_convergence", + "ho_det_001_public_ceiling", + "runtime_signal_public_promotions", + "standing_controls", + "standing_control_replacement", +} REQUIRED_TEXT = { "README.md": [ @@ -253,8 +302,21 @@ def load_manifest(errors: list[str]) -> dict[str, Any]: return {} if manifest.get("schema") != "hawkinsoperations-command-center-invariants-v1": fail("manifest schema mismatch", errors) - if not isinstance(manifest.get("invariants"), dict): + if set(manifest) != EXPECTED_MANIFEST_ROOT_KEYS: + fail("manifest root shape is not closed", errors) + invariants = manifest.get("invariants") + if not isinstance(invariants, dict): fail("manifest invariants must be an object", errors) + elif set(invariants) != EXPECTED_INVARIANT_KEYS: + fail("manifest invariant shape is not closed", errors) + elif any(not isinstance(value, str) or not value.strip() for value in invariants.values()): + fail("manifest invariant values must be non-empty strings", errors) + if not isinstance(manifest.get("scope"), str) or not manifest["scope"].strip(): + fail("manifest scope must be a non-empty string", errors) + if not isinstance(manifest.get("required_route_files"), list): + fail("manifest required_route_files must be an array", errors) + if manifest.get("cross_repo_repositories") != EXACT_REPOSITORIES: + fail("manifest cross-repository list is not canonical", errors) return manifest @@ -400,6 +462,30 @@ def unsafe_workflow_findings(text: str) -> list[str]: findings.append("scheduled drift detection is required") if not isinstance(triggers.get("workflow_dispatch"), dict): findings.append("manual read-only dispatch is required") + pull_request = triggers.get("pull_request") + push = triggers.get("push") + required_paths = { + "README.md", + "profile/**", + "architecture/**", + "governance/**", + "wiki/**", + ".github/pull_request_template.md", + ".github/workflows/command-center-invariants.yml", + "scripts/verify-command-center-invariants.py", + "tests/**", + } + if not isinstance(pull_request, dict) or set(pull_request) != {"paths"}: + findings.append("pull_request trigger shape must be unrestricted except approved paths") + elif set(pull_request.get("paths", [])) != required_paths: + findings.append("pull_request paths must cover every governed verifier surface") + if not isinstance(push, dict) or set(push) != {"branches", "paths"}: + findings.append("push trigger shape must be exactly branches and paths") + else: + if push.get("branches") != ["main"]: + findings.append("push trigger must govern main exactly") + if set(push.get("paths", [])) != required_paths: + findings.append("push paths must cover every governed verifier surface") if workflow.get("permissions") != {"contents": "read"}: findings.append("root permissions must be exactly contents: read") @@ -409,6 +495,72 @@ def unsafe_workflow_findings(text: str) -> list[str]: "seven-repository-convergence", }: findings.append("workflow jobs must be the exact approved pair") + else: + expected_step_names = { + "command-center-invariants": [ + "Checkout command-center authority", + "Set up Python", + "Install structural verifier dependency", + "Verify command-center invariants", + "Run hostile command-center unit tests", + "Verify patch whitespace", + ], + "seven-repository-convergence": [ + "Checkout workflow authority at the event revision", + "Set up Python", + "Set up Node", + "Install bounded verifier dependencies", + "Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json", + "Checkout six immutable sibling revisions without credentials", + "Verify the exact clean detached source set", + "Detect durable sibling main-content drift", + "Verify detection authority and hostile paths", + "Verify validation authority and fail-closed parity", + "Verify proof authority and reverse inventory", + "Verify platform source contract and seven-source convergence", + "Install Hoxline from the checked immutable source", + "Verify Hoxline Case Growth pair and replay integrity", + "Install Website dependencies from the checked lockfile", + "Verify Website rendering-only status plane and static build", + "Write closed-schema verification summary", + "Validate upload artifacts", + "Upload sanitized convergence records", + ], + } + for job_name, expected_names in expected_step_names.items(): + job = jobs.get(job_name) + if not isinstance(job, dict): + findings.append(f"{job_name} job must be an object") + continue + if "if" in job: + findings.append(f"{job_name} mandatory job must not be conditional") + steps = job.get("steps") + if not isinstance(steps, list): + findings.append(f"{job_name} steps must be an array") + continue + names = [step.get("name") if isinstance(step, dict) else None for step in steps] + if names != expected_names: + findings.append(f"{job_name} step order differs from the approved contract") + for step in steps: + if not isinstance(step, dict): + findings.append(f"{job_name} contains a non-object step") + continue + condition = step.get("if") + if step.get("name") == "Detect durable sibling main-content drift": + if condition != "github.event_name != 'pull_request'": + findings.append("durable main observation condition is not exact") + elif condition is not None: + findings.append(f"mandatory step is conditional: {step.get('name')}") + convergence_steps = jobs["seven-repository-convergence"].get("steps", []) + if isinstance(convergence_steps, list): + names = [step.get("name") for step in convergence_steps if isinstance(step, dict)] + try: + validate_index = names.index("Validate upload artifacts") + upload_index = names.index("Upload sanitized convergence records") + if upload_index != validate_index + 1: + findings.append("artifact validation must be immediately before upload") + except ValueError: + findings.append("artifact validation/upload steps are missing") checkout_count = 0 source_set_checkout = False @@ -430,6 +582,9 @@ def unsafe_workflow_findings(text: str) -> list[str]: if key == "run" and isinstance(value, str) and "\n" in value: if "set -euo pipefail" not in value: findings.append("multiline shell steps must enable strict exit propagation") + if key == "run" and isinstance(value, str): + if re.search(r"(?im)^\s*(?:echo|printf)\b.*\b(?:python|git)\b", value): + findings.append("required command may not be replaced by inert output") if key == "uses" and isinstance(value, str): match = re.fullmatch(r"([^@]+)@([0-9a-f]{40})", value) if match is None: @@ -493,8 +648,8 @@ def unsafe_workflow_findings(text: str) -> list[str]: "ledger mutation": r"\b(?:lifetime|ledger)[^\n]*(?:append|correct|mutate|write)\b", "runtime mutation": r"\b(?:runtime|endpoint|wazuh|splunk|cribl)[^\n]*(?:mutate|deploy|configure|restart|write)\b", "proof promotion": r"\b(?:proof|public.safe)[^\n]*(?:promote|publish|approve)\b", - "swallowed failure": r"(?:\|\|\s*true\b|\bset\s+\+e\b|\btrap\b[^\n]*\bexit\s+0\b)", - "backgrounded command": r"(?m)(? list[str]: for fragment in required_fragments: if fragment not in text: findings.append(f"workflow missing required behavior: {fragment}") + exact_executed_patterns = { + "detection contract": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract\.py\s*$", + "detection matrix": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix\.py\s*$", + "sibling fetch": r'(?m)^\s*git -C "source-set/\$repo" fetch --quiet --depth=1 origin "\$revision"\s*$', + "sibling checkout": r'(?m)^\s*git -C "source-set/\$repo" checkout --quiet --detach "\$revision"\s*$', + } + for label, pattern in exact_executed_patterns.items(): + if re.search(pattern, text) is None: + findings.append(f"workflow does not execute exact required command: {label}") return sorted(set(findings)) @@ -895,6 +1059,8 @@ def is_private_scalar(value: str) -> bool: return True if re.search( r"(?:github[_-]?pat_|ghp_|begin (?:rsa |openssh )?private key|" + r"\bAKIA[0-9A-Z]{16}\b|\bbearer\s+[a-z0-9._~+/=-]{12,}\b|" + r"\beyJ[a-z0-9_-]{8,}\.[a-z0-9_-]{8,}\.[a-z0-9_-]{8,}\b|" r"\b(?:10|127)\.\d{1,3}\.\d{1,3}\.\d{1,3}\b|" r"\b172\.(?:1[6-9]|2\d|3[0-1])\.\d{1,3}\.\d{1,3}\b|" r"\b192\.168\.\d{1,3}\.\d{1,3}\b|" @@ -1006,8 +1172,8 @@ def validate_artifact_payloads(directory: Path) -> list[str]: if summary.get("repositories") != EXACT_REPOSITORIES: errors.append("verification summary repository set mismatch") checks = summary.get("checks") - if not isinstance(checks, list) or len(checks) != len(set(checks)) or len(checks) < 20: - errors.append("verification summary check list is missing or duplicated") + if checks != EXPECTED_VERIFICATION_CHECKS: + errors.append("verification summary check list differs from the exact approved checks") if summary.get("mutation_boundary") != { "repository_writes": False, "pull_request_mutation": False, @@ -1038,31 +1204,6 @@ def write_json_atomic(path: Path, value: dict[str, Any]) -> None: def write_verification_summary(path: Path) -> None: - checks = [ - "command_center_invariants", - "command_center_hostile_workflow_tests", - "exact_seven_source_checkout", - "detection_contract", - "detection_promotion_matrix", - "detection_reverse_inventory_and_hostile_tests", - "validation_registry", - "validation_package_sweep", - "validation_source_and_report_parity", - "validation_claim_boundary", - "proof_status_index", - "proof_reverse_inventory", - "proof_integrity", - "platform_public_status_source_contract", - "platform_case_growth_convergence", - "platform_mutation_boundary", - "hoxline_case_growth_pair", - "hoxline_expanded_batch", - "hoxline_replay", - "hoxline_hostile_tests", - "website_source_owner_and_freshness", - "website_nested_claim_and_eol_tests", - "website_static_build", - ] write_json_atomic( path, { @@ -1070,7 +1211,7 @@ def write_verification_summary(path: Path) -> None: "status": "PASS", "repository_count": 7, "repositories": EXACT_REPOSITORIES, - "checks": checks, + "checks": EXPECTED_VERIFICATION_CHECKS, "mutation_boundary": { "repository_writes": False, "pull_request_mutation": False, diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 072d529..8cf0e64 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -69,6 +69,8 @@ def test_mutation_and_exit_neutralization_attacks_fail(self) -> None: "set plus e": "set +e", "unconditional success": "exit 0", "backgrounded command": "python unsafe.py &", + "background and wait": "python unsafe.py & wait", + "swallowed echo": "false || echo ignored", } for label, hostile in hostile_lines.items(): with self.subTest(label=label): @@ -93,6 +95,61 @@ def test_mutation_and_exit_neutralization_attacks_fail(self) -> None: "always", ) + def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> None: + mutations = { + "echo detection verifier": self.workflow.replace( + "python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract.py", + "echo python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract.py", + 1, + ), + "echo sibling fetch": self.workflow.replace( + 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 'echo git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 1, + ), + "conditional job": self.workflow.replace( + " seven-repository-convergence:\n runs-on:", + " seven-repository-convergence:\n if: false\n runs-on:", + 1, + ), + "conditional principal step": self.workflow.replace( + " - name: Verify command-center invariants\n run:", + " - name: Verify command-center invariants\n if: false\n run:", + 1, + ), + } + for label, value in mutations.items(): + with self.subTest(label=label): + self.assert_rejected(value, label) + + def test_trigger_neutralization_and_test_path_omission_fail(self) -> None: + mutations = { + "closed-only PR": self.workflow.replace( + " pull_request:\n paths:", + " pull_request:\n types: [closed]\n paths:", + 1, + ), + "ignored main": self.workflow.replace( + " pull_request:\n paths:", + " pull_request:\n branches-ignore: [main]\n paths:", + 1, + ), + "tests omitted": self.workflow.replace(' - "tests/**"\n', "", 1), + } + for label, value in mutations.items(): + with self.subTest(label=label): + self.assert_rejected(value, label) + + def test_artifact_validation_must_be_immediately_before_upload(self) -> None: + hostile = self.workflow.replace( + " - name: Upload sanitized convergence records", + " - name: Corrupt artifact after validation\n" + " run: echo invalid > verification-artifacts/verification-summary.json\n\n" + " - name: Upload sanitized convergence records", + 1, + ) + self.assert_rejected(hostile, "post-validation artifact mutation") + def test_duplicate_yaml_key_fails_closed(self) -> None: hostile = self.workflow.replace( "permissions:\n contents: read", @@ -185,6 +242,27 @@ def test_duplicate_json_key_fails_closed(self) -> None: with self.assertRaises(VERIFIER.ValidationError): VERIFIER.load_json_strict(path) + def test_command_center_manifest_shape_is_closed(self) -> None: + original = VERIFIER.load_json_strict(VERIFIER.MANIFEST_PATH) + for mutation in ("root", "invariant"): + with self.subTest(mutation=mutation): + candidate = json.loads(json.dumps(original)) + if mutation == "root": + candidate["extension"] = {"ai_authority": True} + else: + candidate["invariants"]["ai_authority"] = True + with tempfile.TemporaryDirectory() as temp: + path = Path(temp) / "manifest.json" + path.write_text(json.dumps(candidate), encoding="utf-8") + prior = VERIFIER.MANIFEST_PATH + try: + VERIFIER.MANIFEST_PATH = path + errors = [] + VERIFIER.load_manifest(errors) + finally: + VERIFIER.MANIFEST_PATH = prior + self.assertTrue(errors) + class SourceSetTests(unittest.TestCase): def run_git(self, repo: Path, *args: str) -> str: @@ -313,6 +391,8 @@ def test_private_and_unsupported_artifacts_fail(self) -> None: "192.168.1.12", "private@example.com", "customer evidence", + "AKIAIOSFODNN7EXAMPLE", + "Bearer abcdefghijklmnopqrstuvwxyz", ] for hostile in hostile_values: with self.subTest(hostile=hostile), tempfile.TemporaryDirectory() as temp: @@ -328,6 +408,16 @@ def test_private_and_unsupported_artifacts_fail(self) -> None: self.create_valid_artifacts(root) (root / "raw.log").write_text("not approved\n", encoding="utf-8") self.assertTrue(VERIFIER.validate_artifact_payloads(root)) + + def test_fabricated_check_set_fails(self) -> None: + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + self.create_valid_artifacts(root) + path = root / "verification-summary.json" + value = json.loads(path.read_text(encoding="utf-8")) + value["checks"] = [f"fabricated_check_{index}" for index in range(23)] + VERIFIER.write_json_atomic(path, value) + self.assertTrue(VERIFIER.validate_artifact_payloads(root)) with tempfile.TemporaryDirectory() as temp: root = Path(temp) self.create_valid_artifacts(root) From c8f7fe023aa8eb9af385a8bb222133b9997fe94e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:03:23 -0500 Subject: [PATCH 004/116] chore(command-center): pin final reviewed source trees --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 68f9585..edfd1fc 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -11,38 +11,38 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "e1d7cae30165f21ebfb7ed701f8e854888bfded9" + "revision": "16d4432eb46d457939f1cfe573c0c5d712650efb", + "reviewed_tree_sha": "74a33886c498ed0c0c79360d0fc2485dea4b4cf7" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "d150cf172a4cb6065fd54c19c59beb9b581ba629", - "reviewed_tree_sha": "b8597f5154f021c6159210af9335ff17e1bf6a2e" + "revision": "34bbfc4f48f75f647d5946b4cbe6835abf5e7dbc", + "reviewed_tree_sha": "edc1f917dfa86cdc32bc47190957786a7dc400c3" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "d1ea495f2b010fbaefc2dccf22986526958ba424", - "reviewed_tree_sha": "fc487801ba4fdae44a85ea52761fb446b69c421e" + "revision": "dce32809fcee7faef3f92da7139b2781bb9c4330", + "reviewed_tree_sha": "cc093904e16859e2f7df9c465b8075d2e7ff41a1" }, { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", - "revision": "042a918ad4a8473cd5abcfd575072fc094639682", - "reviewed_tree_sha": "bedaa1e461556f9c9dced6aac2854594f7baf0cd" + "revision": "8ff2c1a2f1762e7635fe24194617f110275c2f0c", + "reviewed_tree_sha": "841d5070ef48b7eb6cea79846a2b7d0f4b7ed5a9" }, { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "ef7ad97279c06634e153be6e8ecee1959b9f7d78", - "reviewed_tree_sha": "150a6af5df3c2df8cb9b7f3f08b1217a8ad7d7b8" + "revision": "9f4c03b84f2c03a305cd1e974ae405cd05218923", + "reviewed_tree_sha": "dc2005b1dc4ccc3dee5623f27218dd7893302066" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "f2ebea13f5b19fcca348b5359bc9372a7b893962", - "reviewed_tree_sha": "b5ad30a8d7ebbc5bd796ea0bfc58f5317fea5f87" + "revision": "8ddb8eec8102cac6ef5af2e55632354ca0b8e06d", + "reviewed_tree_sha": "931495e3745bff896396a05b514b9b4df8aa70cd" } ], "constraints": { From f6485fba09dd0fcb74e852a74f3af8e789589bee Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:12:46 -0500 Subject: [PATCH 005/116] chore(command-center): include final proof and Hoxline trees --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index edfd1fc..0d1863e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -29,8 +29,8 @@ { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", - "revision": "8ff2c1a2f1762e7635fe24194617f110275c2f0c", - "reviewed_tree_sha": "841d5070ef48b7eb6cea79846a2b7d0f4b7ed5a9" + "revision": "c60882552571c1664549d3e594c6994dc27dce63", + "reviewed_tree_sha": "2f84647f298b36a2286aaddf4ebeedf5e0c3cc82" }, { "repository": "hawkinsoperations-website", @@ -41,8 +41,8 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "8ddb8eec8102cac6ef5af2e55632354ca0b8e06d", - "reviewed_tree_sha": "931495e3745bff896396a05b514b9b4df8aa70cd" + "revision": "5cf99d39a6a85f0c3882ad4f6fc635ba7d908625", + "reviewed_tree_sha": "7673753e2f661f88451e3af6bf20ed8b0da7dce7" } ], "constraints": { From beee6b51eef51986eb6417c5adfd93492eab4b82 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:21:38 -0500 Subject: [PATCH 006/116] fix(command-center): bind detached validation source --- .github/workflows/command-center-invariants.yml | 2 +- scripts/verify-command-center-invariants.py | 1 + tests/test_command_center_workflow_safety.py | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 6253a7d..2932fdc 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -154,7 +154,7 @@ jobs: shell: bash run: | set -euo pipefail - python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry.py + python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry.py --detections-root source-set/hawkinsoperations-detections --detections-ref "$(git -C source-set/hawkinsoperations-detections rev-parse HEAD)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST.json python -B source-set/hawkinsoperations-validation/scripts/verify_all_validation_packages.py python -B source-set/hawkinsoperations-validation/scripts/verify_validation_contract.py python -B source-set/hawkinsoperations-validation/scripts/verify_wazuh_logtest_registry.py diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 48ce7b1..c075009 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -702,6 +702,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: exact_executed_patterns = { "detection contract": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract\.py\s*$", "detection matrix": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix\.py\s*$", + "validation registry exact source": r'(?m)^\s*python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry\.py --detections-root source-set/hawkinsoperations-detections --detections-ref "\$\(git -C source-set/hawkinsoperations-detections rev-parse HEAD\)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST\.json\s*$', "sibling fetch": r'(?m)^\s*git -C "source-set/\$repo" fetch --quiet --depth=1 origin "\$revision"\s*$', "sibling checkout": r'(?m)^\s*git -C "source-set/\$repo" checkout --quiet --detach "\$revision"\s*$', } diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 8cf0e64..58df98f 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -107,6 +107,11 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N 'echo git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', 1, ), + "validation detached source omitted": self.workflow.replace( + ' --detections-root source-set/hawkinsoperations-detections --detections-ref "$(git -C source-set/hawkinsoperations-detections rev-parse HEAD)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST.json', + "", + 1, + ), "conditional job": self.workflow.replace( " seven-repository-convergence:\n runs-on:", " seven-repository-convergence:\n if: false\n runs-on:", From 4f9e71d5b1b735038c572898163eb36ec51e9b06 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:23:54 -0500 Subject: [PATCH 007/116] chore(command-center): pin final website workflow tree --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 0d1863e..3d69141 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -35,8 +35,8 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "9f4c03b84f2c03a305cd1e974ae405cd05218923", - "reviewed_tree_sha": "dc2005b1dc4ccc3dee5623f27218dd7893302066" + "revision": "62573f58de5f83b0e6355702be0637cc902c285f", + "reviewed_tree_sha": "123c6a1f55666986765cc3782acfda368f2bff27" }, { "repository": "hoxline", From bd2995297aad0e2d862eebfd6ea554a0e3859063 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:29:30 -0500 Subject: [PATCH 008/116] chore(command-center): pin merge-resilient website tree --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 3d69141..5e1e7a3 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -35,8 +35,8 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "62573f58de5f83b0e6355702be0637cc902c285f", - "reviewed_tree_sha": "123c6a1f55666986765cc3782acfda368f2bff27" + "revision": "6cff0be8e8130f332971f7f00b49387dbe88e604", + "reviewed_tree_sha": "2988ac2a8a7b3e7edb92b16c02d57aa10693a620" }, { "repository": "hoxline", From c06b4a7526c93516bcf82cc7dd503336fa291d7a Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:30:39 -0500 Subject: [PATCH 009/116] chore(command-center): pin final platform merge-resilience tree --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 5e1e7a3..c1cdf0e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -23,8 +23,8 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "dce32809fcee7faef3f92da7139b2781bb9c4330", - "reviewed_tree_sha": "cc093904e16859e2f7df9c465b8075d2e7ff41a1" + "revision": "af6ca4e93045affc9ba2954cffce4719b04d649f", + "reviewed_tree_sha": "bd6c7456333fa33b09f9fa15be6d108d44bb28cc" }, { "repository": "hawkinsoperations-proof", From e6e91a0f798464f729d111da4b56ca95494e8d2b Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 01:44:59 -0500 Subject: [PATCH 010/116] ci(command-center): set validation import authority --- .github/workflows/command-center-invariants.yml | 2 +- scripts/verify-command-center-invariants.py | 1 + tests/test_command_center_workflow_safety.py | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 2932fdc..37ca082 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -159,7 +159,7 @@ jobs: python -B source-set/hawkinsoperations-validation/scripts/verify_validation_contract.py python -B source-set/hawkinsoperations-validation/scripts/verify_wazuh_logtest_registry.py python -B source-set/hawkinsoperations-validation/scripts/verify_ho_lab_wazuh_001.py - python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests + PYTHONPATH="$GITHUB_WORKSPACE/source-set/hawkinsoperations-validation" python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests - name: Verify proof authority and reverse inventory shell: bash diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index c075009..d968206 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -703,6 +703,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: "detection contract": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract\.py\s*$", "detection matrix": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix\.py\s*$", "validation registry exact source": r'(?m)^\s*python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry\.py --detections-root source-set/hawkinsoperations-detections --detections-ref "\$\(git -C source-set/hawkinsoperations-detections rev-parse HEAD\)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST\.json\s*$', + "validation unit import root": r'(?m)^\s*PYTHONPATH="\$GITHUB_WORKSPACE/source-set/hawkinsoperations-validation" python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests\s*$', "sibling fetch": r'(?m)^\s*git -C "source-set/\$repo" fetch --quiet --depth=1 origin "\$revision"\s*$', "sibling checkout": r'(?m)^\s*git -C "source-set/\$repo" checkout --quiet --detach "\$revision"\s*$', } diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 58df98f..9b7664d 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -112,6 +112,11 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N "", 1, ), + "validation unit import root omitted": self.workflow.replace( + 'PYTHONPATH="$GITHUB_WORKSPACE/source-set/hawkinsoperations-validation" ', + "", + 1, + ), "conditional job": self.workflow.replace( " seven-repository-convergence:\n runs-on:", " seven-repository-convergence:\n if: false\n runs-on:", From fa95bbbf0985c57488b32589307eb2cabb99ea00 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 02:02:20 -0500 Subject: [PATCH 011/116] ci(command-center): bind platform checked observation --- .github/workflows/command-center-invariants.yml | 9 ++++++--- scripts/verify-command-center-invariants.py | 1 + tests/test_command_center_workflow_safety.py | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 37ca082..089b351 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -124,16 +124,19 @@ jobs: --verify-source-set source-set \ --resolved-manifest verification-work/resolved-source-manifest.json \ --source-revisions-output verification-artifacts/source-revisions.json - proof_sha="$(python - verification-work/resolved-source-manifest.json <<'PY' + readarray -t authority_shas < <(python - verification-work/resolved-source-manifest.json <<'PY' import json import sys value = json.load(open(sys.argv[1], encoding="utf-8")) by_repo = {entry["repository"]: entry["revision"] for entry in value["repositories"]} print(by_repo["hawkinsoperations-proof"]) + print(by_repo["hawkinsoperations-platform"]) PY - )" - printf 'HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA=%s\n' "$proof_sha" >> "$GITHUB_ENV" + ) + test "${#authority_shas[@]}" -eq 2 + printf 'HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA=%s\n' "${authority_shas[0]}" >> "$GITHUB_ENV" + printf 'HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA=%s\n' "${authority_shas[1]}" >> "$GITHUB_ENV" - name: Detect durable sibling main-content drift if: github.event_name != 'pull_request' diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index d968206..de8cd6d 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -669,6 +669,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: 'git -C "source-set/$repo" checkout --quiet --detach "$revision"', "source-revisions.json", "HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA", + "HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA", "verify_detection_contract.py", "verify_detection_promotion_matrix.py", "verify_validation_registry.py", diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 9b7664d..45841a1 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -117,6 +117,11 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N "", 1, ), + "platform observed SHA omitted": self.workflow.replace( + "HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA", + "HAWKINS_PLATFORM_OBSERVATION_OMITTED", + 1, + ), "conditional job": self.workflow.replace( " seven-repository-convergence:\n runs-on:", " seven-repository-convergence:\n if: false\n runs-on:", From b0b0bf187163edc80fa042e72c8ccd8436677a1d Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 02:44:03 -0500 Subject: [PATCH 012/116] chore(command-center): seal reviewed convergence trees --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index c1cdf0e..eeb5789 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -23,8 +23,8 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "af6ca4e93045affc9ba2954cffce4719b04d649f", - "reviewed_tree_sha": "bd6c7456333fa33b09f9fa15be6d108d44bb28cc" + "revision": "70ba640773e4116b1fa0e80c86c2a2a0f7287ba6", + "reviewed_tree_sha": "480b7f509cfad910df869eaf20a0b9981cf5edb9" }, { "repository": "hawkinsoperations-proof", @@ -35,14 +35,14 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "6cff0be8e8130f332971f7f00b49387dbe88e604", - "reviewed_tree_sha": "2988ac2a8a7b3e7edb92b16c02d57aa10693a620" + "revision": "7709c7aec560ad0195ca171c093e4f8468301796", + "reviewed_tree_sha": "8596116f5113b9384bdc4025b936a102ec070478" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "5cf99d39a6a85f0c3882ad4f6fc635ba7d908625", - "reviewed_tree_sha": "7673753e2f661f88451e3af6bf20ed8b0da7dce7" + "revision": "352cc0b66fbd78cb1d522934a4262c4ec6c231a4", + "reviewed_tree_sha": "1cf90dfa5d6746c582e5639fe28b7388e7579fa3" } ], "constraints": { From e78929f6e13c11e6926944bfc3537457910fa86c Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 02:48:48 -0500 Subject: [PATCH 013/116] chore(command-center): refresh final authority content trees --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index eeb5789..7cb655f 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -23,8 +23,8 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "70ba640773e4116b1fa0e80c86c2a2a0f7287ba6", - "reviewed_tree_sha": "480b7f509cfad910df869eaf20a0b9981cf5edb9" + "revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", + "reviewed_tree_sha": "a7b45cd71f0b432fb311a9436334d284f54c9472" }, { "repository": "hawkinsoperations-proof", @@ -41,8 +41,8 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "352cc0b66fbd78cb1d522934a4262c4ec6c231a4", - "reviewed_tree_sha": "1cf90dfa5d6746c582e5639fe28b7388e7579fa3" + "revision": "752fade273904e6f9280523a43aaf9dad5181220", + "reviewed_tree_sha": "e3d3aa8c39956996da2ffc4c4bb1cad03cf24353" } ], "constraints": { From 9de52c3d1b8fe05c0f745c65d3817b1e50efc908 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 02:51:50 -0500 Subject: [PATCH 014/116] ci(command-center): bind exact self observation --- .github/workflows/command-center-invariants.yml | 8 +++++--- scripts/verify-command-center-invariants.py | 1 + tests/test_command_center_workflow_safety.py | 5 +++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 089b351..02a2f72 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -130,13 +130,15 @@ jobs: value = json.load(open(sys.argv[1], encoding="utf-8")) by_repo = {entry["repository"]: entry["revision"] for entry in value["repositories"]} + print(by_repo[".github"]) print(by_repo["hawkinsoperations-proof"]) print(by_repo["hawkinsoperations-platform"]) PY ) - test "${#authority_shas[@]}" -eq 2 - printf 'HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA=%s\n' "${authority_shas[0]}" >> "$GITHUB_ENV" - printf 'HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA=%s\n' "${authority_shas[1]}" >> "$GITHUB_ENV" + test "${#authority_shas[@]}" -eq 3 + printf 'HAWKINS_COMMAND_CENTER_IMMUTABLE_OBSERVED_SHA=%s\n' "${authority_shas[0]}" >> "$GITHUB_ENV" + printf 'HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA=%s\n' "${authority_shas[1]}" >> "$GITHUB_ENV" + printf 'HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA=%s\n' "${authority_shas[2]}" >> "$GITHUB_ENV" - name: Detect durable sibling main-content drift if: github.event_name != 'pull_request' diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index de8cd6d..9a737f5 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -668,6 +668,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', 'git -C "source-set/$repo" checkout --quiet --detach "$revision"', "source-revisions.json", + "HAWKINS_COMMAND_CENTER_IMMUTABLE_OBSERVED_SHA", "HAWKINS_PROOF_IMMUTABLE_MANIFEST_SHA", "HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA", "verify_detection_contract.py", diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 45841a1..6e7a3fd 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -122,6 +122,11 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N "HAWKINS_PLATFORM_OBSERVATION_OMITTED", 1, ), + "command-center observed SHA omitted": self.workflow.replace( + "HAWKINS_COMMAND_CENTER_IMMUTABLE_OBSERVED_SHA", + "HAWKINS_COMMAND_CENTER_OBSERVATION_OMITTED", + 1, + ), "conditional job": self.workflow.replace( " seven-repository-convergence:\n runs-on:", " seven-repository-convergence:\n if: false\n runs-on:", From 43fd17e7e66606fac92994cfc9eeb3871a03eff1 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 03:03:23 -0500 Subject: [PATCH 015/116] fix(command-center): separate final tree from authority content --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 14 ++++++++++---- scripts/verify-command-center-invariants.py | 8 ++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7cb655f..1a99667 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,37 +12,43 @@ "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", "revision": "16d4432eb46d457939f1cfe573c0c5d712650efb", + "authority_content_revision": "16d4432eb46d457939f1cfe573c0c5d712650efb", "reviewed_tree_sha": "74a33886c498ed0c0c79360d0fc2485dea4b4cf7" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", "revision": "34bbfc4f48f75f647d5946b4cbe6835abf5e7dbc", + "authority_content_revision": "34bbfc4f48f75f647d5946b4cbe6835abf5e7dbc", "reviewed_tree_sha": "edc1f917dfa86cdc32bc47190957786a7dc400c3" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "a7b45cd71f0b432fb311a9436334d284f54c9472" + "revision": "42c3a4b78548fc4f95fd017f633eaaf207fc7625", + "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", + "reviewed_tree_sha": "6dce9d6afa0a18e33d70946c317dc5a47c141c55" }, { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", "revision": "c60882552571c1664549d3e594c6994dc27dce63", + "authority_content_revision": "c60882552571c1664549d3e594c6994dc27dce63", "reviewed_tree_sha": "2f84647f298b36a2286aaddf4ebeedf5e0c3cc82" }, { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", "revision": "7709c7aec560ad0195ca171c093e4f8468301796", + "authority_content_revision": "7709c7aec560ad0195ca171c093e4f8468301796", "reviewed_tree_sha": "8596116f5113b9384bdc4025b936a102ec070478" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "752fade273904e6f9280523a43aaf9dad5181220", - "reviewed_tree_sha": "e3d3aa8c39956996da2ffc4c4bb1cad03cf24353" + "revision": "105e904223140e299808564757aa7324424c0e53", + "authority_content_revision": "752fade273904e6f9280523a43aaf9dad5181220", + "reviewed_tree_sha": "900c5d1d9a8fd38a9cdc86dd64ee870361dcb5e4" } ], "constraints": { diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 9a737f5..c8b2be2 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -371,11 +371,19 @@ def validate_source_manifest(value: dict[str, Any]) -> list[str]: "repository", "canonical_repository", "revision", + "authority_content_revision", "reviewed_tree_sha", }: errors.append(f"source manifest entry has an unsupported shape: {repository}") if re.fullmatch(r"[0-9a-f]{40}", str(entry.get("revision", ""))) is None: errors.append(f"source manifest revision is not immutable: {repository}") + if re.fullmatch( + r"[0-9a-f]{40}", + str(entry.get("authority_content_revision", "")), + ) is None: + errors.append( + f"source manifest authority content revision is not immutable: {repository}" + ) if re.fullmatch( r"[0-9a-f]{40}", str(entry.get("reviewed_tree_sha", "")) ) is None: From 90c3f8f9be4bf5233abe50fbd24ff8fa347c7c97 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 03:13:12 -0500 Subject: [PATCH 016/116] chore(command-center): seal final dual-identity source matrix --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 1a99667..8347ca9 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -25,9 +25,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "42c3a4b78548fc4f95fd017f633eaaf207fc7625", + "revision": "e7451f51eae4beacdf9c22fbcc1c6983c1fa619c", "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "6dce9d6afa0a18e33d70946c317dc5a47c141c55" + "reviewed_tree_sha": "8a5b258088e29d1d0203fa12b5e9360abc681318" }, { "repository": "hawkinsoperations-proof", @@ -46,9 +46,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "105e904223140e299808564757aa7324424c0e53", - "authority_content_revision": "752fade273904e6f9280523a43aaf9dad5181220", - "reviewed_tree_sha": "900c5d1d9a8fd38a9cdc86dd64ee870361dcb5e4" + "revision": "f6edb75fd96b4fc419a16f8357ce644c3b9f6205", + "authority_content_revision": "f6edb75fd96b4fc419a16f8357ce644c3b9f6205", + "reviewed_tree_sha": "75b07fc67c6eb01239f3f6f29acfc23dcfb5e239" } ], "constraints": { From cc1032cdf913a8cf10050d239f29e45d18a10381 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 03:21:17 -0500 Subject: [PATCH 017/116] fix(command-center): fetch and verify authority content history --- .github/workflows/command-center-invariants.yml | 3 ++- governance/CONVERGENCE_SOURCE_MANIFEST.json | 3 ++- scripts/verify-command-center-invariants.py | 12 ++++++++++-- tests/test_command_center_workflow_safety.py | 9 ++++++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 02a2f72..cb912d0 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -68,6 +68,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha || github.sha }} path: source-set/.github + fetch-depth: 0 persist-credentials: false - name: Set up Python @@ -111,7 +112,7 @@ jobs: mkdir "source-set/$repo" git -C "source-set/$repo" init --quiet git -C "source-set/$repo" remote add origin "https://github.com/HawkinsOperations/$repo.git" - git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision" + git -C "source-set/$repo" fetch --quiet origin "$revision" git -C "source-set/$repo" checkout --quiet --detach "$revision" test "$(git -C "source-set/$repo" rev-parse HEAD)" = "$revision" done < verification-work/sibling-revisions.tsv diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8347ca9..2322ac8 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -6,6 +6,7 @@ "repository": ".github", "canonical_repository": "HawkinsOperations/.github", "revision_source": "github_event_sha", + "authority_content_revision": "43fd17e7e66606fac92994cfc9eeb3871a03eff1", "tree_source": "github_event_tree" }, { @@ -47,7 +48,7 @@ "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", "revision": "f6edb75fd96b4fc419a16f8357ce644c3b9f6205", - "authority_content_revision": "f6edb75fd96b4fc419a16f8357ce644c3b9f6205", + "authority_content_revision": "8a5e6bcc8b0bfff4a8661a8c663bd2832e8659dd", "reviewed_tree_sha": "75b07fc67c6eb01239f3f6f29acfc23dcfb5e239" } ], diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index c8b2be2..8e5e9c6 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -359,6 +359,7 @@ def validate_source_manifest(value: dict[str, Any]) -> list[str]: "repository", "canonical_repository", "revision_source", + "authority_content_revision", "tree_source", }: errors.append(".github source entry has an unsupported shape") @@ -366,6 +367,13 @@ def validate_source_manifest(value: dict[str, Any]) -> list[str]: errors.append(".github source entry must use github_event_sha") if entry.get("tree_source") != "github_event_tree": errors.append(".github source entry must use github_event_tree") + if re.fullmatch( + r"[0-9a-f]{40}", + str(entry.get("authority_content_revision", "")), + ) is None: + errors.append( + ".github source entry authority content revision is not immutable" + ) else: if set(entry) != { "repository", @@ -673,7 +681,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: "--verify-source-set", "--verify-remote-main-content", "while IFS=$'\\t' read -r repo revision", - 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 'git -C "source-set/$repo" fetch --quiet origin "$revision"', 'git -C "source-set/$repo" checkout --quiet --detach "$revision"', "source-revisions.json", "HAWKINS_COMMAND_CENTER_IMMUTABLE_OBSERVED_SHA", @@ -714,7 +722,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: "detection matrix": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix\.py\s*$", "validation registry exact source": r'(?m)^\s*python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry\.py --detections-root source-set/hawkinsoperations-detections --detections-ref "\$\(git -C source-set/hawkinsoperations-detections rev-parse HEAD\)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST\.json\s*$', "validation unit import root": r'(?m)^\s*PYTHONPATH="\$GITHUB_WORKSPACE/source-set/hawkinsoperations-validation" python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests\s*$', - "sibling fetch": r'(?m)^\s*git -C "source-set/\$repo" fetch --quiet --depth=1 origin "\$revision"\s*$', + "sibling fetch": r'(?m)^\s*git -C "source-set/\$repo" fetch --quiet origin "\$revision"\s*$', "sibling checkout": r'(?m)^\s*git -C "source-set/\$repo" checkout --quiet --detach "\$revision"\s*$', } for label, pattern in exact_executed_patterns.items(): diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 6e7a3fd..bf848c3 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -103,8 +103,8 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N 1, ), "echo sibling fetch": self.workflow.replace( - 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', - 'echo git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 'git -C "source-set/$repo" fetch --quiet origin "$revision"', + 'echo git -C "source-set/$repo" fetch --quiet origin "$revision"', 1, ), "validation detached source omitted": self.workflow.replace( @@ -182,7 +182,7 @@ def test_duplicate_yaml_key_fails_closed(self) -> None: def test_missing_checkout_or_unsanitized_upload_fails(self) -> None: self.assert_rejected( self.workflow.replace( - 'git -C "source-set/$repo" fetch --quiet --depth=1 origin "$revision"', + 'git -C "source-set/$repo" fetch --quiet origin "$revision"', 'printf "%s\\n" "$revision"', 1, ), @@ -212,6 +212,9 @@ def test_source_manifest_is_exact_closed_and_immutable(self) -> None: mutable = json.loads(json.dumps(self.source_manifest)) mutable["repositories"][1]["revision"] = "main" attacks.append(mutable) + missing_self_content = json.loads(json.dumps(self.source_manifest)) + missing_self_content["repositories"][0].pop("authority_content_revision") + attacks.append(missing_self_content) malformed_tree = json.loads(json.dumps(self.source_manifest)) malformed_tree["repositories"][1]["reviewed_tree_sha"] = "not-a-tree" attacks.append(malformed_tree) From be463767b16a464bd111f64569762838f29d0906 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 03:43:09 -0500 Subject: [PATCH 018/116] chore(command-center): refresh reviewed content selections --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 2322ac8..0edbfc4 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "e7451f51eae4beacdf9c22fbcc1c6983c1fa619c", + "revision": "87414ef6734993f9a4cedf4b95a03473ba336884", "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "8a5b258088e29d1d0203fa12b5e9360abc681318" + "reviewed_tree_sha": "04753b9d6278bc301129004cac03124c41022a06" }, { "repository": "hawkinsoperations-proof", @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "f6edb75fd96b4fc419a16f8357ce644c3b9f6205", - "authority_content_revision": "8a5e6bcc8b0bfff4a8661a8c663bd2832e8659dd", - "reviewed_tree_sha": "75b07fc67c6eb01239f3f6f29acfc23dcfb5e239" + "revision": "887f0bb9f9ba6e9990e7189eb00cc46d8da0280d", + "authority_content_revision": "887f0bb9f9ba6e9990e7189eb00cc46d8da0280d", + "reviewed_tree_sha": "01f68e5176f3acb7021d99a97d1524afcf765c64" } ], "constraints": { From 3afb59fc452fc1fbdf14207416068ec72b084464 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 04:09:58 -0500 Subject: [PATCH 019/116] chore(command-center): seal consumer content identities --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 0edbfc4..35eb2a3 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "7709c7aec560ad0195ca171c093e4f8468301796", - "authority_content_revision": "7709c7aec560ad0195ca171c093e4f8468301796", - "reviewed_tree_sha": "8596116f5113b9384bdc4025b936a102ec070478" + "revision": "0230c42fb4aa40aa3c917505457848da4f9883c2", + "authority_content_revision": "0230c42fb4aa40aa3c917505457848da4f9883c2", + "reviewed_tree_sha": "e0af2684c80bcd9f368f38eb01aa9ffcb5898f8f" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "887f0bb9f9ba6e9990e7189eb00cc46d8da0280d", - "authority_content_revision": "887f0bb9f9ba6e9990e7189eb00cc46d8da0280d", - "reviewed_tree_sha": "01f68e5176f3acb7021d99a97d1524afcf765c64" + "revision": "cc0e3e11b86b8998eccaec7d7981cc4f051f156e", + "authority_content_revision": "cc0e3e11b86b8998eccaec7d7981cc4f051f156e", + "reviewed_tree_sha": "a103c823c768ccb292b90ca833ce1c4f2ebd6b5e" } ], "constraints": { From cd4ed1dd55928f4714d67d8e0a2cc6ac4c9549f7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 04:12:45 -0500 Subject: [PATCH 020/116] chore(command-center): seal final reviewed source matrix --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 35eb2a3..b38b100 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "cc0e3e11b86b8998eccaec7d7981cc4f051f156e", + "revision": "47c72da9f4dbbfb8f4a602136345f5428c497167", "authority_content_revision": "cc0e3e11b86b8998eccaec7d7981cc4f051f156e", - "reviewed_tree_sha": "a103c823c768ccb292b90ca833ce1c4f2ebd6b5e" + "reviewed_tree_sha": "7e43bf40313e97172074025aa0fe667fd08b57ba" } ], "constraints": { From f345b42eb1e3ccf97907a084c5851fb1494a9624 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 04:18:35 -0500 Subject: [PATCH 021/116] chore(command-center): seal final platform review identity --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index b38b100..7c577ec 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "87414ef6734993f9a4cedf4b95a03473ba336884", + "revision": "d9ffb49baeb96b9f5789a7dc9d56e028909fd89d", "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "04753b9d6278bc301129004cac03124c41022a06" + "reviewed_tree_sha": "e900c448b3feacc0c21abda35ae75910d3289354" }, { "repository": "hawkinsoperations-proof", From d636d194f91dc19b779c9ceb249445b6d8e62a5d Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 05:27:48 -0500 Subject: [PATCH 022/116] fix(ci): bind command-center execution and authority identity --- .../workflows/command-center-invariants.yml | 2 + scripts/verify-command-center-invariants.py | 240 +++++++++++++++++- tests/test_command_center_workflow_safety.py | 151 ++++++++++- 3 files changed, 386 insertions(+), 7 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index cb912d0..0532a0c 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -239,6 +239,8 @@ jobs: python -B source-set/.github/scripts/verify-command-center-invariants.py --validate-artifacts verification-artifacts + --artifact-source-set + source-set - name: Upload sanitized convergence records uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 8e5e9c6..7367b6f 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -37,6 +37,15 @@ repository: f"https://github.com/HawkinsOperations/{repository}.git" for repository in EXACT_REPOSITORIES } +CANONICAL_AUTHORITY_PATHS = { + ".github": "governance/COMMAND_CENTER_INVARIANTS.json", + "hawkinsoperations-detections": "detections/DETECTION_PROMOTION_MATRIX.yml", + "hawkinsoperations-validation": "validation/VALIDATION_REGISTRY.yml", + "hawkinsoperations-platform": "contracts/public-status-source-contract-v1.json", + "hawkinsoperations-proof": "proof/indexes/DETECTION_PROOF_STATUS_INDEX.yml", + "hawkinsoperations-website": "schemas/public-status-v0.schema.json", + "hoxline": "src/hoxline/case_growth/collector.py", +} PINNED_ACTIONS = { "actions/checkout": "11d5960a326750d5838078e36cf38b85af677262", "actions/setup-python": "a26af69be951a213d495a4c3e4e4022e16d87065", @@ -70,6 +79,73 @@ "website_nested_claim_and_eol_tests", "website_static_build", ] +EXPECTED_RUN_SHA256_BY_STEP = { + "Install structural verifier dependency": "6777f50efc1a4de7a52454974ba0da5a7adda9e7a84e251b3f3fe93912fdd695", + "Verify command-center invariants": "7457407dbbf6fc6c710590149da3c3a7be1358b567f31ffda84cb8fa4fcd2e46", + "Run hostile command-center unit tests": "16792c22d70f184d03660b7d7641f13a305e9227f1d31be6950732ca2a80a5d3", + "Verify patch whitespace": "466c2f308b48c7661d646fdd068fbecea974c665fe65dbf8ed508f224180ce0b", + "Install bounded verifier dependencies": "4e24c9f627196734440d7af0f88696d5c78bcabf31951f052d6f5b8c0d5913b2", + "Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json": "2cc7ec88e5f15e3ce2005c2a7d69d9612b88cd4832d3b6f7ebfc900d326530e8", + "Checkout six immutable sibling revisions without credentials": "49ab88b506c80d864d1616ad4ac3c7448ce7187a92ba2bb36404cf6724ada38a", + "Verify the exact clean detached source set": "3dbfdd7ea15772914b827f395b09fe23aa61c0d31e91703b05cc3ef8c4476e57", + "Detect durable sibling main-content drift": "fa27754b70cd171cac072a868b3632405e5b2c5b8744e34139cf8e64dbcd7a53", + "Verify detection authority and hostile paths": "f65bc86480dc945e0545b9a4a319f0a8dff71bb09d3d331169fe3b2e2b1e63e7", + "Verify validation authority and fail-closed parity": "accba85cf224b66e99287179a83418ae779bfc9d8630579ebd375844181411da", + "Verify proof authority and reverse inventory": "f07b841030269d74bd563238e59e4ff695e2d140108321f9d33ea364a0d850b8", + "Verify platform source contract and seven-source convergence": "698d9e4b0035d4581a87c889bff1c7bb7ef53db957d75688f1364a713be76ee5", + "Install Hoxline from the checked immutable source": "f6954cbb94cbc30f5110c536a4c73b71f985953e71e4c08385cf46b7eb8fea0c", + "Verify Hoxline Case Growth pair and replay integrity": "b8950bb94cb7b0b6bbe505b3180c031aeb1dec904e78d820fc761d302798ad69", + "Install Website dependencies from the checked lockfile": "4be0617fbf64515a837109e98174e687edc18a027a37368223fff95cb33d8f94", + "Verify Website rendering-only status plane and static build": "2d4c7844b0673771d92373c4674a7828e23a2195c6d8bd29e9cd4e00e92f2493", + "Write closed-schema verification summary": "056a198f6f178d60e01d0a0eecda11181372ced82d68793b24fc0676a8cb15b7", + "Validate upload artifacts": "e0b9d66521ae1e69ce51a89d1380fcb70f6edbaa8c9a62a7a78aa1c6a4e6ac0f", +} +EXPECTED_ACTION_BY_STEP = { + "Checkout command-center authority": { + "uses": f"actions/checkout@{PINNED_ACTIONS['actions/checkout']}", + "with": {"persist-credentials": "false"}, + }, + "Checkout workflow authority at the event revision": { + "uses": f"actions/checkout@{PINNED_ACTIONS['actions/checkout']}", + "with": { + "ref": "${{ github.event.pull_request.head.sha || github.sha }}", + "path": "source-set/.github", + "fetch-depth": 0, + "persist-credentials": "false", + }, + }, + "Set up Python": { + "uses": f"actions/setup-python@{PINNED_ACTIONS['actions/setup-python']}", + "with": {"python-version": "3.12"}, + }, + "Set up Node": { + "uses": f"actions/setup-node@{PINNED_ACTIONS['actions/setup-node']}", + "with": {"node-version": "20"}, + }, + "Upload sanitized convergence records": { + "uses": f"actions/upload-artifact@{PINNED_ACTIONS['actions/upload-artifact']}", + "with": { + "name": "seven-repository-convergence-${{ github.run_id }}", + "path": ( + "verification-artifacts/source-revisions.json\n" + "verification-artifacts/verification-summary.json\n" + ), + "if-no-files-found": "error", + "retention-days": 14, + }, + }, +} +EXPECTED_BASH_STEPS = { + "Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json", + "Checkout six immutable sibling revisions without credentials", + "Verify the exact clean detached source set", + "Verify detection authority and hostile paths", + "Verify validation authority and fail-closed parity", + "Verify proof authority and reverse inventory", + "Verify platform source contract and seven-source convergence", + "Verify Hoxline Case Growth pair and replay integrity", + "Verify Website rendering-only status plane and static build", +} EXPECTED_MANIFEST_ROOT_KEYS = { "schema", "scope", @@ -548,6 +624,19 @@ def unsafe_workflow_findings(text: str) -> list[str]: if not isinstance(job, dict): findings.append(f"{job_name} job must be an object") continue + expected_job_keys = ( + {"runs-on", "env", "steps"} + if job_name == "seven-repository-convergence" + else {"runs-on", "steps"} + ) + if set(job) != expected_job_keys: + findings.append(f"{job_name} job shape is not closed") + if job.get("runs-on") != "ubuntu-latest": + findings.append(f"{job_name} runner must be ubuntu-latest") + if job_name == "seven-repository-convergence" and job.get("env") != { + "PYTHONDONTWRITEBYTECODE": "1" + }: + findings.append("seven-repository job environment is not exact") if "if" in job: findings.append(f"{job_name} mandatory job must not be conditional") steps = job.get("steps") @@ -561,12 +650,49 @@ def unsafe_workflow_findings(text: str) -> list[str]: if not isinstance(step, dict): findings.append(f"{job_name} contains a non-object step") continue + name = step.get("name") + if not isinstance(name, str): + findings.append(f"{job_name} step name must be a string") + continue + if "run" in step: + expected_keys = {"name", "run"} + if name in EXPECTED_BASH_STEPS: + expected_keys.add("shell") + if name == "Detect durable sibling main-content drift": + expected_keys.add("if") + if set(step) != expected_keys: + findings.append(f"run step shape is not closed: {name}") + run = step.get("run") + if not isinstance(run, str): + findings.append(f"run step command must be a string: {name}") + else: + expected_digest = EXPECTED_RUN_SHA256_BY_STEP.get(name) + actual_digest = hashlib.sha256(run.encode("utf-8")).hexdigest() + if expected_digest is None or actual_digest != expected_digest: + findings.append( + f"run step differs from exact command allowlist: {name}" + ) + if name in EXPECTED_BASH_STEPS and step.get("shell") != "bash": + findings.append(f"multiline step shell must be exactly bash: {name}") + elif name not in EXPECTED_BASH_STEPS and "shell" in step: + findings.append(f"shell override is forbidden: {name}") + elif "uses" in step: + if set(step) != {"name", "uses", "with"}: + findings.append(f"action step shape is not closed: {name}") + expected_action = EXPECTED_ACTION_BY_STEP.get(name) + if expected_action is None or { + "uses": step.get("uses"), + "with": step.get("with"), + } != expected_action: + findings.append(f"action step differs from exact allowlist: {name}") + else: + findings.append(f"step must use one exact action or run block: {name}") condition = step.get("if") - if step.get("name") == "Detect durable sibling main-content drift": + if name == "Detect durable sibling main-content drift": if condition != "github.event_name != 'pull_request'": findings.append("durable main observation condition is not exact") elif condition is not None: - findings.append(f"mandatory step is conditional: {step.get('name')}") + findings.append(f"mandatory step is conditional: {name}") convergence_steps = jobs["seven-repository-convergence"].get("steps", []) if isinstance(convergence_steps, list): names = [step.get("name") for step in convergence_steps if isinstance(step, dict)] @@ -585,6 +711,8 @@ def unsafe_workflow_findings(text: str) -> list[str]: key = path[-1].casefold() if path else "" if key == "continue-on-error": findings.append("continue-on-error is forbidden") + if key == "defaults": + findings.append("workflow and job defaults are forbidden") if key == "permissions": if path != ("permissions",): findings.append("job or step permission override is forbidden") @@ -664,7 +792,22 @@ def unsafe_workflow_findings(text: str) -> list[str]: "ledger mutation": r"\b(?:lifetime|ledger)[^\n]*(?:append|correct|mutate|write)\b", "runtime mutation": r"\b(?:runtime|endpoint|wazuh|splunk|cribl)[^\n]*(?:mutate|deploy|configure|restart|write)\b", "proof promotion": r"\b(?:proof|public.safe)[^\n]*(?:promote|publish|approve)\b", - "swallowed failure": r"(?:\|\|\s*(?:true|echo|printf)\b|\bset\s+\+e\b|\btrap\b[^\n]*\bexit\s+0\b)", + "swallowed failure": ( + r"(?:\|\|\s*(?::(?:\s|$)|true\b|echo\b|printf\b|exit\s+0\b|" + r"\{[^\n}]*\bexit\s+0\b)|;\s*(?:true\b|exit\s+0\b)|" + r"\bset\s+\+e\b|\btrap\b[^\n]*\bexit\s+0\b)" + ), + "no-op command prefix": r"(?m)^\s*:\s+(?:python|git|npm|npx)\b", + "command function override": ( + r"(?m)^\s*(?:python|python3|git|npm|npx)\s*\(\s*\)\s*\{" + ), + "command alias override": ( + r"(?m)^\s*alias\s+(?:python|python3|git|npm|npx)\s*=" + ), + "command path shadowing": ( + r"(?m)^\s*(?:PATH\s*=|export\s+PATH\s*=|" + r"(?:function\s+)?(?:python|python3|git|npm|npx)\s*=)" + ), "backgrounded command": r"(?m)(? list[str]: "repository", "canonical_repository", "revision", + "authority_content_revision", "reviewed_tree_sha", }: errors.append("resolved source entry has unsupported shape") @@ -905,6 +1050,10 @@ def validate_resolved_manifest(value: dict[str, Any]) -> list[str]: errors.append(f"resolved source owner mismatch: {repository}") if re.fullmatch(r"[0-9a-f]{40}", str(entry.get("revision", ""))) is None: errors.append(f"resolved source revision invalid: {repository}") + if re.fullmatch( + r"[0-9a-f]{40}", str(entry.get("authority_content_revision", "")) + ) is None: + errors.append(f"resolved authority content revision invalid: {repository}") if re.fullmatch( r"[0-9a-f]{40}", str(entry.get("reviewed_tree_sha", "")) ) is None: @@ -973,12 +1122,40 @@ def verify_source_set( status = git(repo_path, "status", "--porcelain=v1", "--untracked-files=all") if status: raise ValidationError(f"{repository}: source checkout is dirty") + authority_path = CANONICAL_AUTHORITY_PATHS[repository] + content_revision = entry["authority_content_revision"] + try: + git(repo_path, "cat-file", "-e", f"{content_revision}^{{commit}}") + except ValidationError as exc: + raise ValidationError( + f"{repository}: authority content revision is not reachable" + ) from exc + try: + current_blob = git(repo_path, "rev-parse", f"HEAD:{authority_path}") + content_blob = git( + repo_path, + "rev-parse", + f"{content_revision}:{authority_path}", + ) + except ValidationError as exc: + raise ValidationError( + f"{repository}: canonical authority path is absent at the " + "current or content revision" + ) from exc + if current_blob != content_blob: + raise ValidationError( + f"{repository}: authority content revision does not identify " + f"the current blob at {authority_path}" + ) records.append( { "repository": repository, "canonical_repository": entry["canonical_repository"], "checked_sha": head, "checked_tree_sha": tree, + "authority_path": authority_path, + "authority_content_revision": content_revision, + "authority_git_blob_sha": current_blob, "detached": True, "clean": True, } @@ -1092,7 +1269,9 @@ def is_private_scalar(value: str) -> bool: return False -def validate_artifact_payloads(directory: Path) -> list[str]: +def validate_artifact_payloads( + directory: Path, source_set: Path | None = None +) -> list[str]: errors: list[str] = [] if not directory.is_dir() or directory.is_symlink(): return ["artifact path must be a real directory"] @@ -1136,6 +1315,9 @@ def validate_artifact_payloads(directory: Path) -> list[str]: "canonical_repository", "checked_sha", "checked_tree_sha", + "authority_path", + "authority_content_revision", + "authority_git_blob_sha", "detached", "clean", }: @@ -1162,6 +1344,32 @@ def validate_artifact_payloads(directory: Path) -> list[str]: errors.append( f"source-revisions.json: checked tree mismatch: {repository}" ) + resolved_entries = { + item["repository"]: item + for item in revisions.get("repositories", []) + if isinstance(item, dict) + } + resolved_entry = resolved_entries.get(str(repository), {}) + if entry.get("authority_path") != CANONICAL_AUTHORITY_PATHS.get( + str(repository) + ): + errors.append( + f"source-revisions.json: authority path mismatch: {repository}" + ) + if entry.get("authority_content_revision") != resolved_entry.get( + "authority_content_revision" + ): + errors.append( + f"source-revisions.json: authority content revision mismatch: " + f"{repository}" + ) + if re.fullmatch( + r"[0-9a-f]{40}", + str(entry.get("authority_git_blob_sha", "")), + ) is None: + errors.append( + f"source-revisions.json: authority blob is invalid: {repository}" + ) if entry.get("detached") is not True or entry.get("clean") is not True: errors.append( f"source-revisions.json: checked state is not clean and detached: {repository}" @@ -1170,6 +1378,18 @@ def validate_artifact_payloads(directory: Path) -> list[str]: errors.append( "source-revisions.json: checked repositories differ from exact order" ) + if source_set is not None and not errors: + actual_records, source_errors = verify_source_set( + source_set, resolved_fields + ) + errors.extend( + f"source-revisions.json: {error}" for error in source_errors + ) + if not source_errors and checked != actual_records: + errors.append( + "source-revisions.json: checked authority records differ from " + "the exact current source set" + ) summary = payloads.get("verification-summary.json") if summary is not None: allowed = { @@ -1410,6 +1630,7 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--source-revisions-output", type=Path) parser.add_argument("--write-verification-summary", type=Path) parser.add_argument("--validate-artifacts", type=Path) + parser.add_argument("--artifact-source-set", type=Path) return parser.parse_args() @@ -1456,7 +1677,16 @@ def main() -> int: elif args.write_verification_summary is not None: write_verification_summary(args.write_verification_summary) elif args.validate_artifacts is not None: - errors.extend(validate_artifact_payloads(args.validate_artifacts)) + if args.artifact_source_set is None: + errors.append( + "--validate-artifacts requires --artifact-source-set" + ) + else: + errors.extend( + validate_artifact_payloads( + args.validate_artifacts, args.artifact_source_set + ) + ) else: errors.extend(run_full_verification(args.self_test)) diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index bf848c3..1153eee 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -142,6 +142,70 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N with self.subTest(label=label): self.assert_rejected(value, label) + def test_exact_run_allowlist_rejects_command_laundering(self) -> None: + command = ( + "python -B source-set/hawkinsoperations-detections/scripts/" + "verify_detection_contract.py" + ) + mutations = { + "or colon": self.workflow.replace(command, f"{command} || :", 1), + "or exit zero": self.workflow.replace(command, f"{command} || exit 0", 1), + "semicolon true": self.workflow.replace(command, f"{command}; true", 1), + "compound swallowed exit": self.workflow.replace( + command, + f"{command} || {{ echo swallowed; exit 0; }}", + 1, + ), + "no-op command prefix": self.workflow.replace(command, f": {command}", 1), + "function override": self.workflow.replace( + command, + f"python() {{ :; }}\n {command}", + 1, + ), + "alias override": self.workflow.replace( + command, + f"alias python=:\n {command}", + 1, + ), + "PATH shadow": self.workflow.replace( + command, + f"PATH=/tmp/hostile:$PATH\n {command}", + 1, + ), + } + for label, value in mutations.items(): + with self.subTest(label=label): + self.assert_rejected(value, label) + + def test_shell_and_job_default_overrides_fail_closed(self) -> None: + mutations = { + "shell suffix": self.workflow.replace( + "shell: bash", "shell: bash {0}; true", 1 + ), + "shell nested exit": self.workflow.replace( + "shell: bash", "shell: bash -c '$0; exit 0' {0}", 1 + ), + "job default shell": self.workflow.replace( + " command-center-invariants:\n runs-on: ubuntu-latest", + " command-center-invariants:\n" + " defaults:\n" + " run:\n" + " shell: bash {0}; true\n" + " runs-on: ubuntu-latest", + 1, + ), + "step working directory": self.workflow.replace( + " - name: Verify command-center invariants\n run:", + " - name: Verify command-center invariants\n" + " working-directory: /tmp\n" + " run:", + 1, + ), + } + for label, value in mutations.items(): + with self.subTest(label=label): + self.assert_rejected(value, label) + def test_trigger_neutralization_and_test_path_omission_fail(self) -> None: mutations = { "closed-only PR": self.workflow.replace( @@ -305,8 +369,11 @@ def create_source_set(self, root: Path) -> dict: self.run_git(repo, "init", "--quiet") self.run_git(repo, "config", "user.name", "Command Center Test") self.run_git(repo, "config", "user.email", "test@invalid.example") - (repo / "authority.txt").write_text(repository + "\n", encoding="utf-8") - self.run_git(repo, "add", "authority.txt") + authority_path = VERIFIER.CANONICAL_AUTHORITY_PATHS[repository] + authority_file = repo / Path(authority_path) + authority_file.parent.mkdir(parents=True, exist_ok=True) + authority_file.write_text(repository + "\n", encoding="utf-8") + self.run_git(repo, "add", authority_path) self.run_git(repo, "commit", "--quiet", "-m", "fixture") sha = self.run_git(repo, "rev-parse", "HEAD") tree = self.run_git(repo, "rev-parse", "HEAD^{tree}") @@ -319,6 +386,7 @@ def create_source_set(self, root: Path) -> dict: "repository": repository, "canonical_repository": f"HawkinsOperations/{repository}", "revision": sha, + "authority_content_revision": sha, "reviewed_tree_sha": tree, } ) @@ -376,6 +444,78 @@ def test_dirty_wrong_origin_branch_and_missing_repo_fail(self) -> None: _, errors = VERIFIER.verify_source_set(root, resolved) self.assertTrue(errors) + def test_authority_content_revision_is_bound_to_canonical_current_blob(self) -> None: + for attack in ("unreachable", "wrong-blob"): + with self.subTest(attack=attack), tempfile.TemporaryDirectory() as temp: + root = Path(temp) / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + target = root / "hawkinsoperations-detections" + entry = resolved["repositories"][1] + if attack == "unreachable": + entry["authority_content_revision"] = "f" * 40 + else: + authority_file = target / Path( + VERIFIER.CANONICAL_AUTHORITY_PATHS[ + "hawkinsoperations-detections" + ] + ) + authority_file.write_text("contradictory authority\n", encoding="utf-8") + self.run_git(target, "add", authority_file.relative_to(target).as_posix()) + self.run_git(target, "commit", "--quiet", "-m", "contradiction") + entry["authority_content_revision"] = self.run_git( + target, "rev-parse", "HEAD" + ) + self.run_git(target, "checkout", "--quiet", "--detach", entry["revision"]) + unsigned = { + key: value + for key, value in resolved.items() + if key != "manifest_sha256" + } + resolved["manifest_sha256"] = VERIFIER.hashlib.sha256( + json.dumps( + unsigned, sort_keys=True, separators=(",", ":") + ).encode("utf-8") + ).hexdigest() + _, errors = VERIFIER.verify_source_set(root, resolved) + self.assertTrue(errors) + + def test_uploaded_authority_blob_record_is_reverified_against_source_set( + self, + ) -> None: + with tempfile.TemporaryDirectory() as temp: + base = Path(temp) + source_root = base / "source-set" + source_root.mkdir() + resolved = self.create_source_set(source_root) + records, errors = VERIFIER.verify_source_set(source_root, resolved) + self.assertEqual([], errors) + artifacts = base / "artifacts" + artifacts.mkdir() + source_record = dict(resolved) + source_record["checked_repositories"] = records + VERIFIER.write_json_atomic( + artifacts / "source-revisions.json", source_record + ) + VERIFIER.write_verification_summary( + artifacts / "verification-summary.json" + ) + self.assertEqual( + [], VERIFIER.validate_artifact_payloads(artifacts, source_root) + ) + path = artifacts / "source-revisions.json" + tampered = VERIFIER.load_json_strict(path) + tampered["checked_repositories"][0][ + "authority_git_blob_sha" + ] = "f" * 40 + VERIFIER.write_json_atomic(path, tampered) + errors = VERIFIER.validate_artifact_payloads( + artifacts, source_root + ) + self.assertTrue( + any("exact current source set" in error for error in errors) + ) + class ArtifactSanitizerTests(unittest.TestCase): def create_valid_artifacts(self, root: Path) -> None: @@ -390,6 +530,13 @@ def create_valid_artifacts(self, root: Path) -> None: "canonical_repository": entry["canonical_repository"], "checked_sha": entry["revision"], "checked_tree_sha": entry["reviewed_tree_sha"], + "authority_path": VERIFIER.CANONICAL_AUTHORITY_PATHS[ + entry["repository"] + ], + "authority_content_revision": entry[ + "authority_content_revision" + ], + "authority_git_blob_sha": "a" * 40, "detached": True, "clean": True, } From ac4677fb1273210154eb8c90805078e7dd492ac5 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 06:29:19 -0500 Subject: [PATCH 023/116] ci(command-center): match owning trust-boundary checks --- .../workflows/command-center-invariants.yml | 10 +++++++++- scripts/verify-command-center-invariants.py | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 0532a0c..73176c8 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -153,7 +153,10 @@ jobs: run: | set -euo pipefail python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract.py - python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix.py + python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix.py \ + --validation-registry source-set/hawkinsoperations-validation/validation/VALIDATION_REGISTRY.yml \ + --proof-index source-set/hawkinsoperations-proof/proof/indexes/DETECTION_PROOF_STATUS_INDEX.yml \ + --require-sibling-handoffs python -B -m unittest discover -s source-set/hawkinsoperations-detections/tests - name: Verify validation authority and fail-closed parity @@ -201,6 +204,9 @@ jobs: python -B -m hoxline.cli case-growth verify \ --repo-root source-set \ --snapshot verification-work/current-case-growth-index.json + python -B -m hoxline.cli case-growth verify \ + --repo-root source-set \ + --snapshot source-set/hoxline/examples/case-growth/current-case-growth-index.json python -B -m hoxline review batch run \ --index source-set/hoxline/examples/review/multi-artifact-review-index-v1.json \ --output verification-work/batch \ @@ -222,7 +228,9 @@ jobs: npm --prefix source-set/hawkinsoperations-website run public-status:owner-self-test npm --prefix source-set/hawkinsoperations-website run public-status:source-checkout-test npm --prefix source-set/hawkinsoperations-website run public-status:freshness-reachability-test + npm --prefix source-set/hawkinsoperations-website run public-status:dirty-provenance-test npm --prefix source-set/hawkinsoperations-website run public-status:nested-claim-test + npm --prefix source-set/hawkinsoperations-website run public-status:strict-json-test npm --prefix source-set/hawkinsoperations-website run public-status:eol-self-test npm --prefix source-set/hawkinsoperations-website run check:site npm --prefix source-set/hawkinsoperations-website run typecheck diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 7367b6f..557048c 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -89,14 +89,14 @@ "Checkout six immutable sibling revisions without credentials": "49ab88b506c80d864d1616ad4ac3c7448ce7187a92ba2bb36404cf6724ada38a", "Verify the exact clean detached source set": "3dbfdd7ea15772914b827f395b09fe23aa61c0d31e91703b05cc3ef8c4476e57", "Detect durable sibling main-content drift": "fa27754b70cd171cac072a868b3632405e5b2c5b8744e34139cf8e64dbcd7a53", - "Verify detection authority and hostile paths": "f65bc86480dc945e0545b9a4a319f0a8dff71bb09d3d331169fe3b2e2b1e63e7", + "Verify detection authority and hostile paths": "a55bb68d511268423e7ed392184dab55f3864c8411d74ff725c54f776daa4d4d", "Verify validation authority and fail-closed parity": "accba85cf224b66e99287179a83418ae779bfc9d8630579ebd375844181411da", "Verify proof authority and reverse inventory": "f07b841030269d74bd563238e59e4ff695e2d140108321f9d33ea364a0d850b8", "Verify platform source contract and seven-source convergence": "698d9e4b0035d4581a87c889bff1c7bb7ef53db957d75688f1364a713be76ee5", "Install Hoxline from the checked immutable source": "f6954cbb94cbc30f5110c536a4c73b71f985953e71e4c08385cf46b7eb8fea0c", - "Verify Hoxline Case Growth pair and replay integrity": "b8950bb94cb7b0b6bbe505b3180c031aeb1dec904e78d820fc761d302798ad69", + "Verify Hoxline Case Growth pair and replay integrity": "979ca538d7eb872fa2da00afbf8e73606ab874d94cc134475d12e2b86b36886b", "Install Website dependencies from the checked lockfile": "4be0617fbf64515a837109e98174e687edc18a027a37368223fff95cb33d8f94", - "Verify Website rendering-only status plane and static build": "2d4c7844b0673771d92373c4674a7828e23a2195c6d8bd29e9cd4e00e92f2493", + "Verify Website rendering-only status plane and static build": "4430722c68c09465e87a12d612e0d721ef0f7b9494b1e77a8b0d8ba3dc2649c8", "Write closed-schema verification summary": "056a198f6f178d60e01d0a0eecda11181372ced82d68793b24fc0676a8cb15b7", "Validate upload artifacts": "e0b9d66521ae1e69ce51a89d1380fcb70f6edbaa8c9a62a7a78aa1c6a4e6ac0f", } @@ -832,6 +832,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: "HAWKINS_PLATFORM_IMMUTABLE_OBSERVED_SHA", "verify_detection_contract.py", "verify_detection_promotion_matrix.py", + "--require-sibling-handoffs", "verify_validation_registry.py", "verify_all_validation_packages.py", "verify_validation_contract.py", @@ -849,7 +850,9 @@ def unsafe_workflow_findings(text: str) -> list[str]: "public-status:owner-self-test", "public-status:source-checkout-test", "public-status:freshness-reachability-test", + "public-status:dirty-provenance-test", "public-status:nested-claim-test", + "public-status:strict-json-test", "public-status:eol-self-test", "git diff --check", "--write-verification-summary", @@ -862,7 +865,15 @@ def unsafe_workflow_findings(text: str) -> list[str]: findings.append(f"workflow missing required behavior: {fragment}") exact_executed_patterns = { "detection contract": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_contract\.py\s*$", - "detection matrix": r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/verify_detection_promotion_matrix\.py\s*$", + "detection matrix": ( + r"(?m)^\s*python -B source-set/hawkinsoperations-detections/scripts/" + r"verify_detection_promotion_matrix\.py \\\s*$\n" + r"^\s*--validation-registry source-set/hawkinsoperations-validation/" + r"validation/VALIDATION_REGISTRY\.yml \\\s*$\n" + r"^\s*--proof-index source-set/hawkinsoperations-proof/proof/indexes/" + r"DETECTION_PROOF_STATUS_INDEX\.yml \\\s*$\n" + r"^\s*--require-sibling-handoffs\s*$" + ), "validation registry exact source": r'(?m)^\s*python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry\.py --detections-root source-set/hawkinsoperations-detections --detections-ref "\$\(git -C source-set/hawkinsoperations-detections rev-parse HEAD\)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST\.json\s*$', "validation unit import root": r'(?m)^\s*PYTHONPATH="\$GITHUB_WORKSPACE/source-set/hawkinsoperations-validation" python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests\s*$', "sibling fetch": r'(?m)^\s*git -C "source-set/\$repo" fetch --quiet origin "\$revision"\s*$', From d879a971e39594e08de89186dc2b34907309d6ba Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 06:54:05 -0500 Subject: [PATCH 024/116] fix(ci): enforce controlled-test vocabulary --- scripts/verify-command-center-invariants.py | 57 ++++++++++++++++++++ tests/test_command_center_workflow_safety.py | 30 +++++++++++ 2 files changed, 87 insertions(+) diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 557048c..8bdac11 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -297,6 +297,62 @@ def iter_text_files() -> list[Path]: return sorted(set(files)) +def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: + retired = "".join(("syn", "thetic")) + findings: list[str] = [] + listed = subprocess.run( + ["git", "-C", str(repo_root), "ls-files", "-z"], + capture_output=True, + check=False, + ) + if listed.returncode != 0: + return ["tracked-source vocabulary check could not enumerate Git-tracked files"] + try: + tracked_paths = listed.stdout.decode("utf-8").split("\0") + except UnicodeDecodeError: + return ["tracked-source vocabulary filename inventory is not valid UTF-8"] + for relative in filter(None, tracked_paths): + if retired in relative.casefold(): + findings.append( + f"retired fixture vocabulary appears in tracked filename: {relative}" + ) + scanned = subprocess.run( + [ + "git", + "-C", + str(repo_root), + "grep", + "-n", + "-I", + "-i", + "-F", + retired, + "--", + ".", + ], + capture_output=True, + check=False, + ) + if scanned.returncode not in {0, 1}: + findings.append( + "tracked-source vocabulary content scan failed before producing a decision" + ) + return findings + if scanned.returncode == 0: + try: + matches = scanned.stdout.decode("utf-8").splitlines() + except UnicodeDecodeError: + findings.append( + "tracked-source vocabulary content findings are not valid UTF-8" + ) + else: + findings.extend( + f"retired fixture vocabulary appears in tracked content: {match}" + for match in matches + ) + return findings + + def reject_duplicate_object_pairs(pairs: list[tuple[str, Any]]) -> dict[str, Any]: result: dict[str, Any] = {} normalized: set[str] = set() @@ -1611,6 +1667,7 @@ def check_identity_and_claim_context( def run_full_verification(self_test: bool) -> list[str]: errors: list[str] = [] + errors.extend(tracked_vocabulary_findings()) manifest = load_manifest(errors) source_manifest = load_source_manifest(errors) check_required_files(manifest, errors) diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 1153eee..8b09824 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -28,6 +28,36 @@ def assert_rejected(self, value: str, label: str) -> None: f"hostile workflow was accepted: {label}", ) + def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: + retired = "".join(("syn", "thetic")) + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + subprocess.run( + ["git", "init", "--quiet"], + cwd=root, + check=True, + capture_output=True, + ) + content_path = root / "content-fixture.txt" + filename_path = root / f"fixture-{retired}.txt" + content_path.write_text( + f"controlled-test boundary rejects {retired}\n", + encoding="utf-8", + ) + filename_path.write_text( + "controlled-test boundary\n", + encoding="utf-8", + ) + subprocess.run( + ["git", "add", "--", content_path.name, filename_path.name], + cwd=root, + check=True, + capture_output=True, + ) + findings = VERIFIER.tracked_vocabulary_findings(root) + self.assertTrue(any("tracked content" in item for item in findings)) + self.assertTrue(any("tracked filename" in item for item in findings)) + def test_current_workflow_is_structurally_safe(self) -> None: self.assertEqual([], VERIFIER.unsafe_workflow_findings(self.workflow)) From 376436899f8098c6c006f92d811f9511341c794e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 07:23:45 -0500 Subject: [PATCH 025/116] fix(ci): fail closed on vocabulary scan evasions --- scripts/verify-command-center-invariants.py | 61 ++++++++++---------- tests/test_command_center_workflow_safety.py | 41 ++++++++++++- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 8bdac11..1baf237 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -9,6 +9,7 @@ import re import subprocess import sys +import unicodedata from pathlib import Path, PurePosixPath, PureWindowsPath from typing import Any from urllib.parse import unquote @@ -299,6 +300,14 @@ def iter_text_files() -> list[Path]: def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: retired = "".join(("syn", "thetic")) + binary_extensions = frozenset( + { + ".7z", ".avif", ".avi", ".bz2", ".dll", ".dylib", ".eot", ".exe", ".gif", + ".gz", ".ico", ".jpeg", ".jpg", ".mov", ".mp3", ".mp4", ".pdf", + ".png", ".pyc", ".so", ".tar", ".tgz", ".ttf", ".wasm", ".webp", + ".woff", ".woff2", ".xz", ".zip", + } + ) findings: list[str] = [] listed = subprocess.run( ["git", "-C", str(repo_root), "ls-files", "-z"], @@ -312,43 +321,37 @@ def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: except UnicodeDecodeError: return ["tracked-source vocabulary filename inventory is not valid UTF-8"] for relative in filter(None, tracked_paths): - if retired in relative.casefold(): + if retired in unicodedata.normalize("NFKC", relative).casefold(): findings.append( f"retired fixture vocabulary appears in tracked filename: {relative}" ) - scanned = subprocess.run( - [ - "git", - "-C", - str(repo_root), - "grep", - "-n", - "-I", - "-i", - "-F", - retired, - "--", - ".", - ], - capture_output=True, - check=False, - ) - if scanned.returncode not in {0, 1}: - findings.append( - "tracked-source vocabulary content scan failed before producing a decision" + if PurePosixPath(relative).suffix.casefold() in binary_extensions: + continue + scanned = subprocess.run( + ["git", "-C", str(repo_root), "show", f":{relative}"], + capture_output=True, + check=False, ) - return findings - if scanned.returncode == 0: + if scanned.returncode != 0: + findings.append( + f"tracked-source vocabulary check could not read indexed content: {relative}" + ) + continue + if b"\0" in scanned.stdout: + findings.append( + f"tracked non-binary content contains NUL: {relative}" + ) + continue try: - matches = scanned.stdout.decode("utf-8").splitlines() + text = scanned.stdout.decode("utf-8") except UnicodeDecodeError: findings.append( - "tracked-source vocabulary content findings are not valid UTF-8" + f"tracked non-binary content is not UTF-8: {relative}" ) - else: - findings.extend( - f"retired fixture vocabulary appears in tracked content: {match}" - for match in matches + continue + if retired in unicodedata.normalize("NFKC", text).casefold(): + findings.append( + f"retired fixture vocabulary appears in tracked content: {relative}" ) return findings diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 8b09824..0094ddf 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -6,6 +6,7 @@ import tempfile import unittest from pathlib import Path +from unittest import mock REPO_ROOT = Path(__file__).resolve().parents[1] @@ -30,6 +31,7 @@ def assert_rejected(self, value: str, label: str) -> None: def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: retired = "".join(("syn", "thetic")) + fullwidth = "".join(chr(ord(character) + 0xFEE0) for character in retired) with tempfile.TemporaryDirectory() as temp: root = Path(temp) subprocess.run( @@ -39,17 +41,28 @@ def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: capture_output=True, ) content_path = root / "content-fixture.txt" - filename_path = root / f"fixture-{retired}.txt" + filename_path = root / f"fixture-{fullwidth}.txt" + utf16_path = root / "utf16-fixture.md" content_path.write_text( - f"controlled-test boundary rejects {retired}\n", + f"controlled-test boundary rejects {fullwidth}\n", encoding="utf-8", ) filename_path.write_text( "controlled-test boundary\n", encoding="utf-8", ) + utf16_path.write_bytes( + f"controlled-test {retired}\n".encode("utf-16-le") + ) subprocess.run( - ["git", "add", "--", content_path.name, filename_path.name], + [ + "git", + "add", + "--", + content_path.name, + filename_path.name, + utf16_path.name, + ], cwd=root, check=True, capture_output=True, @@ -57,6 +70,28 @@ def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: findings = VERIFIER.tracked_vocabulary_findings(root) self.assertTrue(any("tracked content" in item for item in findings)) self.assertTrue(any("tracked filename" in item for item in findings)) + self.assertTrue(any("utf16-fixture.md" in item for item in findings)) + + def test_tracked_vocabulary_guard_fails_on_indexed_read_error(self) -> None: + listed = subprocess.CompletedProcess( + args=["git", "ls-files"], + returncode=0, + stdout=b"fixture.md\0", + stderr=b"", + ) + unreadable = subprocess.CompletedProcess( + args=["git", "show"], + returncode=128, + stdout=b"", + stderr=b"unreadable", + ) + with mock.patch.object( + VERIFIER.subprocess, + "run", + side_effect=(listed, unreadable), + ): + findings = VERIFIER.tracked_vocabulary_findings(REPO_ROOT) + self.assertTrue(any("could not read indexed content" in item for item in findings)) def test_current_workflow_is_structurally_safe(self) -> None: self.assertEqual([], VERIFIER.unsafe_workflow_findings(self.workflow)) From 0dc7708e4b3c3d93d50cea3fd48ea6fc9a7777a3 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 07:27:48 -0500 Subject: [PATCH 026/116] ci(command-center): require cross-repo claim parity --- .github/workflows/command-center-invariants.yml | 1 + scripts/verify-command-center-invariants.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 73176c8..848c372 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -168,6 +168,7 @@ jobs: python -B source-set/hawkinsoperations-validation/scripts/verify_validation_contract.py python -B source-set/hawkinsoperations-validation/scripts/verify_wazuh_logtest_registry.py python -B source-set/hawkinsoperations-validation/scripts/verify_ho_lab_wazuh_001.py + python -B source-set/hawkinsoperations-validation/scripts/verify_cross_repo_claim_parity.py --repo-root source-set --enforce PYTHONPATH="$GITHUB_WORKSPACE/source-set/hawkinsoperations-validation" python -B -m unittest discover -s source-set/hawkinsoperations-validation/tests - name: Verify proof authority and reverse inventory diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 1baf237..6f05bdc 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -91,7 +91,7 @@ "Verify the exact clean detached source set": "3dbfdd7ea15772914b827f395b09fe23aa61c0d31e91703b05cc3ef8c4476e57", "Detect durable sibling main-content drift": "fa27754b70cd171cac072a868b3632405e5b2c5b8744e34139cf8e64dbcd7a53", "Verify detection authority and hostile paths": "a55bb68d511268423e7ed392184dab55f3864c8411d74ff725c54f776daa4d4d", - "Verify validation authority and fail-closed parity": "accba85cf224b66e99287179a83418ae779bfc9d8630579ebd375844181411da", + "Verify validation authority and fail-closed parity": "fe94626b4d2064476cc9fdca3b85b4dc4604c30cca7660a911bf9bbbb1cbc3bd", "Verify proof authority and reverse inventory": "f07b841030269d74bd563238e59e4ff695e2d140108321f9d33ea364a0d850b8", "Verify platform source contract and seven-source convergence": "698d9e4b0035d4581a87c889bff1c7bb7ef53db957d75688f1364a713be76ee5", "Install Hoxline from the checked immutable source": "f6954cbb94cbc30f5110c536a4c73b71f985953e71e4c08385cf46b7eb8fea0c", From 33cdacef8bcb7e685c4a46ae644afe76f533631f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 08:59:48 -0500 Subject: [PATCH 027/116] fix(governance): normalize vocabulary security scans --- scripts/verify-command-center-invariants.py | 14 +++++++-- tests/test_command_center_workflow_safety.py | 32 ++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 6f05bdc..3eb9835 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -298,6 +298,16 @@ def iter_text_files() -> list[Path]: return sorted(set(files)) +def normalize_vocabulary_security_text(value: str) -> str: + """Collapse Unicode token-splitting characters for security matching only.""" + normalized = unicodedata.normalize("NFKD", value) + return "".join( + character + for character in normalized + if not unicodedata.category(character).startswith(("C", "M")) + ) + + def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: retired = "".join(("syn", "thetic")) binary_extensions = frozenset( @@ -321,7 +331,7 @@ def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: except UnicodeDecodeError: return ["tracked-source vocabulary filename inventory is not valid UTF-8"] for relative in filter(None, tracked_paths): - if retired in unicodedata.normalize("NFKC", relative).casefold(): + if retired in normalize_vocabulary_security_text(relative).casefold(): findings.append( f"retired fixture vocabulary appears in tracked filename: {relative}" ) @@ -349,7 +359,7 @@ def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: f"tracked non-binary content is not UTF-8: {relative}" ) continue - if retired in unicodedata.normalize("NFKC", text).casefold(): + if retired in normalize_vocabulary_security_text(text).casefold(): findings.append( f"retired fixture vocabulary appears in tracked content: {relative}" ) diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 0094ddf..f889b11 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -32,6 +32,8 @@ def assert_rejected(self, value: str, label: str) -> None: def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: retired = "".join(("syn", "thetic")) fullwidth = "".join(chr(ord(character) + 0xFEE0) for character in retired) + zero_width = retired[:3] + "\u200b" + retired[3:] + combining = retired[:3] + "\u034f" + retired[3:] with tempfile.TemporaryDirectory() as temp: root = Path(temp) subprocess.run( @@ -44,13 +46,27 @@ def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: filename_path = root / f"fixture-{fullwidth}.txt" utf16_path = root / "utf16-fixture.md" content_path.write_text( - f"controlled-test boundary rejects {fullwidth}\n", + ( + f"controlled-test boundary rejects {fullwidth}\n" + f"controlled-test boundary rejects {zero_width}\n" + f"controlled-test boundary rejects {combining}\n" + ), encoding="utf-8", ) filename_path.write_text( "controlled-test boundary\n", encoding="utf-8", ) + zero_width_filename_path = root / f"fixture-{zero_width}.txt" + combining_filename_path = root / f"fixture-{combining}.txt" + zero_width_filename_path.write_text( + "controlled-test boundary\n", + encoding="utf-8", + ) + combining_filename_path.write_text( + "controlled-test boundary\n", + encoding="utf-8", + ) utf16_path.write_bytes( f"controlled-test {retired}\n".encode("utf-16-le") ) @@ -61,6 +77,8 @@ def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: "--", content_path.name, filename_path.name, + zero_width_filename_path.name, + combining_filename_path.name, utf16_path.name, ], cwd=root, @@ -69,9 +87,19 @@ def test_tracked_vocabulary_guard_rejects_content_and_filename(self) -> None: ) findings = VERIFIER.tracked_vocabulary_findings(root) self.assertTrue(any("tracked content" in item for item in findings)) - self.assertTrue(any("tracked filename" in item for item in findings)) + self.assertGreaterEqual( + sum("tracked filename" in item for item in findings), + 3, + ) self.assertTrue(any("utf16-fixture.md" in item for item in findings)) + def test_vocabulary_security_view_preserves_benign_unicode_semantics(self) -> None: + normalized = VERIFIER.normalize_vocabulary_security_text( + "Café résumé – review 👩‍💻 only" + ) + self.assertNotIn("synthetic", normalized.casefold()) + self.assertIn("Cafe resume", normalized) + def test_tracked_vocabulary_guard_fails_on_indexed_read_error(self) -> None: listed = subprocess.CompletedProcess( args=["git", "ls-files"], From cb76579b5b6a178ed3bc494eae6d04e4473d1d27 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 09:20:16 -0500 Subject: [PATCH 028/116] test(governance): keep vocabulary controls bounded --- tests/test_command_center_workflow_safety.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index f889b11..eec239f 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -97,7 +97,8 @@ def test_vocabulary_security_view_preserves_benign_unicode_semantics(self) -> No normalized = VERIFIER.normalize_vocabulary_security_text( "Café résumé – review 👩‍💻 only" ) - self.assertNotIn("synthetic", normalized.casefold()) + retired = "".join(("syn", "thetic")) + self.assertNotIn(retired, normalized.casefold()) self.assertIn("Cafe resume", normalized) def test_tracked_vocabulary_guard_fails_on_indexed_read_error(self) -> None: From 4c04ace8ddfe9aca9e6ad91e7984995210fa4025 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 09:54:22 -0500 Subject: [PATCH 029/116] chore(command-center): select hardened source heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 36 ++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7c577ec..79f241e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -6,50 +6,50 @@ "repository": ".github", "canonical_repository": "HawkinsOperations/.github", "revision_source": "github_event_sha", - "authority_content_revision": "43fd17e7e66606fac92994cfc9eeb3871a03eff1", + "authority_content_revision": "6e6763a81d6af09c2e4588462b56117ce82c2f88", "tree_source": "github_event_tree" }, { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "16d4432eb46d457939f1cfe573c0c5d712650efb", - "authority_content_revision": "16d4432eb46d457939f1cfe573c0c5d712650efb", - "reviewed_tree_sha": "74a33886c498ed0c0c79360d0fc2485dea4b4cf7" + "revision": "11a481afbc739c994ce19cdb12052a307a6eec77", + "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", + "reviewed_tree_sha": "48e43af2aebb0d0d4ef6b321cbd116b8f7f0df04" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "34bbfc4f48f75f647d5946b4cbe6835abf5e7dbc", - "authority_content_revision": "34bbfc4f48f75f647d5946b4cbe6835abf5e7dbc", - "reviewed_tree_sha": "edc1f917dfa86cdc32bc47190957786a7dc400c3" + "revision": "2e833f340e183e8e2357c860314509c6d1cc2dd3", + "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", + "reviewed_tree_sha": "a6852d017cd51510ff32ce319114a4b1cd5b1a0c" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "d9ffb49baeb96b9f5789a7dc9d56e028909fd89d", + "revision": "2192bae326e47681884fd82e9ab762f2ba04e53a", "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "e900c448b3feacc0c21abda35ae75910d3289354" + "reviewed_tree_sha": "aac06c90f0db6f812799b09376593e7b07f72d02" }, { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", - "revision": "c60882552571c1664549d3e594c6994dc27dce63", - "authority_content_revision": "c60882552571c1664549d3e594c6994dc27dce63", - "reviewed_tree_sha": "2f84647f298b36a2286aaddf4ebeedf5e0c3cc82" + "revision": "79d4bff2dccb24c2b29a68f4a3be7a1e916414b4", + "authority_content_revision": "042a918ad4a8473cd5abcfd575072fc094639682", + "reviewed_tree_sha": "a1d23af53a8515ab38b14f767f8de7f9984ec567" }, { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "0230c42fb4aa40aa3c917505457848da4f9883c2", - "authority_content_revision": "0230c42fb4aa40aa3c917505457848da4f9883c2", - "reviewed_tree_sha": "e0af2684c80bcd9f368f38eb01aa9ffcb5898f8f" + "revision": "048a11ea7e0404a7d426e900f2d9584b842e4bb3", + "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", + "reviewed_tree_sha": "e904a247dc8cde8d095b68ac8f978f012a792443" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "47c72da9f4dbbfb8f4a602136345f5428c497167", - "authority_content_revision": "cc0e3e11b86b8998eccaec7d7981cc4f051f156e", - "reviewed_tree_sha": "7e43bf40313e97172074025aa0fe667fd08b57ba" + "revision": "6d1581393deb8a1ffe1894b2761056d3af792746", + "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", + "reviewed_tree_sha": "71ce96b835278b245cd81969bb5ceb95ebeab514" } ], "constraints": { From 76f2897b30d0e1b92799cd4c2d87ea7700fd2779 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 10:09:18 -0500 Subject: [PATCH 030/116] chore(command-center): review final convergence code heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 79f241e..d380817 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "2192bae326e47681884fd82e9ab762f2ba04e53a", + "revision": "bca89adb3222c34b81458e319e5272402256ec6f", "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "aac06c90f0db6f812799b09376593e7b07f72d02" + "reviewed_tree_sha": "1addf4477f14e7cc3e8beabf76d09f6a10314f69" }, { "repository": "hawkinsoperations-proof", @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "048a11ea7e0404a7d426e900f2d9584b842e4bb3", + "revision": "d7e43ff8458448fedf43055538b5e27d780ab062", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "e904a247dc8cde8d095b68ac8f978f012a792443" + "reviewed_tree_sha": "ad42f71c0ea0a8e1223f5047ddad73d248fff089" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "6d1581393deb8a1ffe1894b2761056d3af792746", + "revision": "d8aeb256b0642ad210550a0f21e3bdd9a93b5d49", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "71ce96b835278b245cd81969bb5ceb95ebeab514" + "reviewed_tree_sha": "36bda4da12278b32d3219e742323fd06e3b3d7ca" } ], "constraints": { From a93f3b99477507063c8321fdc20a64ef57d0a801 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 10:31:43 -0500 Subject: [PATCH 031/116] chore(command-center): review final website identity logic --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index d380817..72051ef 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "d7e43ff8458448fedf43055538b5e27d780ab062", + "revision": "c76f49828f457d5004ede6f674013e9349e9d7e8", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "ad42f71c0ea0a8e1223f5047ddad73d248fff089" + "reviewed_tree_sha": "a511783d6645d4636501478049268854438427e2" }, { "repository": "hoxline", From e806e91e3047a9ec235b2aa83c19a340034eb578 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:00:55 -0500 Subject: [PATCH 032/116] chore(command-center): review final generator substitution guard --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 72051ef..81e1561 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "c76f49828f457d5004ede6f674013e9349e9d7e8", + "revision": "5aa2d6699f9836df430b6ba3fff527ffcdbc95fa", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "a511783d6645d4636501478049268854438427e2" + "reviewed_tree_sha": "8f70d4ed86b9f5091e1aa338deab4705d9272000" }, { "repository": "hoxline", From 3a9a25498effcc7e364d4d8c4ced19983b0f5238 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:29:20 -0500 Subject: [PATCH 033/116] chore(command-center): seal hardened generated state --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 81e1561..a3be6e5 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "5aa2d6699f9836df430b6ba3fff527ffcdbc95fa", + "revision": "8be70f1614d37eec590fdb1bb9234de312711021", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "8f70d4ed86b9f5091e1aa338deab4705d9272000" + "reviewed_tree_sha": "46e3ece930f05c9412cdab07ac224949c3039168" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "d8aeb256b0642ad210550a0f21e3bdd9a93b5d49", + "revision": "fb0cb3bd45fd046d82742e53d858800c58ef8c7f", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "36bda4da12278b32d3219e742323fd06e3b3d7ca" + "reviewed_tree_sha": "dd3b194111d937ba1a6cde65b74459b435529e1f" } ], "constraints": { From 09400482786a99384a2cb42d1505253568bf85c3 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:38:22 -0500 Subject: [PATCH 034/116] chore(command-center): review final Website projection repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index a3be6e5..40dc764 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "8be70f1614d37eec590fdb1bb9234de312711021", + "revision": "93828c0e7002c3abdefdf2762ed3da452dd55078", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "46e3ece930f05c9412cdab07ac224949c3039168" + "reviewed_tree_sha": "b4b79425f6ea3bfeff00016524ec643508c48a21" }, { "repository": "hoxline", From 350602ef3514db397b9c587d54113f7b185113c0 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:40:23 -0500 Subject: [PATCH 035/116] chore(command-center): seal final generated Website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 40dc764..29666c4 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "93828c0e7002c3abdefdf2762ed3da452dd55078", + "revision": "91ac06fc7add623fe320e8ab469a842b674c4a5a", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "b4b79425f6ea3bfeff00016524ec643508c48a21" + "reviewed_tree_sha": "0858c8521d42eff2098e712ad5da5a164ed4025c" }, { "repository": "hoxline", From eec78d80cb78f02cf82b3861c38c776f41cb9084 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:53:09 -0500 Subject: [PATCH 036/116] chore(command-center): review final Platform and Website repairs --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 29666c4..08da53a 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "bca89adb3222c34b81458e319e5272402256ec6f", - "authority_content_revision": "541ffcd0e94e9db94638d8ffa5934da11ae38771", - "reviewed_tree_sha": "1addf4477f14e7cc3e8beabf76d09f6a10314f69" + "revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", + "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", + "reviewed_tree_sha": "54d73b1b2e75a7d17b31b2e8e381d608fce97cfe" }, { "repository": "hawkinsoperations-proof", @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "91ac06fc7add623fe320e8ab469a842b674c4a5a", + "revision": "dc27bdc7673332a571e1c0723fbfe4744e7dbd03", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "0858c8521d42eff2098e712ad5da5a164ed4025c" + "reviewed_tree_sha": "9274625f95345324fd0cd838753dd1ca0af0402f" }, { "repository": "hoxline", From 503d3af7b84b9fe9c76ca06db0ae2a87925fb32f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:55:49 -0500 Subject: [PATCH 037/116] chore(command-center): seal hardened Website data pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 08da53a..0f931fd 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "dc27bdc7673332a571e1c0723fbfe4744e7dbd03", + "revision": "50cb1a2fd39887de9e413b450a8af37090953102", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "9274625f95345324fd0cd838753dd1ca0af0402f" + "reviewed_tree_sha": "ae99b730d317e66ea3f62bd7d5d34d356578e499" }, { "repository": "hoxline", From 841f37a68f737ab9d4a93a7c9669af6aea38c27d Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 11:58:21 -0500 Subject: [PATCH 038/116] chore(command-center): review one-sided pair rejection --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 0f931fd..eaed1e6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "50cb1a2fd39887de9e413b450a8af37090953102", + "revision": "cfe6c049480964c28dd733cb54ac0917302772c8", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "ae99b730d317e66ea3f62bd7d5d34d356578e499" + "reviewed_tree_sha": "45fe7d7bce86429261f0ae5fcfe2d7998890c6bb" }, { "repository": "hoxline", From ab4a4e071784e861e8604be6543e39dd5548478f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:03:15 -0500 Subject: [PATCH 039/116] chore(command-center): review final projection model --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index eaed1e6..ffaa171 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "cfe6c049480964c28dd733cb54ac0917302772c8", + "revision": "f95bb2f9e99dde48aa16b2c0bec060c083facdfb", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "45fe7d7bce86429261f0ae5fcfe2d7998890c6bb" + "reviewed_tree_sha": "8116527a2f02c259f9ad4823e64a5acf5e179b2c" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "fb0cb3bd45fd046d82742e53d858800c58ef8c7f", + "revision": "768fd2263a123fe6a508849a9f5eaed37f403135", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "dd3b194111d937ba1a6cde65b74459b435529e1f" + "reviewed_tree_sha": "65066d5a13c31e0606fba39940439777705b8267" } ], "constraints": { From da64b4638b46696274206cc85ecb44427b2c9566 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:05:36 -0500 Subject: [PATCH 040/116] chore(command-center): seal final Website status pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index ffaa171..f2e904e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "f95bb2f9e99dde48aa16b2c0bec060c083facdfb", + "revision": "8a08611f9562e9b34a7422a7c3faeabfe69aba0a", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "8116527a2f02c259f9ad4823e64a5acf5e179b2c" + "reviewed_tree_sha": "eb7adedc43960fc332534488960581b168ea6b6b" }, { "repository": "hoxline", From a591c8fb7977222dcd1aff1b1541392652e84554 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:08:04 -0500 Subject: [PATCH 041/116] chore(command-center): seal final Hoxline Case Growth pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index f2e904e..8da1ad7 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "768fd2263a123fe6a508849a9f5eaed37f403135", + "revision": "0b40f45ec7b5275effb8270ab3382fa6df218e95", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "65066d5a13c31e0606fba39940439777705b8267" + "reviewed_tree_sha": "e12a1980e5a696d60bb1fe4f8ee6cf5e0f66f63c" } ], "constraints": { From a3803960c3da395555c9e8bcabb12d98543d37fc Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:19:27 -0500 Subject: [PATCH 042/116] chore(command-center): review merge-resilient Platform verifier --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8da1ad7..9dc3639 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", + "revision": "8ad2ec22595c3cccf6696a07d9708c3397d60175", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "54d73b1b2e75a7d17b31b2e8e381d608fce97cfe" + "reviewed_tree_sha": "1a4bd83c807a93291f0f955b73452310ca677337" }, { "repository": "hawkinsoperations-proof", From 7ed69fa7656121f3e595b83de61705557aa073d7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:22:42 -0500 Subject: [PATCH 043/116] chore(command-center): seal final Platform observation refresh --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 9dc3639..4b4fd3d 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "8a08611f9562e9b34a7422a7c3faeabfe69aba0a", + "revision": "ad76debe8f183477f1f8244c04d19177cce3aede", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "eb7adedc43960fc332534488960581b168ea6b6b" + "reviewed_tree_sha": "f8806f1f63bd0a6b5b9d277643c8d218d977f516" }, { "repository": "hoxline", From d4ed132b97b75a5dbe78aa816d832c5149fb6b51 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:28:15 -0500 Subject: [PATCH 044/116] chore(command-center): review strategy-resilient source heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 4b4fd3d..642e888 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "8ad2ec22595c3cccf6696a07d9708c3397d60175", + "revision": "1662b888858a605057f2189ac00e4a0d8fb78873", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "1a4bd83c807a93291f0f955b73452310ca677337" + "reviewed_tree_sha": "a5d0a5a4dd46fcdd73304264890a9b9bb3e54f9e" }, { "repository": "hawkinsoperations-proof", @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "0b40f45ec7b5275effb8270ab3382fa6df218e95", + "revision": "84c7be52b3077d4b9075954de8900693813c725e", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "e12a1980e5a696d60bb1fe4f8ee6cf5e0f66f63c" + "reviewed_tree_sha": "9ada0c6433dbfd7b1efb200a4fa5c23d13945816" } ], "constraints": { From bba6e6a2afd13baae36c339edb023109f0eb184f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:31:23 -0500 Subject: [PATCH 045/116] chore(command-center): seal strategy-resilient Website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 642e888..8dfa62a 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "ad76debe8f183477f1f8244c04d19177cce3aede", + "revision": "4d66cfe7401aa90589b378960941cc0d402a7cde", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "f8806f1f63bd0a6b5b9d277643c8d218d977f516" + "reviewed_tree_sha": "35ab95d56421a79f659855b9e3f8a38b9d635c40" }, { "repository": "hoxline", From 4f8d7d21c4206dc136ed1784786e902a5b712af0 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:34:03 -0500 Subject: [PATCH 046/116] chore(command-center): seal final strategy-resilient Hoxline pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8dfa62a..cffea28 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "84c7be52b3077d4b9075954de8900693813c725e", + "revision": "92e40bfe6c516c2f67f0efd1478e355f1b7c0374", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "9ada0c6433dbfd7b1efb200a4fa5c23d13945816" + "reviewed_tree_sha": "8eabc2b51a8bdb922f617370518ddbfb5504a9fe" } ], "constraints": { From e7b3cfbbb4c7984222c40a73d0dba910296c31b5 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:48:22 -0500 Subject: [PATCH 047/116] chore(command-center): review explicit observation verifier --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index cffea28..0e8e6c6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "1662b888858a605057f2189ac00e4a0d8fb78873", + "revision": "152a28ca790ca16c81e3815fa3139fd6b4a26610", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "a5d0a5a4dd46fcdd73304264890a9b9bb3e54f9e" + "reviewed_tree_sha": "4dbc11b524160b644b0b2b266a8ccbd543bed87d" }, { "repository": "hawkinsoperations-proof", From 8b7a498fbbcdf7d135a44d558eb512a17a837316 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:52:42 -0500 Subject: [PATCH 048/116] chore(command-center): review rewritten-head Website verifier --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 0e8e6c6..b96d9cb 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "4d66cfe7401aa90589b378960941cc0d402a7cde", + "revision": "75aad797572fb61d6fa90fdee7eb932840078307", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "35ab95d56421a79f659855b9e3f8a38b9d635c40" + "reviewed_tree_sha": "2ee645d066a6ec817d2e917b2f4faadfa6f74ba4" }, { "repository": "hoxline", From b99a82c7ef012a927eb56eb00cef64d30ba077bf Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:58:18 -0500 Subject: [PATCH 049/116] chore(command-center): seal rewritten-head-safe Website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index b96d9cb..b64d2a9 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "75aad797572fb61d6fa90fdee7eb932840078307", + "revision": "42f327f1bda0ef1f90ac55eb54f6150201690936", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "2ee645d066a6ec817d2e917b2f4faadfa6f74ba4" + "reviewed_tree_sha": "a7418f15f7ae4b73f52d4bdab28971984e3cda69" }, { "repository": "hoxline", From 6878d9e8730b45e8b56709692da76f859887fe23 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:59:22 -0500 Subject: [PATCH 050/116] chore(command-center): review generator identity binding --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index b64d2a9..7c738b6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "42f327f1bda0ef1f90ac55eb54f6150201690936", + "revision": "bc79824a7e50073cb93816ec53c0f0aa68e6dedf", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "a7418f15f7ae4b73f52d4bdab28971984e3cda69" + "reviewed_tree_sha": "9f300e8e9ca9d17d875a5f6e61a4e8eed4eb1256" }, { "repository": "hoxline", From 842cf348ae778899c80a7c9cf7c5b724b208bf88 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 12:59:56 -0500 Subject: [PATCH 051/116] chore(command-center): review revision-substitution rejection --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7c738b6..8ac8a58 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "bc79824a7e50073cb93816ec53c0f0aa68e6dedf", + "revision": "c36e8d5bd2efbec094574e243c37a88bc505cc35", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "9f300e8e9ca9d17d875a5f6e61a4e8eed4eb1256" + "reviewed_tree_sha": "b07457d5ab6a107c7269a73a8eed1849235c4466" }, { "repository": "hoxline", From 0868ba3903f5f50c4e50a5806957247abd60cbfd Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 13:05:42 -0500 Subject: [PATCH 052/116] chore(command-center): seal final rewrite-resilient Website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8ac8a58..f3be6ea 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "c36e8d5bd2efbec094574e243c37a88bc505cc35", + "revision": "6719cc6b54e77cb3d46231b12ac19718ca3c3343", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "b07457d5ab6a107c7269a73a8eed1849235c4466" + "reviewed_tree_sha": "351ec3725810cc1111dca4ba1cacc21e97fe08fa" }, { "repository": "hoxline", From 2be25d5fe88615a83ebb922f70d08904615f9769 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 13:09:10 -0500 Subject: [PATCH 053/116] chore(command-center): seal explicit-observation Hoxline pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index f3be6ea..182118b 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "92e40bfe6c516c2f67f0efd1478e355f1b7c0374", + "revision": "385f3a09c9bae92ac481123ebd40d20ca2643451", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "8eabc2b51a8bdb922f617370518ddbfb5504a9fe" + "reviewed_tree_sha": "596c9f4f1d6e423bdd3ddc79e3bfb0eabf0b24c3" } ], "constraints": { From 1050238b15ee89d6efcb792ff1c4ddadc38e69a0 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 13:56:00 -0500 Subject: [PATCH 054/116] chore(command-center): review rewrite-resilient consumers --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 182118b..cf88679 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "152a28ca790ca16c81e3815fa3139fd6b4a26610", + "revision": "7357a0cc8f87bb4b455969279122d9a195da49c8", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "4dbc11b524160b644b0b2b266a8ccbd543bed87d" + "reviewed_tree_sha": "e6d6cfe785a8577c36ae1ff449ddff169de97234" }, { "repository": "hawkinsoperations-proof", @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "6719cc6b54e77cb3d46231b12ac19718ca3c3343", + "revision": "01dcaa42fcadb31d6fba291b3a4acca020df03a3", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "351ec3725810cc1111dca4ba1cacc21e97fe08fa" + "reviewed_tree_sha": "93b86daf35dfd8464557f48cc1f899dc5540175d" }, { "repository": "hoxline", From a54f2c19913bdd010de5a752b348a0115f4abd93 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 13:58:02 -0500 Subject: [PATCH 055/116] chore(command-center): seal regenerated website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index cf88679..35fa9a4 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "01dcaa42fcadb31d6fba291b3a4acca020df03a3", + "revision": "3aaf8d38e51d2fb59403acb99b01e04badd173ba", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "93b86daf35dfd8464557f48cc1f899dc5540175d" + "reviewed_tree_sha": "a5e651abcd7784e033ec68d18d73712451b82d2a" }, { "repository": "hoxline", From cbf4daea4f7cb5580b507dbb5276db2b04e8b257 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 14:00:12 -0500 Subject: [PATCH 056/116] chore(command-center): seal rewrite-resilient Hoxline pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 35fa9a4..7a1992c 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "385f3a09c9bae92ac481123ebd40d20ca2643451", + "revision": "804b19eead9a71066a9a4f28286015e0a2397aae", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "596c9f4f1d6e423bdd3ddc79e3bfb0eabf0b24c3" + "reviewed_tree_sha": "bce107a81e7dc2adc572e9bdb1e6cb1e2743f1a4" } ], "constraints": { From df00940dd11785811ae990262e98b2f245f8293e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 15:20:42 -0500 Subject: [PATCH 057/116] chore(command-center): seal schema-aware Hoxline pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7a1992c..665de31 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "804b19eead9a71066a9a4f28286015e0a2397aae", + "revision": "7c842a1ad7f30f3c516082b31ed9fc892ca70a58", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "bce107a81e7dc2adc572e9bdb1e6cb1e2743f1a4" + "reviewed_tree_sha": "1f02e5e5763963727afd7386394b6db422c15474" } ], "constraints": { From 9d87c265f8bf123e90b9cdb70f75401a049acbd5 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 15:25:58 -0500 Subject: [PATCH 058/116] chore(command-center): review consumer-path generator repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 665de31..5fdd07a 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "3aaf8d38e51d2fb59403acb99b01e04badd173ba", + "revision": "f868ca3f48831f7e461256da3d0e762aca064701", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "a5e651abcd7784e033ec68d18d73712451b82d2a" + "reviewed_tree_sha": "fdc88c2164213bccd176d9883a8165ec51652ea2" }, { "repository": "hoxline", From 071ec49ddef3643fed12b7047eba5635ee783a11 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 15:27:55 -0500 Subject: [PATCH 059/116] chore(command-center): seal consumer-path provenance pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 5fdd07a..e91ffc1 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "f868ca3f48831f7e461256da3d0e762aca064701", + "revision": "5e887c88ddc4ae5325fdcc927fb7552e699aed02", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "fdc88c2164213bccd176d9883a8165ec51652ea2" + "reviewed_tree_sha": "f7182dafe0c2e9cc9e6903844dc78df659696505" }, { "repository": "hoxline", From aa09bc2f2cee337cf946102a3ca72f40763d15f4 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 16:01:39 -0500 Subject: [PATCH 060/116] chore(command-center): seal final source observations --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index e91ffc1..7c877b4 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "7c842a1ad7f30f3c516082b31ed9fc892ca70a58", + "revision": "ad8c4507304bd0796bab3ff95daadab3b1ad50b5", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "1f02e5e5763963727afd7386394b6db422c15474" + "reviewed_tree_sha": "26fe2545cc49767f613606f984ebfc800e470096" } ], "constraints": { From eeab391a520ec2c31574b8219820259aa027d481 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 16:43:16 -0500 Subject: [PATCH 061/116] ci(command-center): bound immutable checkout retries --- .github/workflows/command-center-invariants.yml | 14 +++++++++++++- scripts/verify-command-center-invariants.py | 2 +- tests/test_command_center_workflow_safety.py | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 848c372..9a0610d 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -112,7 +112,19 @@ jobs: mkdir "source-set/$repo" git -C "source-set/$repo" init --quiet git -C "source-set/$repo" remote add origin "https://github.com/HawkinsOperations/$repo.git" - git -C "source-set/$repo" fetch --quiet origin "$revision" + fetch_complete=0 + for attempt in 1 2 3 4 5 6; do + if + git -C "source-set/$repo" fetch --quiet origin "$revision" + then + fetch_complete=1 + break + fi + if [ "$attempt" -lt 6 ]; then + sleep 5 + fi + done + test "$fetch_complete" -eq 1 git -C "source-set/$repo" checkout --quiet --detach "$revision" test "$(git -C "source-set/$repo" rev-parse HEAD)" = "$revision" done < verification-work/sibling-revisions.tsv diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 3eb9835..ef5e76f 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -87,7 +87,7 @@ "Verify patch whitespace": "466c2f308b48c7661d646fdd068fbecea974c665fe65dbf8ed508f224180ce0b", "Install bounded verifier dependencies": "4e24c9f627196734440d7af0f88696d5c78bcabf31951f052d6f5b8c0d5913b2", "Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json": "2cc7ec88e5f15e3ce2005c2a7d69d9612b88cd4832d3b6f7ebfc900d326530e8", - "Checkout six immutable sibling revisions without credentials": "49ab88b506c80d864d1616ad4ac3c7448ce7187a92ba2bb36404cf6724ada38a", + "Checkout six immutable sibling revisions without credentials": "457e61f1280506ee49cce8d2c796031a25b7874bb3cffeb76441f788cfdd1942", "Verify the exact clean detached source set": "3dbfdd7ea15772914b827f395b09fe23aa61c0d31e91703b05cc3ef8c4476e57", "Detect durable sibling main-content drift": "fa27754b70cd171cac072a868b3632405e5b2c5b8744e34139cf8e64dbcd7a53", "Verify detection authority and hostile paths": "a55bb68d511268423e7ed392184dab55f3864c8411d74ff725c54f776daa4d4d", diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index eec239f..56e82c2 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -236,6 +236,21 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N with self.subTest(label=label): self.assert_rejected(value, label) + def test_sibling_fetch_retry_is_bounded_and_fails_closed(self) -> None: + for fragment in ( + "for attempt in 1 2 3 4 5 6; do", + "fetch_complete=1", + 'if [ "$attempt" -lt 6 ]; then', + "sleep 5", + 'test "$fetch_complete" -eq 1', + ): + self.assertIn(fragment, self.workflow) + + self.assert_rejected( + self.workflow.replace('test "$fetch_complete" -eq 1', "true", 1), + "unconditional success", + ) + def test_exact_run_allowlist_rejects_command_laundering(self) -> None: command = ( "python -B source-set/hawkinsoperations-detections/scripts/" From 5cf31d71951e9652c1a27f19bdc5b9aed2918994 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 16:51:10 -0500 Subject: [PATCH 062/116] chore(command-center): record CI repair heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7c877b4..174e5c1 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -19,16 +19,16 @@ { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "2e833f340e183e8e2357c860314509c6d1cc2dd3", + "revision": "46a7ed39e3c0ea74ad102a1547a8bca2d00f3b4a", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "a6852d017cd51510ff32ce319114a4b1cd5b1a0c" + "reviewed_tree_sha": "6078cf7cfc98368c597363bbf28fc72b77f10e01" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "7357a0cc8f87bb4b455969279122d9a195da49c8", + "revision": "c624877d5e61d02ca4593f50b92655e318d25830", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "e6d6cfe785a8577c36ae1ff449ddff169de97234" + "reviewed_tree_sha": "62e81e4b1efd4dfb65e5722a0ad48ab7155336f6" }, { "repository": "hawkinsoperations-proof", @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "5e887c88ddc4ae5325fdcc927fb7552e699aed02", + "revision": "f793698a047c79ccc7d72ab2a0575e5f691630b9", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "f7182dafe0c2e9cc9e6903844dc78df659696505" + "reviewed_tree_sha": "02faed6dd8651d515c2a4c942eca4aa217a00003" }, { "repository": "hoxline", From 5dd76305b291ecaa0e17273d48e58a32b97d2990 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 16:53:26 -0500 Subject: [PATCH 063/116] chore(command-center): seal repaired website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 174e5c1..fd4d72c 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "f793698a047c79ccc7d72ab2a0575e5f691630b9", + "revision": "c23b03a7603e0ffab2a07ca7a9cdf7b45e62ca27", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "02faed6dd8651d515c2a4c942eca4aa217a00003" + "reviewed_tree_sha": "34a661df37d6b54ac1a815c328ec3661bdea8345" }, { "repository": "hoxline", From 6334b59be083d73d2c4f2cc38df038954530cf89 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 16:55:56 -0500 Subject: [PATCH 064/116] chore(command-center): seal final CI repair observations --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index fd4d72c..fc6462a 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "ad8c4507304bd0796bab3ff95daadab3b1ad50b5", + "revision": "29772b10a68721068d541213559a9a8e2af22639", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "26fe2545cc49767f613606f984ebfc800e470096" + "reviewed_tree_sha": "d8e6c89b9667ea5db791fef91a901171a9a529ab" } ], "constraints": { From 657b041e55cb1c8e31e1ba4ebf0c620ab8a00cc7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 16:58:59 -0500 Subject: [PATCH 065/116] fix(command-center): record exact repaired revisions --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index fc6462a..ece0096 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,14 +40,14 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "c23b03a7603e0ffab2a07ca7a9cdf7b45e62ca27", + "revision": "c23b03a3f3f5373c1d2d918f43ca65eb8ac74e6c", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", "reviewed_tree_sha": "34a661df37d6b54ac1a815c328ec3661bdea8345" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "29772b10a68721068d541213559a9a8e2af22639", + "revision": "29772b1da7acf684ac476ea6e671de48e9b0e04f", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", "reviewed_tree_sha": "d8e6c89b9667ea5db791fef91a901171a9a529ab" } From d5c8edc779e58474126e67c26265b1f4cf2aa80a Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 17:06:43 -0500 Subject: [PATCH 066/116] chore(command-center): seal exact Hoxline CI source set --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index ece0096..70d61c8 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "29772b1da7acf684ac476ea6e671de48e9b0e04f", + "revision": "fc1f65828c7c67d47cdc066d970822524759cbf0", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "d8e6c89b9667ea5db791fef91a901171a9a529ab" + "reviewed_tree_sha": "9687ad192b02555e523f5fea3bddb2f4cc2ffbfd" } ], "constraints": { From fbec4fdee5f36e7f5c9d377f0868e0b79cde8469 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 17:10:21 -0500 Subject: [PATCH 067/116] chore(command-center): seal exact website source pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 70d61c8..e9b23ce 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "c23b03a3f3f5373c1d2d918f43ca65eb8ac74e6c", + "revision": "66ec4034005a76fc64f6ad8e6e0a4001cba68fbc", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "34a661df37d6b54ac1a815c328ec3661bdea8345" + "reviewed_tree_sha": "2aa66597691475d673583741365b10d01b70c233" }, { "repository": "hoxline", From 44b179b867ea57ae09e97fd7d724f7d31929be30 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 17:12:30 -0500 Subject: [PATCH 068/116] chore(command-center): seal final review source heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index e9b23ce..2294ac6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "fc1f65828c7c67d47cdc066d970822524759cbf0", + "revision": "5204ef31849d83ad790a142b68ea84e1451087d1", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "9687ad192b02555e523f5fea3bddb2f4cc2ffbfd" + "reviewed_tree_sha": "64dc64b07441f7ce4369bf0f89f2db41cbfd4e98" } ], "constraints": { From 207e18601c10584a55b7662f107654c60cfd2925 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 17:34:39 -0500 Subject: [PATCH 069/116] chore(command-center): seal hardened platform source set --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 2294ac6..12bc6b2 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "c624877d5e61d02ca4593f50b92655e318d25830", + "revision": "56fed73fe1135916f4bacd4cdbae0ff7e968f7a2", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "62e81e4b1efd4dfb65e5722a0ad48ab7155336f6" + "reviewed_tree_sha": "5115c2ec2b72fd9ba7a265a4b0e1b15cd89d3ec8" }, { "repository": "hawkinsoperations-proof", From 41dc7fec4a38ed550c2136bf0e13cec9458e4a42 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 18:04:58 -0500 Subject: [PATCH 070/116] chore(command-center): seal adversarial repair heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 12bc6b2..be5cb73 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,23 +12,23 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "11a481afbc739c994ce19cdb12052a307a6eec77", + "revision": "015a9dc359b3fa4c4853cd1b18372c3e44eacec9", "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "48e43af2aebb0d0d4ef6b321cbd116b8f7f0df04" + "reviewed_tree_sha": "e662abc50961367e39284cdcca325f133eedff91" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "46a7ed39e3c0ea74ad102a1547a8bca2d00f3b4a", + "revision": "03d8b909b2304a9a570129a559f9cd44e98dc2b1", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "6078cf7cfc98368c597363bbf28fc72b77f10e01" + "reviewed_tree_sha": "32a2ab07c979e7974baef906926e2c87215f46ce" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "56fed73fe1135916f4bacd4cdbae0ff7e968f7a2", + "revision": "26ae0fd0112d2123f90197b9aa5078db0d35db65", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "5115c2ec2b72fd9ba7a265a4b0e1b15cd89d3ec8" + "reviewed_tree_sha": "95bed82102d5baa1e6768daf7accea5fa5390dc7" }, { "repository": "hawkinsoperations-proof", @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "5204ef31849d83ad790a142b68ea84e1451087d1", + "revision": "b0899fe48f0c50989e60dbbfb69c6822e7e88d85", "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "64dc64b07441f7ce4369bf0f89f2db41cbfd4e98" + "reviewed_tree_sha": "a4980bdc9b763dcf843d75cf2ba31ad5fd2ad3fc" } ], "constraints": { From b56c7d694b9fc84e53635636976db4b2e929e796 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 18:29:31 -0500 Subject: [PATCH 071/116] chore(command-center): seal detached-source repairs --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index be5cb73..285bae1 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "66ec4034005a76fc64f6ad8e6e0a4001cba68fbc", + "revision": "722f9393f766267e81309210208673ead248251c", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "2aa66597691475d673583741365b10d01b70c233" + "reviewed_tree_sha": "01bfe3dfc773afb4411f9dbd086bcc5a70ba0681" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "b0899fe48f0c50989e60dbbfb69c6822e7e88d85", - "authority_content_revision": "d2ce9d977e832e327b4bdbfef55f04a4fd7c35e7", - "reviewed_tree_sha": "a4980bdc9b763dcf843d75cf2ba31ad5fd2ad3fc" + "revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", + "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", + "reviewed_tree_sha": "8896f118af0a0ed32f5185d7e3b0bdcfd6c4fcf0" } ], "constraints": { From 51e4b0959f3eb8774f7e048e89f4ac5c7659772d Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 18:33:34 -0500 Subject: [PATCH 072/116] chore(command-center): seal atomic detached-source pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 285bae1..d91640f 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", + "revision": "58a891578ee296d0cbd332797aad8a8928e69a5c", "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "8896f118af0a0ed32f5185d7e3b0bdcfd6c4fcf0" + "reviewed_tree_sha": "a167e51bb2b5b3fc18808a33ad5fa2c324b99444" } ], "constraints": { From b87acd4487ff779bc0cb8b96c783ada0d712a0ed Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 18:47:13 -0500 Subject: [PATCH 073/116] chore(ci): seal final website source identity --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index d91640f..6722893 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "722f9393f766267e81309210208673ead248251c", + "revision": "5ee3fe553e78ca35b3a2422b2231c627c1ee1f99", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "01bfe3dfc773afb4411f9dbd086bcc5a70ba0681" + "reviewed_tree_sha": "0374df88ae26e8cbb71ff6013c6f079fde239660" }, { "repository": "hoxline", From 4d2bdfb5504a6cfe58acdd7c02f23a105b39fafe Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 19:17:04 -0500 Subject: [PATCH 074/116] chore(ci): reseal website workflow identity --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 6722893..611fca5 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "5ee3fe553e78ca35b3a2422b2231c627c1ee1f99", + "revision": "9ac2c1442d3be6f8f70877d228a91523e11fdc12", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "0374df88ae26e8cbb71ff6013c6f079fde239660" + "reviewed_tree_sha": "d8211d5b794811214adb9315c465434473be2cb0" }, { "repository": "hoxline", From 5c9e17cb590d46263d3266138ac654426018a7f7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 19:29:09 -0500 Subject: [PATCH 075/116] chore(ci): seal executable checkout and hoxline heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 611fca5..5882919 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "9ac2c1442d3be6f8f70877d228a91523e11fdc12", + "revision": "e85aa60295f36ff01a89f0e76089fc8d7295f41c", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "d8211d5b794811214adb9315c465434473be2cb0" + "reviewed_tree_sha": "fcfd53e501b6969e376e0017350a602cc5dcdbda" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "58a891578ee296d0cbd332797aad8a8928e69a5c", + "revision": "193f929633635f351b2ef0e2ca5d8c0166e595ff", "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "a167e51bb2b5b3fc18808a33ad5fa2c324b99444" + "reviewed_tree_sha": "077189c4d7d3b78a29da57c6a59c094a00f10550" } ], "constraints": { From 816a694de3e3e23961c227d8d59591898a215973 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 19:38:21 -0500 Subject: [PATCH 076/116] chore(ci): seal final reviewed identity matrix --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 5882919..905f945 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "26ae0fd0112d2123f90197b9aa5078db0d35db65", + "revision": "c24c6df923b2354d95efc486b5e8a2d7f4991161", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "95bed82102d5baa1e6768daf7accea5fa5390dc7" + "reviewed_tree_sha": "ab12ba99f4163b6c260f0b56a7648747ca13d363" }, { "repository": "hawkinsoperations-proof", @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "e85aa60295f36ff01a89f0e76089fc8d7295f41c", + "revision": "ecc73ff1c762c1aa6d8ebfca8b2fcb2124935e48", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "fcfd53e501b6969e376e0017350a602cc5dcdbda" + "reviewed_tree_sha": "1926f18b12ea03c3a48bfa4dcb1ee64351499232" }, { "repository": "hoxline", From d10bcaf3c175bf15f7f7d4ca9c775270a000d50e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 19:45:03 -0500 Subject: [PATCH 077/116] chore(ci): seal final platform selection head --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 905f945..dfb7a7f 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "c24c6df923b2354d95efc486b5e8a2d7f4991161", + "revision": "487d17048091e7f3f8625c14008c382e9cdf1843", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "ab12ba99f4163b6c260f0b56a7648747ca13d363" + "reviewed_tree_sha": "e5fc44075cd344ac1087a08ad8fb7034daab21d3" }, { "repository": "hawkinsoperations-proof", From d38a9d1dfa3efc3a55d6dc935c7b7a2a22721651 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 19:49:17 -0500 Subject: [PATCH 078/116] chore(ci): seal pinned platform manifest repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index dfb7a7f..257dcd3 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "487d17048091e7f3f8625c14008c382e9cdf1843", + "revision": "0ef69cb2dec93e9786bf611e06201f6e8eb7c854", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "e5fc44075cd344ac1087a08ad8fb7034daab21d3" + "reviewed_tree_sha": "fbac98915f772f942602919f35ef269ce349a6e3" }, { "repository": "hawkinsoperations-proof", From b86cc465faa375a8bc4bd78dbb9954a9620f922f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 20:02:45 -0500 Subject: [PATCH 079/116] chore(governance): seal content-resilient platform review --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 257dcd3..854e2c9 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "0ef69cb2dec93e9786bf611e06201f6e8eb7c854", + "revision": "13c31e4eb60885420564e411965bfdb17b46f491", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "fbac98915f772f942602919f35ef269ce349a6e3" + "reviewed_tree_sha": "79892e1b502a86222af91fa73deb1ef0a10ec722" }, { "repository": "hawkinsoperations-proof", From fc6c4b6ad9357293b67387fefea36ed250692ebe Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 20:11:17 -0500 Subject: [PATCH 080/116] chore(governance): seal refreshed case-growth pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 854e2c9..58e289c 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "193f929633635f351b2ef0e2ca5d8c0166e595ff", + "revision": "6616877345c169ed3201ffeb951d2f710b04bba8", "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "077189c4d7d3b78a29da57c6a59c094a00f10550" + "reviewed_tree_sha": "405bffd6571fe3bd1c51fc61058744c41d2c3798" } ], "constraints": { From 4e6995774daba161c032e573634607afe807c8ef Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 20:16:53 -0500 Subject: [PATCH 081/116] chore(governance): seal content-resilient platform tests --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 58e289c..b4393fb 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "13c31e4eb60885420564e411965bfdb17b46f491", + "revision": "f2f1517c40669c621830ab3dcd00dd4d60b60cbc", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "79892e1b502a86222af91fa73deb1ef0a10ec722" + "reviewed_tree_sha": "a52cae5457c2eb50dd0e31f81a8ebfdd5d7a85d5" }, { "repository": "hawkinsoperations-proof", From a9d1e8b4f2b4ccc7da5a01b3bc407310bf3cf21e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 20:19:29 -0500 Subject: [PATCH 082/116] chore(governance): seal settled case-growth observations --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index b4393fb..999c7ee 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "6616877345c169ed3201ffeb951d2f710b04bba8", + "revision": "9a8ff9bfbf523ea61e7ce2c2142ec40c5a192c09", "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "405bffd6571fe3bd1c51fc61058744c41d2c3798" + "reviewed_tree_sha": "c3d37f7f14f869c7a0d6e4901b76a18b3e66c9d7" } ], "constraints": { From c3bc35693f88f4cb907c2c6c53281631dcbdb6b8 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 20:25:09 -0500 Subject: [PATCH 083/116] chore(governance): seal merge-resilient platform review --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 999c7ee..6d5196b 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "f2f1517c40669c621830ab3dcd00dd4d60b60cbc", + "revision": "eb43cd3ce4ad6668dbc9a175bf3de714fcb40c63", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "a52cae5457c2eb50dd0e31f81a8ebfdd5d7a85d5" + "reviewed_tree_sha": "8d2901a6765ed5801fe7c7c42734c471dd923833" }, { "repository": "hawkinsoperations-proof", From c99c062aa85ef617716cf047a460deb52793602d Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 20:39:31 -0500 Subject: [PATCH 084/116] chore(governance): seal final merge-resilient observations --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 6d5196b..b560707 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "9a8ff9bfbf523ea61e7ce2c2142ec40c5a192c09", + "revision": "cad8114853ce3e6570149b6762fba4e8f5c396ae", "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "c3d37f7f14f869c7a0d6e4901b76a18b3e66c9d7" + "reviewed_tree_sha": "05dcb1c39abd18e26a65b051a506bf8d3b13e82c" } ], "constraints": { From 24244e77258cbb4d5f277ebb39637dc35e7bc02b Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 21:30:14 -0500 Subject: [PATCH 085/116] fix(governance): bind authority origins to stored config --- scripts/verify-command-center-invariants.py | 25 ++++++++- tests/test_command_center_workflow_safety.py | 59 ++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index ef5e76f..6212c6a 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -1041,6 +1041,29 @@ def canonical_origin(value: str) -> str: return normalized +def stored_origin(repo: Path) -> str: + result = subprocess.run( + [ + "git", + "-C", + str(repo), + "config", + "--local", + "--get-all", + "remote.origin.url", + ], + check=False, + capture_output=True, + text=True, + ) + values = [value.strip() for value in result.stdout.splitlines()] + if result.returncode != 0 or len(values) != 1 or not values[0]: + raise ValidationError( + f"{repo.name}: stored origin must contain exactly one nonempty local URL" + ) + return values[0] + + def git(repo: Path, *args: str) -> str: result = subprocess.run( ["git", "-C", str(repo), *args], @@ -1196,7 +1219,7 @@ def verify_source_set( branch = git(repo_path, "rev-parse", "--abbrev-ref", "HEAD") if branch != "HEAD": raise ValidationError(f"{repository}: checkout must be detached at exact revision") - origin = git(repo_path, "remote", "get-url", "origin") + origin = stored_origin(repo_path) if canonical_origin(origin) != canonical_origin(CANONICAL_ORIGINS[repository]): raise ValidationError(f"{repository}: canonical origin mismatch") status = git(repo_path, "status", "--porcelain=v1", "--untracked-files=all") diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 56e82c2..70d2953 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -2,6 +2,7 @@ import importlib.util import json +import os import subprocess import tempfile import unittest @@ -553,6 +554,64 @@ def test_dirty_wrong_origin_branch_and_missing_repo_fail(self) -> None: _, errors = VERIFIER.verify_source_set(root, resolved) self.assertTrue(errors) + def test_origin_rewrite_cannot_launder_wrong_stored_origin(self) -> None: + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + repository = "hawkinsoperations-detections" + target = root / repository + canonical = VERIFIER.CANONICAL_ORIGINS[repository] + wrong = "https://local.invalid/hawkinsoperations-detections.git" + self.run_git(target, "remote", "set-url", "origin", wrong) + rewrite_env = { + "GIT_CONFIG_COUNT": "1", + "GIT_CONFIG_KEY_0": f"url.{canonical}.insteadOf", + "GIT_CONFIG_VALUE_0": wrong, + } + with mock.patch.dict(os.environ, rewrite_env, clear=False): + self.assertEqual( + canonical, + self.run_git(target, "remote", "get-url", "origin"), + "attack precondition: interpreted Git URL must look canonical", + ) + _, errors = VERIFIER.verify_source_set(root, resolved) + self.assertTrue( + any("canonical origin mismatch" in error for error in errors), + errors, + ) + + def test_missing_empty_or_multiple_stored_origins_fail_closed(self) -> None: + for attack in ("missing", "empty", "multiple"): + with self.subTest(attack=attack), tempfile.TemporaryDirectory() as temp: + root = Path(temp) / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + target = root / "hawkinsoperations-detections" + self.run_git(target, "config", "--unset-all", "remote.origin.url") + if attack == "empty": + self.run_git(target, "config", "--add", "remote.origin.url", "") + elif attack == "multiple": + self.run_git( + target, + "config", + "--add", + "remote.origin.url", + VERIFIER.CANONICAL_ORIGINS["hawkinsoperations-detections"], + ) + self.run_git( + target, + "config", + "--add", + "remote.origin.url", + "https://local.invalid/hawkinsoperations-detections.git", + ) + _, errors = VERIFIER.verify_source_set(root, resolved) + self.assertTrue( + any("exactly one nonempty local URL" in error for error in errors), + errors, + ) + def test_authority_content_revision_is_bound_to_canonical_current_blob(self) -> None: for attack in ("unreachable", "wrong-blob"): with self.subTest(attack=attack), tempfile.TemporaryDirectory() as temp: From 404b667f364db666cdadf40edd5a32829e3d1499 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 21:52:23 -0500 Subject: [PATCH 086/116] chore(convergence): refresh repaired source revisions --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index b560707..8fad1e3 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,23 +12,23 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "015a9dc359b3fa4c4853cd1b18372c3e44eacec9", + "revision": "e0360e6a5011e28417855677fbd4b331ae156966", "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "e662abc50961367e39284cdcca325f133eedff91" + "reviewed_tree_sha": "a1d09e4f8fa7f07e3020bf1f113750b8760d6370" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "03d8b909b2304a9a570129a559f9cd44e98dc2b1", + "revision": "073e8c0899d306b6d845d48bc47cbd7f5f78c3c7", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "32a2ab07c979e7974baef906926e2c87215f46ce" + "reviewed_tree_sha": "ad5d178f25e0aea30480bb715f87e7b15a6ffd4f" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "eb43cd3ce4ad6668dbc9a175bf3de714fcb40c63", + "revision": "77b2bbde6c0678e69c16ee91d5b2614cd5fd167b", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "8d2901a6765ed5801fe7c7c42734c471dd923833" + "reviewed_tree_sha": "611f2cb27e74f518f0516a19e79cd9d7d0aab3d6" }, { "repository": "hawkinsoperations-proof", @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "ecc73ff1c762c1aa6d8ebfca8b2fcb2124935e48", + "revision": "71dcdabb0cab9bc8a08ec838a91482c5b50aaea7", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "1926f18b12ea03c3a48bfa4dcb1ee64351499232" + "reviewed_tree_sha": "adba4a09fb1577468055581e6981174c4e4a883e" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "cad8114853ce3e6570149b6762fba4e8f5c396ae", + "revision": "dbfd4a195ce00cb4e4b96494f114f7f487bb029a", "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "05dcb1c39abd18e26a65b051a506bf8d3b13e82c" + "reviewed_tree_sha": "068fdd4b63938967a75675e85f55a83213f749bb" } ], "constraints": { From 0c3d2734e9fd320420315a54f66af398889923f8 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 22:07:41 -0500 Subject: [PATCH 087/116] fix(governance): isolate command-center git authority --- scripts/verify-command-center-invariants.py | 16 +++ tests/test_command_center_workflow_safety.py | 130 +++++++++++++++++++ 2 files changed, 146 insertions(+) diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 6212c6a..2578072 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -6,6 +6,7 @@ import argparse import hashlib import json +import os import re import subprocess import sys @@ -38,6 +39,15 @@ repository: f"https://github.com/HawkinsOperations/{repository}.git" for repository in EXACT_REPOSITORIES } +def sanitized_git_environment() -> dict[str, str]: + environment = { + key: value + for key, value in os.environ.items() + if not key.casefold().startswith("git_") + } + environment["GIT_NO_REPLACE_OBJECTS"] = "1" + environment["GIT_TERMINAL_PROMPT"] = "0" + return environment CANONICAL_AUTHORITY_PATHS = { ".github": "governance/COMMAND_CENTER_INVARIANTS.json", "hawkinsoperations-detections": "detections/DETECTION_PROMOTION_MATRIX.yml", @@ -323,6 +333,7 @@ def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: ["git", "-C", str(repo_root), "ls-files", "-z"], capture_output=True, check=False, + env=sanitized_git_environment(), ) if listed.returncode != 0: return ["tracked-source vocabulary check could not enumerate Git-tracked files"] @@ -341,6 +352,7 @@ def tracked_vocabulary_findings(repo_root: Path = ROOT) -> list[str]: ["git", "-C", str(repo_root), "show", f":{relative}"], capture_output=True, check=False, + env=sanitized_git_environment(), ) if scanned.returncode != 0: findings.append( @@ -1055,6 +1067,7 @@ def stored_origin(repo: Path) -> str: check=False, capture_output=True, text=True, + env=sanitized_git_environment(), ) values = [value.strip() for value in result.stdout.splitlines()] if result.returncode != 0 or len(values) != 1 or not values[0]: @@ -1070,6 +1083,7 @@ def git(repo: Path, *args: str) -> str: check=False, capture_output=True, text=True, + env=sanitized_git_environment(), ) if result.returncode: raise ValidationError( @@ -1308,6 +1322,7 @@ def verify_remote_main_content( check=False, capture_output=True, text=True, + env=sanitized_git_environment(), ) fields = result.stdout.strip().split() if result.returncode != 0 or len(fields) != 2 or fields[1] != "refs/heads/main": @@ -1323,6 +1338,7 @@ def verify_remote_main_content( check=False, capture_output=True, text=True, + env=sanitized_git_environment(), ) if fetch.returncode: errors.append(f"{repository}: current main content cannot be fetched") diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index 70d2953..fdef83e 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -581,6 +581,136 @@ def test_origin_rewrite_cannot_launder_wrong_stored_origin(self) -> None: errors, ) + def test_git_environment_scrub_rejects_every_ambient_git_control(self) -> None: + hostile = { + "GIT_DIR": "decoy", + "GIT_WORK_TREE": "decoy", + "GIT_COMMON_DIR": "decoy", + "GIT_INDEX_FILE": "decoy", + "GIT_OBJECT_DIRECTORY": "decoy", + "GIT_ALTERNATE_OBJECT_DIRECTORIES": "decoy", + "GIT_CONFIG": "decoy", + "GIT_CONFIG_GLOBAL": "decoy", + "GIT_CONFIG_SYSTEM": "decoy", + "GIT_CONFIG_NOSYSTEM": "0", + "GIT_CONFIG_COUNT": "1", + "GIT_CONFIG_KEY_0": "core.repositoryformatversion", + "GIT_CONFIG_VALUE_0": "1", + "GIT_CEILING_DIRECTORIES": "decoy", + "GIT_DISCOVERY_ACROSS_FILESYSTEM": "1", + "GIT_SHALLOW_FILE": "decoy", + "GIT_NAMESPACE": "decoy", + "GIT_REPLACE_REF_BASE": "refs/decoy", + "GIT_IMPLICIT_WORK_TREE": "1", + "GIT_NO_REPLACE_OBJECTS": "0", + "GIT_TERMINAL_PROMPT": "1", + } + with mock.patch.dict(os.environ, hostile, clear=False): + sanitized = VERIFIER.sanitized_git_environment() + self.assertEqual("1", sanitized["GIT_NO_REPLACE_OBJECTS"]) + self.assertEqual("0", sanitized["GIT_TERMINAL_PROMPT"]) + self.assertEqual( + {"git_no_replace_objects", "git_terminal_prompt"}, + { + key.casefold() + for key in sanitized + if key.casefold().startswith("git_") + }, + ) + + def test_git_dir_decoy_cannot_redirect_stored_origin_authority(self) -> None: + with tempfile.TemporaryDirectory() as temp: + base = Path(temp) + root = base / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + repository = "hawkinsoperations-detections" + target = root / repository + canonical = VERIFIER.CANONICAL_ORIGINS[repository] + wrong = "https://local.invalid/hawkinsoperations-detections.git" + self.run_git(target, "remote", "set-url", "origin", wrong) + decoy = base / "decoy" + decoy.mkdir() + self.run_git(decoy, "init", "--quiet") + self.run_git(decoy, "remote", "add", "origin", canonical) + raw_env = os.environ.copy() + raw_env["GIT_DIR"] = str(decoy / ".git") + interpreted = subprocess.run( + [ + "git", + "-C", + str(target), + "config", + "--local", + "--get-all", + "remote.origin.url", + ], + check=True, + capture_output=True, + text=True, + env=raw_env, + ).stdout.strip() + self.assertEqual(canonical, interpreted) + with mock.patch.dict( + os.environ, {"GIT_DIR": str(decoy / ".git")}, clear=False + ): + self.assertEqual(wrong, VERIFIER.stored_origin(target)) + _, errors = VERIFIER.verify_source_set(root, resolved) + self.assertTrue( + any("canonical origin mismatch" in error for error in errors), + errors, + ) + + def test_git_index_file_cannot_hide_staged_dirty_authority(self) -> None: + with tempfile.TemporaryDirectory() as temp: + base = Path(temp) + root = base / "source-set" + root.mkdir() + resolved = self.create_source_set(root) + repository = "hawkinsoperations-detections" + target = root / repository + clean_index = base / "clean.index" + alternate_env = os.environ.copy() + alternate_env["GIT_INDEX_FILE"] = str(clean_index) + subprocess.run( + ["git", "-C", str(target), "read-tree", "HEAD"], + check=True, + capture_output=True, + env=alternate_env, + ) + authority_file = target / VERIFIER.CANONICAL_AUTHORITY_PATHS[repository] + original = authority_file.read_text(encoding="utf-8") + authority_file.write_text("staged contradiction\n", encoding="utf-8") + self.run_git( + target, + "add", + VERIFIER.CANONICAL_AUTHORITY_PATHS[repository], + ) + authority_file.write_text(original, encoding="utf-8") + hidden = subprocess.run( + [ + "git", + "-C", + str(target), + "status", + "--porcelain=v1", + "--untracked-files=all", + ], + check=True, + capture_output=True, + text=True, + env=alternate_env, + ).stdout.strip() + self.assertEqual("", hidden, "attack precondition: alternate index is clean") + with mock.patch.dict( + os.environ, {"GIT_INDEX_FILE": str(clean_index)}, clear=False + ): + _, errors = VERIFIER.verify_source_set(root, resolved) + self.assertTrue( + any("source checkout is dirty" in error for error in errors), + errors, + ) + def test_missing_empty_or_multiple_stored_origins_fail_closed(self) -> None: for attack in ("missing", "empty", "multiple"): with self.subTest(attack=attack), tempfile.TemporaryDirectory() as temp: From b93fb586fccf80dd40c714281086fe2a940506a7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 22:17:07 -0500 Subject: [PATCH 088/116] chore(convergence): select hardened authority content --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8fad1e3..8fe3309 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,23 +12,23 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "e0360e6a5011e28417855677fbd4b331ae156966", + "revision": "48de1240a8437432f35aee77654b568704627a68", "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "a1d09e4f8fa7f07e3020bf1f113750b8760d6370" + "reviewed_tree_sha": "9662d0033aae5f2fc1fe46c00e20bc3540576b7e" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "073e8c0899d306b6d845d48bc47cbd7f5f78c3c7", + "revision": "5840c517bbacf845acdbbcca10c5c09953dbb595", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "ad5d178f25e0aea30480bb715f87e7b15a6ffd4f" + "reviewed_tree_sha": "768fd46b60a645120819ad521a617d2a75bfe253" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "77b2bbde6c0678e69c16ee91d5b2614cd5fd167b", + "revision": "bc489b6c1549288909a6d19cd96f3fa731059ce9", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "611f2cb27e74f518f0516a19e79cd9d7d0aab3d6" + "reviewed_tree_sha": "069d0e4a33fde7037a7d68d22cec6f3f719b4878" }, { "repository": "hawkinsoperations-proof", @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "71dcdabb0cab9bc8a08ec838a91482c5b50aaea7", + "revision": "0c16f2a97ae73910633daf6193a51918f26d1798", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "adba4a09fb1577468055581e6981174c4e4a883e" + "reviewed_tree_sha": "ab28bbaf73fb1a9de02615b875439de948e6e339" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "dbfd4a195ce00cb4e4b96494f114f7f487bb029a", - "authority_content_revision": "b0945c4c3db7312f7d50a51d4abab9e65ac454da", - "reviewed_tree_sha": "068fdd4b63938967a75675e85f55a83213f749bb" + "revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", + "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", + "reviewed_tree_sha": "17fe346423d6ad57fade3efc737052ca354d49f5" } ], "constraints": { From cf2769104bfe585b9115eb16bef799f2ee31ff21 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 22:29:14 -0500 Subject: [PATCH 089/116] chore(convergence): seal final reviewed trees --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8fe3309..56f15ef 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "bc489b6c1549288909a6d19cd96f3fa731059ce9", + "revision": "c73ee7cfe5223197482afa6dc8668e3924855067", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "069d0e4a33fde7037a7d68d22cec6f3f719b4878" + "reviewed_tree_sha": "fe2a709e93692f5e958d573fd610ec2482ba5924" }, { "repository": "hawkinsoperations-proof", @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "0c16f2a97ae73910633daf6193a51918f26d1798", + "revision": "a4c91273da4770b79b1e71a844b71a9e981bc606", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "ab28bbaf73fb1a9de02615b875439de948e6e339" + "reviewed_tree_sha": "74165f87f62cff23a9099bf212e98e43099f02f0" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", + "revision": "55cf0f5afa38bb40e7480a61725196c5d6603cc2", "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", - "reviewed_tree_sha": "17fe346423d6ad57fade3efc737052ca354d49f5" + "reviewed_tree_sha": "5277c671d1ff8a0ba6d6197353dc9e7bada60621" } ], "constraints": { From 7caeb644393f3e3036ad076ae7789a118372c36c Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 22:44:03 -0500 Subject: [PATCH 090/116] chore(command-center): seal pair-containing review heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 56f15ef..d31f386 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "c73ee7cfe5223197482afa6dc8668e3924855067", + "revision": "eaf9f45c7c4fc3f79cf952eecfb813de7a6cce11", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "fe2a709e93692f5e958d573fd610ec2482ba5924" + "reviewed_tree_sha": "2d2f16fce29b4a3a6f04cb06984ce904b7453ec8" }, { "repository": "hawkinsoperations-proof", @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "a4c91273da4770b79b1e71a844b71a9e981bc606", + "revision": "632ad726cbef9922cf85709183852b3d5625282d", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "74165f87f62cff23a9099bf212e98e43099f02f0" + "reviewed_tree_sha": "7fd12d1d07ec0c63d4b14fc8050a6eab40f42321" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "55cf0f5afa38bb40e7480a61725196c5d6603cc2", + "revision": "63ad111b62cca2d9e779534421e6737e6cc36732", "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", - "reviewed_tree_sha": "5277c671d1ff8a0ba6d6197353dc9e7bada60621" + "reviewed_tree_sha": "ca2e7da9ee110ce7790bf8d555d376be2001acfb" } ], "constraints": { From 6e3db50000b963d67f1426d895a7a3848a1be81f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 23:06:13 -0500 Subject: [PATCH 091/116] chore(command-center): seal rewrite-resilient review heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index d31f386..417a914 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "eaf9f45c7c4fc3f79cf952eecfb813de7a6cce11", + "revision": "6ab0e6029fb76168f05150819a44e537397ca631", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "2d2f16fce29b4a3a6f04cb06984ce904b7453ec8" + "reviewed_tree_sha": "0d82db0494a9d516c03ae40060d7469c0365a10a" }, { "repository": "hawkinsoperations-proof", @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "63ad111b62cca2d9e779534421e6737e6cc36732", + "revision": "0dcade7d11ede78e07f707805ad3034458ff948e", "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", - "reviewed_tree_sha": "ca2e7da9ee110ce7790bf8d555d376be2001acfb" + "reviewed_tree_sha": "b592aef631670291936a4dbd58f11bba3c9c9760" } ], "constraints": { From 77b0a2d2311faa8157cc4b2948b90947d4a46cab Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 23:50:37 -0500 Subject: [PATCH 092/116] chore(command-center): select rewritten website generator --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 417a914..8fa45c2 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "632ad726cbef9922cf85709183852b3d5625282d", + "revision": "762ba706ae0a38ca131c0fbf530fff740f931391", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "7fd12d1d07ec0c63d4b14fc8050a6eab40f42321" + "reviewed_tree_sha": "fcb550592ea4aaaf1438112ea16278a2df87639e" }, { "repository": "hoxline", From c36c75eddc0527a43bbf4ae7cca26eaaabbf9caf Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Thu, 23 Jul 2026 23:53:12 -0500 Subject: [PATCH 093/116] chore(command-center): seal rewrite-resilient website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 8fa45c2..2becfd0 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "762ba706ae0a38ca131c0fbf530fff740f931391", + "revision": "abd933f8f41da41262e5335a6437a24c31f46d92", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "fcb550592ea4aaaf1438112ea16278a2df87639e" + "reviewed_tree_sha": "be077c3f810f4f0006e20f1d6e9506ea1ae7e148" }, { "repository": "hoxline", From a09d08f6285e63415541699665bb0e70dd713c8a Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 00:05:26 -0500 Subject: [PATCH 094/116] chore(command-center): seal repaired website workflow --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 2becfd0..ae1af07 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "abd933f8f41da41262e5335a6437a24c31f46d92", + "revision": "cd7e47865540fa2734fc06cb9fd9686e871550ac", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "be077c3f810f4f0006e20f1d6e9506ea1ae7e148" + "reviewed_tree_sha": "a9b639c33fe74a300596cee72686811cee371161" }, { "repository": "hoxline", From 1725ece2efe6ef58d23720bcd3de7248952d973c Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 08:01:19 -0500 Subject: [PATCH 095/116] fix(ci): serialize convergence behind invariant checks --- .../workflows/command-center-invariants.yml | 3 ++- scripts/verify-command-center-invariants.py | 11 ++++++++-- tests/test_command_center_workflow_safety.py | 20 +++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 9a0610d..55ff609 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -59,6 +59,7 @@ jobs: run: git diff --check seven-repository-convergence: + needs: command-center-invariants runs-on: ubuntu-latest env: PYTHONDONTWRITEBYTECODE: "1" @@ -176,7 +177,7 @@ jobs: run: | set -euo pipefail python -B source-set/hawkinsoperations-validation/scripts/verify_validation_registry.py --detections-root source-set/hawkinsoperations-detections --detections-ref "$(git -C source-set/hawkinsoperations-detections rev-parse HEAD)" --source-manifest source-set/hawkinsoperations-validation/validation/SOURCE_AUTHORITY_MANIFEST.json - python -B source-set/hawkinsoperations-validation/scripts/verify_all_validation_packages.py + python -B source-set/hawkinsoperations-validation/scripts/verify_all_validation_packages.py --source-contract required python -B source-set/hawkinsoperations-validation/scripts/verify_validation_contract.py python -B source-set/hawkinsoperations-validation/scripts/verify_wazuh_logtest_registry.py python -B source-set/hawkinsoperations-validation/scripts/verify_ho_lab_wazuh_001.py diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 2578072..89eeb9f 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -101,7 +101,7 @@ def sanitized_git_environment() -> dict[str, str]: "Verify the exact clean detached source set": "3dbfdd7ea15772914b827f395b09fe23aa61c0d31e91703b05cc3ef8c4476e57", "Detect durable sibling main-content drift": "fa27754b70cd171cac072a868b3632405e5b2c5b8744e34139cf8e64dbcd7a53", "Verify detection authority and hostile paths": "a55bb68d511268423e7ed392184dab55f3864c8411d74ff725c54f776daa4d4d", - "Verify validation authority and fail-closed parity": "fe94626b4d2064476cc9fdca3b85b4dc4604c30cca7660a911bf9bbbb1cbc3bd", + "Verify validation authority and fail-closed parity": "d4b3bf07e7ae50adb8ef1d385be77ad61a11f339f724fc061eeb992a022346c0", "Verify proof authority and reverse inventory": "f07b841030269d74bd563238e59e4ff695e2d140108321f9d33ea364a0d850b8", "Verify platform source contract and seven-source convergence": "698d9e4b0035d4581a87c889bff1c7bb7ef53db957d75688f1364a713be76ee5", "Install Hoxline from the checked immutable source": "f6954cbb94cbc30f5110c536a4c73b71f985953e71e4c08385cf46b7eb8fea0c", @@ -706,7 +706,7 @@ def unsafe_workflow_findings(text: str) -> list[str]: findings.append(f"{job_name} job must be an object") continue expected_job_keys = ( - {"runs-on", "env", "steps"} + {"needs", "runs-on", "env", "steps"} if job_name == "seven-repository-convergence" else {"runs-on", "steps"} ) @@ -714,6 +714,13 @@ def unsafe_workflow_findings(text: str) -> list[str]: findings.append(f"{job_name} job shape is not closed") if job.get("runs-on") != "ubuntu-latest": findings.append(f"{job_name} runner must be ubuntu-latest") + if ( + job_name == "seven-repository-convergence" + and job.get("needs") != "command-center-invariants" + ): + findings.append( + "seven-repository convergence must depend on command-center invariants" + ) if job_name == "seven-repository-convergence" and job.get("env") != { "PYTHONDONTWRITEBYTECODE": "1" }: diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index fdef83e..ea8977d 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -223,8 +223,8 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N 1, ), "conditional job": self.workflow.replace( - " seven-repository-convergence:\n runs-on:", - " seven-repository-convergence:\n if: false\n runs-on:", + " seven-repository-convergence:\n needs: command-center-invariants\n runs-on:", + " seven-repository-convergence:\n needs: command-center-invariants\n if: false\n runs-on:", 1, ), "conditional principal step": self.workflow.replace( @@ -237,6 +237,22 @@ def test_required_commands_cannot_be_echoed_or_conditionally_disabled(self) -> N with self.subTest(label=label): self.assert_rejected(value, label) + def test_convergence_summary_cannot_outlive_owning_invariant_job(self) -> None: + self.assertIn( + " seven-repository-convergence:\n" + " needs: command-center-invariants\n" + " runs-on:", + self.workflow, + ) + self.assert_rejected( + self.workflow.replace( + " needs: command-center-invariants\n", + "", + 1, + ), + "missing owning-job dependency", + ) + def test_sibling_fetch_retry_is_bounded_and_fails_closed(self) -> None: for fragment in ( "for attempt in 1 2 3 4 5 6; do", From bfe47d165edfa11b1508d364304159224efaa28c Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 08:07:18 -0500 Subject: [PATCH 096/116] chore(ci): select repaired convergence heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index ae1af07..09dd6ca 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,37 +12,37 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "48de1240a8437432f35aee77654b568704627a68", + "revision": "455dc07603f1a502481351c7b57df67206085a16", "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "9662d0033aae5f2fc1fe46c00e20bc3540576b7e" + "reviewed_tree_sha": "3b56762368c262a43ab6dd611382ab8502f7d5cd" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "5840c517bbacf845acdbbcca10c5c09953dbb595", + "revision": "e4a9fc1e35ad7dda56a8e7e6976ee31b82afadef", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "768fd46b60a645120819ad521a617d2a75bfe253" + "reviewed_tree_sha": "879a359e12f11fbb9a59a1dc0e6fe2effc6f76d1" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "6ab0e6029fb76168f05150819a44e537397ca631", + "revision": "ff827f459a2525d65a4ae1fb5782340d542b0c37", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "0d82db0494a9d516c03ae40060d7469c0365a10a" + "reviewed_tree_sha": "66a63fa3deb1549e8c8f69b4a4f744cda1703387" }, { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", - "revision": "79d4bff2dccb24c2b29a68f4a3be7a1e916414b4", + "revision": "b42ba945ae1ea540037643bb25f7165ab55dab21", "authority_content_revision": "042a918ad4a8473cd5abcfd575072fc094639682", - "reviewed_tree_sha": "a1d23af53a8515ab38b14f767f8de7f9984ec567" + "reviewed_tree_sha": "8039038d79d8f6f4f58235036d75cd4fcec0abf8" }, { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "cd7e47865540fa2734fc06cb9fd9686e871550ac", + "revision": "6252231b789dc3dd5f12d5ef94312f251b3c43cc", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "a9b639c33fe74a300596cee72686811cee371161" + "reviewed_tree_sha": "5389a807a98b4c1a1cee7ed473b36eb6e4d2c04e" }, { "repository": "hoxline", From b5ee64399ef59a19f9d7918b9ff6021ca5952c9e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 08:15:07 -0500 Subject: [PATCH 097/116] chore(ci): select final repaired heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 09dd6ca..fa8e5c7 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,16 +12,16 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "455dc07603f1a502481351c7b57df67206085a16", + "revision": "e2b7532784e1d18b07f33b8536708c1492524b87", "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "3b56762368c262a43ab6dd611382ab8502f7d5cd" + "reviewed_tree_sha": "23cc8d9f20f7962d70fbfd06d54b5b21515912c4" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "e4a9fc1e35ad7dda56a8e7e6976ee31b82afadef", + "revision": "41448874c4d7f470e7f81ee298b1a580b8ddc6e0", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "879a359e12f11fbb9a59a1dc0e6fe2effc6f76d1" + "reviewed_tree_sha": "b53e474676147d656a3470a66bf796d53e0c6df2" }, { "repository": "hawkinsoperations-platform", @@ -33,16 +33,16 @@ { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", - "revision": "b42ba945ae1ea540037643bb25f7165ab55dab21", + "revision": "67ae70d6c7bb5298c629e10cf33a25399feb972d", "authority_content_revision": "042a918ad4a8473cd5abcfd575072fc094639682", - "reviewed_tree_sha": "8039038d79d8f6f4f58235036d75cd4fcec0abf8" + "reviewed_tree_sha": "a5c423dad556ca61610c91331ddb78bda962fa2f" }, { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "6252231b789dc3dd5f12d5ef94312f251b3c43cc", + "revision": "c506065e3ac47941e894ea5c58de513ea9dd7bdc", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "5389a807a98b4c1a1cee7ed473b36eb6e4d2c04e" + "reviewed_tree_sha": "24b448612e5f92fdc612e41d10585e3ef15fa96f" }, { "repository": "hoxline", From 5acb7fc4ce0c0806ee82cafde03590fd13147099 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 08:29:37 -0500 Subject: [PATCH 098/116] chore(ci): select claim-boundary repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index fa8e5c7..90da501 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -19,9 +19,9 @@ { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "41448874c4d7f470e7f81ee298b1a580b8ddc6e0", + "revision": "e047f99d7c8779cc8368fe82218d202dc40fc416", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "b53e474676147d656a3470a66bf796d53e0c6df2" + "reviewed_tree_sha": "7089ee6ea0519070d63632cc9bee869dca2359cc" }, { "repository": "hawkinsoperations-platform", From fce2b13aee89fc175bc02eacbdc3d67b547929d5 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 08:54:45 -0500 Subject: [PATCH 099/116] fix(ci): trigger command-center checks for every tracked path --- .../workflows/command-center-invariants.yml | 32 +++++---------- scripts/verify-command-center-invariants.py | 30 +++++--------- tests/test_command_center_workflow_safety.py | 40 ++++++++++++++++--- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/.github/workflows/command-center-invariants.yml b/.github/workflows/command-center-invariants.yml index 55ff609..93f6ae6 100644 --- a/.github/workflows/command-center-invariants.yml +++ b/.github/workflows/command-center-invariants.yml @@ -1,30 +1,10 @@ name: command-center-invariants on: - pull_request: - paths: - - "README.md" - - "profile/**" - - "architecture/**" - - "governance/**" - - "wiki/**" - - ".github/pull_request_template.md" - - ".github/workflows/command-center-invariants.yml" - - "scripts/verify-command-center-invariants.py" - - "tests/**" + pull_request: {} push: branches: - main - paths: - - "README.md" - - "profile/**" - - "architecture/**" - - "governance/**" - - "wiki/**" - - ".github/pull_request_template.md" - - ".github/workflows/command-center-invariants.yml" - - "scripts/verify-command-center-invariants.py" - - "tests/**" workflow_dispatch: {} schedule: - cron: "23 7 * * 1" @@ -40,6 +20,7 @@ jobs: uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 with: persist-credentials: false + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 @@ -56,7 +37,14 @@ jobs: run: python -B -m unittest discover -s tests - name: Verify patch whitespace - run: git diff --check + shell: bash + run: | + set -euo pipefail + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + git diff --check "${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}" + else + git show --check --format= HEAD + fi seven-repository-convergence: needs: command-center-invariants diff --git a/scripts/verify-command-center-invariants.py b/scripts/verify-command-center-invariants.py index 89eeb9f..a722bb8 100644 --- a/scripts/verify-command-center-invariants.py +++ b/scripts/verify-command-center-invariants.py @@ -94,7 +94,7 @@ def sanitized_git_environment() -> dict[str, str]: "Install structural verifier dependency": "6777f50efc1a4de7a52454974ba0da5a7adda9e7a84e251b3f3fe93912fdd695", "Verify command-center invariants": "7457407dbbf6fc6c710590149da3c3a7be1358b567f31ffda84cb8fa4fcd2e46", "Run hostile command-center unit tests": "16792c22d70f184d03660b7d7641f13a305e9227f1d31be6950732ca2a80a5d3", - "Verify patch whitespace": "466c2f308b48c7661d646fdd068fbecea974c665fe65dbf8ed508f224180ce0b", + "Verify patch whitespace": "c6cab74e9117e643b9234134c46cfcf6cf1733747c76d31399834e41cee706a4", "Install bounded verifier dependencies": "4e24c9f627196734440d7af0f88696d5c78bcabf31951f052d6f5b8c0d5913b2", "Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json": "2cc7ec88e5f15e3ce2005c2a7d69d9612b88cd4832d3b6f7ebfc900d326530e8", "Checkout six immutable sibling revisions without credentials": "457e61f1280506ee49cce8d2c796031a25b7874bb3cffeb76441f788cfdd1942", @@ -114,7 +114,7 @@ def sanitized_git_environment() -> dict[str, str]: EXPECTED_ACTION_BY_STEP = { "Checkout command-center authority": { "uses": f"actions/checkout@{PINNED_ACTIONS['actions/checkout']}", - "with": {"persist-credentials": "false"}, + "with": {"persist-credentials": "false", "fetch-depth": 0}, }, "Checkout workflow authority at the event revision": { "uses": f"actions/checkout@{PINNED_ACTIONS['actions/checkout']}", @@ -147,6 +147,7 @@ def sanitized_git_environment() -> dict[str, str]: }, } EXPECTED_BASH_STEPS = { + "Verify patch whitespace", "Resolve governance/CONVERGENCE_SOURCE_MANIFEST.json", "Checkout six immutable sibling revisions without credentials", "Verify the exact clean detached source set", @@ -637,28 +638,15 @@ def unsafe_workflow_findings(text: str) -> list[str]: findings.append("manual read-only dispatch is required") pull_request = triggers.get("pull_request") push = triggers.get("push") - required_paths = { - "README.md", - "profile/**", - "architecture/**", - "governance/**", - "wiki/**", - ".github/pull_request_template.md", - ".github/workflows/command-center-invariants.yml", - "scripts/verify-command-center-invariants.py", - "tests/**", - } - if not isinstance(pull_request, dict) or set(pull_request) != {"paths"}: - findings.append("pull_request trigger shape must be unrestricted except approved paths") - elif set(pull_request.get("paths", [])) != required_paths: - findings.append("pull_request paths must cover every governed verifier surface") - if not isinstance(push, dict) or set(push) != {"branches", "paths"}: - findings.append("push trigger shape must be exactly branches and paths") + if pull_request != {}: + findings.append( + "pull_request trigger must be unrestricted so every tracked path is scanned" + ) + if not isinstance(push, dict) or set(push) != {"branches"}: + findings.append("push trigger shape must contain only branches") else: if push.get("branches") != ["main"]: findings.append("push trigger must govern main exactly") - if set(push.get("paths", [])) != required_paths: - findings.append("push paths must cover every governed verifier surface") if workflow.get("permissions") != {"contents": "read"}: findings.append("root permissions must be exactly contents: read") diff --git a/tests/test_command_center_workflow_safety.py b/tests/test_command_center_workflow_safety.py index ea8977d..85a2394 100644 --- a/tests/test_command_center_workflow_safety.py +++ b/tests/test_command_center_workflow_safety.py @@ -253,6 +253,30 @@ def test_convergence_summary_cannot_outlive_owning_invariant_job(self) -> None: "missing owning-job dependency", ) + def test_whitespace_check_covers_committed_event_revision(self) -> None: + for fragment in ( + "fetch-depth: 0", + 'git diff --check "${{ github.event.pull_request.base.sha }}...' + '${{ github.event.pull_request.head.sha }}"', + "git show --check --format= HEAD", + ): + self.assertIn(fragment, self.workflow) + self.assert_rejected( + self.workflow.replace( + " run: |\n" + " set -euo pipefail\n" + ' if [[ "${{ github.event_name }}" == "pull_request" ]]; then\n' + ' git diff --check "${{ github.event.pull_request.base.sha }}...' + '${{ github.event.pull_request.head.sha }}"\n' + " else\n" + " git show --check --format= HEAD\n" + " fi\n", + " run: git diff --check\n", + 1, + ), + "working-tree-only whitespace check", + ) + def test_sibling_fetch_retry_is_bounded_and_fails_closed(self) -> None: for fragment in ( "for attempt in 1 2 3 4 5 6; do", @@ -332,19 +356,23 @@ def test_shell_and_job_default_overrides_fail_closed(self) -> None: with self.subTest(label=label): self.assert_rejected(value, label) - def test_trigger_neutralization_and_test_path_omission_fail(self) -> None: + def test_trigger_neutralization_and_tracked_path_narrowing_fail(self) -> None: mutations = { "closed-only PR": self.workflow.replace( - " pull_request:\n paths:", - " pull_request:\n types: [closed]\n paths:", + " pull_request: {}", + " pull_request:\n types: [closed]", 1, ), "ignored main": self.workflow.replace( - " pull_request:\n paths:", - " pull_request:\n branches-ignore: [main]\n paths:", + " pull_request: {}", + " pull_request:\n branches-ignore: [main]", + 1, + ), + "tracked vocabulary surface narrowed": self.workflow.replace( + " pull_request: {}", + ' pull_request:\n paths: ["governance/**"]', 1, ), - "tests omitted": self.workflow.replace(' - "tests/**"\n', "", 1), } for label, value in mutations.items(): with self.subTest(label=label): From 40a73b53cff40d11dcc83f431d7db471f8e53855 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 09:03:04 -0500 Subject: [PATCH 100/116] chore(ci): refresh repaired seven-head manifest --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 90da501..5987b8e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,37 +12,37 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "e2b7532784e1d18b07f33b8536708c1492524b87", - "authority_content_revision": "c2790ab007279faff6130a60dc68818343c255ee", - "reviewed_tree_sha": "23cc8d9f20f7962d70fbfd06d54b5b21515912c4" + "revision": "f8bc0a0925113ca815bf5692081b5216162cc918", + "authority_content_revision": "f8bc0a0925113ca815bf5692081b5216162cc918", + "reviewed_tree_sha": "91b5a9ae8cfad52da942575c592ac93e7ea59d84" }, { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "e047f99d7c8779cc8368fe82218d202dc40fc416", + "revision": "646e0d1b7e9f03ca84e7d4e71406659230828b06", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "7089ee6ea0519070d63632cc9bee869dca2359cc" + "reviewed_tree_sha": "a3f241d8d1ea9a975aa68d5da37cf0e9828ab12d" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "ff827f459a2525d65a4ae1fb5782340d542b0c37", + "revision": "878b0e62d725bc099dfa3279c8ff3278a2784c9b", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "66a63fa3deb1549e8c8f69b4a4f744cda1703387" + "reviewed_tree_sha": "e6cf0ddb9c73f49dac0c11111eb995f33e9e41a2" }, { "repository": "hawkinsoperations-proof", "canonical_repository": "HawkinsOperations/hawkinsoperations-proof", - "revision": "67ae70d6c7bb5298c629e10cf33a25399feb972d", + "revision": "77b7874dd753369792330508fa3438cf397cd050", "authority_content_revision": "042a918ad4a8473cd5abcfd575072fc094639682", - "reviewed_tree_sha": "a5c423dad556ca61610c91331ddb78bda962fa2f" + "reviewed_tree_sha": "68fc8c604ffebb392e2fa6b205a920e9560b424b" }, { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "c506065e3ac47941e894ea5c58de513ea9dd7bdc", + "revision": "ca1c4adb7591a0d780934a70604613ae173fbb27", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "24b448612e5f92fdc612e41d10585e3ef15fa96f" + "reviewed_tree_sha": "85e056ac61a970fff91cbd44da0712351a98a10d" }, { "repository": "hoxline", From 396eb92460ca4dd505da688c839db15677097be7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 09:06:28 -0500 Subject: [PATCH 101/116] chore(ci): observe repaired platform head --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 5987b8e..7b33ec6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "878b0e62d725bc099dfa3279c8ff3278a2784c9b", + "revision": "f5b902b2a8d67e258a5662daeff1749fb65db15a", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "e6cf0ddb9c73f49dac0c11111eb995f33e9e41a2" + "reviewed_tree_sha": "d645434976b417340f3425bd6ed8c364c5c15987" }, { "repository": "hawkinsoperations-proof", From eee90989aade24090bf7ad309fc41467347ad5e7 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 09:14:58 -0500 Subject: [PATCH 102/116] chore(ci): observe final platform repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7b33ec6..2a411b3 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "f5b902b2a8d67e258a5662daeff1749fb65db15a", + "revision": "3fd0dba09ccc46be9d3aab3fff006771304821dd", "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "d645434976b417340f3425bd6ed8c364c5c15987" + "reviewed_tree_sha": "985be8665fba5eeb8f948346448b8dfd6ff35954" }, { "repository": "hawkinsoperations-proof", From 4a3508f9d530b1b671bc76755efedcd4702d7911 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 09:18:15 -0500 Subject: [PATCH 103/116] chore(ci): observe regenerated hoxline pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 2a411b3..a29476e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -47,9 +47,9 @@ { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "0dcade7d11ede78e07f707805ad3034458ff948e", + "revision": "dd13842f4e59851f6ddaf0c45fe470570dc322ed", "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", - "reviewed_tree_sha": "b592aef631670291936a4dbd58f11bba3c9c9760" + "reviewed_tree_sha": "c1a339fc2093e14d317893f953b603e0d295555b" } ], "constraints": { From f6d88acac2cbb2ab95482bb4b09dc70bd939a06f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 09:46:19 -0500 Subject: [PATCH 104/116] chore(ci): observe regenerated website pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index a29476e..eb894e4 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "ca1c4adb7591a0d780934a70604613ae173fbb27", + "revision": "240814a247057796f46f854ca9967c95b346559e", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "85e056ac61a970fff91cbd44da0712351a98a10d" + "reviewed_tree_sha": "8e2ff9e1ef7869e3e144091fa82dca6293c91cef" }, { "repository": "hoxline", From 4db63ce07bbf1a0657bb7bae98d5656e2e5ba5cd Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 10:32:03 -0500 Subject: [PATCH 105/116] chore(command-center): record platform stabilization wave --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index eb894e4..5659d2e 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -19,16 +19,16 @@ { "repository": "hawkinsoperations-validation", "canonical_repository": "HawkinsOperations/hawkinsoperations-validation", - "revision": "646e0d1b7e9f03ca84e7d4e71406659230828b06", + "revision": "677b704150b0f5f333c27913dd481b4be6a78ab7", "authority_content_revision": "ebf52f7c6c9b78de767272cc56fccdc584f5c4e0", - "reviewed_tree_sha": "a3f241d8d1ea9a975aa68d5da37cf0e9828ab12d" + "reviewed_tree_sha": "b4a12cfe4a67e5b66171f73cd228c2691789dcc6" }, { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "3fd0dba09ccc46be9d3aab3fff006771304821dd", - "authority_content_revision": "651a43a4dfe0776605d5bd7b85ef4f8381c42b64", - "reviewed_tree_sha": "985be8665fba5eeb8f948346448b8dfd6ff35954" + "revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", + "authority_content_revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", + "reviewed_tree_sha": "85accfe41ae7f6fba3c26c9b40699e1ddd719d27" }, { "repository": "hawkinsoperations-proof", From 5c6127f5acc1031bae2528df3ce1f197da882100 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 10:37:38 -0500 Subject: [PATCH 106/116] chore(command-center): review generator code wave --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 5659d2e..b1fb5f6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -12,9 +12,9 @@ { "repository": "hawkinsoperations-detections", "canonical_repository": "HawkinsOperations/hawkinsoperations-detections", - "revision": "f8bc0a0925113ca815bf5692081b5216162cc918", + "revision": "9e01f43fb350de3370f8c01a323dcdcdf2e33147", "authority_content_revision": "f8bc0a0925113ca815bf5692081b5216162cc918", - "reviewed_tree_sha": "91b5a9ae8cfad52da942575c592ac93e7ea59d84" + "reviewed_tree_sha": "4135fc6fafb3bc842096ee58fa7dd53d24172b65" }, { "repository": "hawkinsoperations-validation", @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", + "revision": "4716d7e65525425be4f70127cdc7f7d3de3a7b9e", "authority_content_revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", - "reviewed_tree_sha": "85accfe41ae7f6fba3c26c9b40699e1ddd719d27" + "reviewed_tree_sha": "9c8e56ec5a9aa62cad4f646f520dd9129494474c" }, { "repository": "hawkinsoperations-proof", @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "240814a247057796f46f854ca9967c95b346559e", + "revision": "0e7cb554ee3fd5519142006246201e7b15f0c9b5", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "8e2ff9e1ef7869e3e144091fa82dca6293c91cef" + "reviewed_tree_sha": "579df6ed7e3da1eb69094c3c9df88dfa47bfbadb" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "dd13842f4e59851f6ddaf0c45fe470570dc322ed", + "revision": "52867ee7e332dba3cab4d2c3e308d636ed5bb610", "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", - "reviewed_tree_sha": "c1a339fc2093e14d317893f953b603e0d295555b" + "reviewed_tree_sha": "7fa92c0e415d5dbe74fda2f418b9d3ca43f6fa74" } ], "constraints": { From d4e26310a070421e296994e5144a35b79c4657c2 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 10:48:57 -0500 Subject: [PATCH 107/116] chore(command-center): record generated consumer wave --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index b1fb5f6..959df8b 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,16 +40,16 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "0e7cb554ee3fd5519142006246201e7b15f0c9b5", + "revision": "9f312edfce59de952efdf5b279dbebba6e7ae540", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "579df6ed7e3da1eb69094c3c9df88dfa47bfbadb" + "reviewed_tree_sha": "67704d031708d32124d0ed46ad20649981036a68" }, { "repository": "hoxline", "canonical_repository": "HawkinsOperations/hoxline", - "revision": "52867ee7e332dba3cab4d2c3e308d636ed5bb610", + "revision": "cd797da491f07b9a0130278d7245f51962dd82c0", "authority_content_revision": "1cb97efc45ffe753389105645c25ed7fe57cf9e5", - "reviewed_tree_sha": "7fa92c0e415d5dbe74fda2f418b9d3ca43f6fa74" + "reviewed_tree_sha": "29dc0d921bbc342f30d8be46cf88f049ea591f0a" } ], "constraints": { From b4e675d706ce7296ca5462f03428b1b401054bdc Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 10:50:39 -0500 Subject: [PATCH 108/116] chore(command-center): record final repair heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 959df8b..c7e6c78 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "4716d7e65525425be4f70127cdc7f7d3de3a7b9e", + "revision": "0413b2581600bf474bbc025d276b740b410719e5", "authority_content_revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", - "reviewed_tree_sha": "9c8e56ec5a9aa62cad4f646f520dd9129494474c" + "reviewed_tree_sha": "217a047462ac87ed5159e0863ce0976729fd9dc0" }, { "repository": "hawkinsoperations-proof", From 86d66bc032f705e8d193a72f6c2b44945d8b627f Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 10:59:45 -0500 Subject: [PATCH 109/116] chore(command-center): review website schema repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index c7e6c78..f28554d 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "9f312edfce59de952efdf5b279dbebba6e7ae540", + "revision": "b1842e98bc03989cbdead133a2a7f2182471b759", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "67704d031708d32124d0ed46ad20649981036a68" + "reviewed_tree_sha": "6c6802966ddcd308142b252d5062b434739a934f" }, { "repository": "hoxline", From f3dd6bcad5b0d91509cf047447707d9c6b9d6008 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:01:13 -0500 Subject: [PATCH 110/116] chore(command-center): record final website repair heads --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index f28554d..73b3779 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "0413b2581600bf474bbc025d276b740b410719e5", + "revision": "92efbcc826e8331c37752f79bfc0abb6fc328471", "authority_content_revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", - "reviewed_tree_sha": "217a047462ac87ed5159e0863ce0976729fd9dc0" + "reviewed_tree_sha": "150b77bcf27276ce903e46bca7e8cf6b14ea1393" }, { "repository": "hawkinsoperations-proof", From d7c92a8775be17334e2ed64a474299f0439604d9 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:05:35 -0500 Subject: [PATCH 111/116] chore(command-center): review website lineage-fetch repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 73b3779..2f86299 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "b1842e98bc03989cbdead133a2a7f2182471b759", + "revision": "839e1ac498b6fca055d7101da91c6df523201205", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "6c6802966ddcd308142b252d5062b434739a934f" + "reviewed_tree_sha": "243b3d9a5cb2ea8f3f65a7ddf5d3d22d8d1a7c6b" }, { "repository": "hoxline", From e7bdfda79e89bb01e3098edb82297449f836f402 Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:11:24 -0500 Subject: [PATCH 112/116] chore(command-center): bind finite generated pair wave --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 2f86299..7110fb6 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -26,9 +26,9 @@ { "repository": "hawkinsoperations-platform", "canonical_repository": "HawkinsOperations/hawkinsoperations-platform", - "revision": "92efbcc826e8331c37752f79bfc0abb6fc328471", + "revision": "d2901f303a2047436d1ada2d97f2eb4310380585", "authority_content_revision": "a667c4de8b478fe165c3ec612e642bbd5d879492", - "reviewed_tree_sha": "150b77bcf27276ce903e46bca7e8cf6b14ea1393" + "reviewed_tree_sha": "0ad3ad8ff804e6b0fff9c4bf5eb1c913a76f602c" }, { "repository": "hawkinsoperations-proof", @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "839e1ac498b6fca055d7101da91c6df523201205", + "revision": "ea3e07dd6326d996efc264b02f2a30ff7bd13419", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "243b3d9a5cb2ea8f3f65a7ddf5d3d22d8d1a7c6b" + "reviewed_tree_sha": "2fef438743f962258f21340da17c2c89af5efb79" }, { "repository": "hoxline", From f82fda883771e240af1178947b2855d26616f4fb Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:28:52 -0500 Subject: [PATCH 113/116] chore(command-center): review rewrite-projection repair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 7110fb6..f68ce8d 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "ea3e07dd6326d996efc264b02f2a30ff7bd13419", + "revision": "79fd791afe466143ab5540604dd51c8cd52ce285", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "2fef438743f962258f21340da17c2c89af5efb79" + "reviewed_tree_sha": "5b9f35b95dfbf37b067ceb7e88feac0b66dcfe6a" }, { "repository": "hoxline", From 32269a3da4909d08a90747da332cebb7adc0006c Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:32:52 -0500 Subject: [PATCH 114/116] chore(command-center): bind rewrite-resilient status pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index f68ce8d..d4026ac 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "79fd791afe466143ab5540604dd51c8cd52ce285", + "revision": "6c799b595bae574303974e2db2c820a7886418e8", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "5b9f35b95dfbf37b067ceb7e88feac0b66dcfe6a" + "reviewed_tree_sha": "0a68abe2f3a1d480615795b2ea40e28200c835e9" }, { "repository": "hoxline", From ba99c8dd3f67c17076ef5eee5d36d341dc78e09e Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:36:55 -0500 Subject: [PATCH 115/116] chore(command-center): review projection governance binding --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index d4026ac..0715f83 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "6c799b595bae574303974e2db2c820a7886418e8", + "revision": "72f3702b42bdefe4923fc20fd05b7e5470154d3c", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "0a68abe2f3a1d480615795b2ea40e28200c835e9" + "reviewed_tree_sha": "c153565ecbebe097015f88bdbae441906b087a7a" }, { "repository": "hoxline", From 1f30d7bc23347cd011ac6b96561b3bff7414679a Mon Sep 17 00:00:00 2001 From: Raylee Hawkins Date: Fri, 24 Jul 2026 11:40:31 -0500 Subject: [PATCH 116/116] chore(command-center): bind projection-governed status pair --- governance/CONVERGENCE_SOURCE_MANIFEST.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/governance/CONVERGENCE_SOURCE_MANIFEST.json b/governance/CONVERGENCE_SOURCE_MANIFEST.json index 0715f83..eafbb19 100644 --- a/governance/CONVERGENCE_SOURCE_MANIFEST.json +++ b/governance/CONVERGENCE_SOURCE_MANIFEST.json @@ -40,9 +40,9 @@ { "repository": "hawkinsoperations-website", "canonical_repository": "HawkinsOperations/hawkinsoperations-website", - "revision": "72f3702b42bdefe4923fc20fd05b7e5470154d3c", + "revision": "ee30ae81d31e8f27fa779ddb42470f7d27db1f33", "authority_content_revision": "5856f8e69527b5e61c3953b88a2ad4c088268655", - "reviewed_tree_sha": "c153565ecbebe097015f88bdbae441906b087a7a" + "reviewed_tree_sha": "672da08e0e5c42d7be543cb9bdcfa45ccb59daa2" }, { "repository": "hoxline",