From a6d47c51cc02ccf161bf142f0486c436bdbacbcd Mon Sep 17 00:00:00 2001 From: codex Date: Tue, 1 Sep 2026 00:18:15 +0200 Subject: [PATCH] Record Policy Nexus metadata apply and diagnose bootstrap Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663 --- ...0014-policy-nexus-forgejo-source-read.yaml | 12 +++++++++++- .../provision-policy-nexus-forgejo-source.py | 19 ++++++++++++++++++- ...t_policy_nexus_forgejo_source_provision.py | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/credential-change-requests/CCR-2026-0014-policy-nexus-forgejo-source-read.yaml b/credential-change-requests/CCR-2026-0014-policy-nexus-forgejo-source-read.yaml index 768e3a4..ca882b8 100644 --- a/credential-change-requests/CCR-2026-0014-policy-nexus-forgejo-source-read.yaml +++ b/credential-change-requests/CCR-2026-0014-policy-nexus-forgejo-source-read.yaml @@ -3,7 +3,7 @@ kind: credential-change-request schema_version: 1 request_type: workload-kv-read title: Policy Nexus Forgejo private-source read token lane -status: approved +status: applied created: '2026-08-31' updated: '2026-08-31' requester: @@ -137,6 +137,16 @@ verification: and its public health endpoint returns 200; the KeyCape openbao-admin authorize path returns 302. No Forgejo identity, PAT, OpenBao secret value, Actions secret, or workflow run was created. + - at: '2026-08-31T22:15:50+00:00' + actor: attended operator via governed platform-admin lane + kind: delegated_metadata_apply + result: passed + details: + - Delegated metadata applier ran as attended operator via governed platform-admin + lane using local bao CLI ambient authority. + - 'Policy metadata write: sys/policies/acl/workload-kv-read-policy-nexus-forgejo-source' + - 'Auth role metadata write: auth/netkingdom/role/policy-nexus-forgejo-source-workload-kv-read' + - No secret values were read, written, printed, or accepted in argv. lifecycle: deactivate: Remove the repository Actions secret, revoke the Forgejo PAT, disable the OpenBao access path, and leave scheduled publication failing closed. diff --git a/scripts/provision-policy-nexus-forgejo-source.py b/scripts/provision-policy-nexus-forgejo-source.py index 3ca5f13..0eae946 100755 --- a/scripts/provision-policy-nexus-forgejo-source.py +++ b/scripts/provision-policy-nexus-forgejo-source.py @@ -26,6 +26,7 @@ SECRET = "FORGEJO_SOURCE_TOKEN" TOKEN_PREFIX = "policy-nexus-source-read-" SCOPES = ["read:repository"] REPO_DIR = Path(__file__).resolve().parent.parent +DIAGNOSTIC_PATH = Path("/tmp/policy-nexus-source-bootstrap-diagnostic.json") NON_CODE_UNITS = ( "repo.actions", "repo.packages", @@ -43,6 +44,14 @@ class ProvisionError(RuntimeError): pass +def write_diagnostic(stage: str, error: Exception | None = None) -> None: + detail = str(error) if isinstance(error, ProvisionError) else "unexpected internal error" + DIAGNOSTIC_PATH.write_text( + json.dumps({"stage": stage, "detail": detail}, sort_keys=True) + "\n" + ) + DIAGNOSTIC_PATH.chmod(0o600) + + def api_request( token: str, method: str, @@ -332,6 +341,7 @@ def provision(admin_token: str) -> None: def outer() -> int: + DIAGNOSTIC_PATH.unlink(missing_ok=True) result = subprocess.run( [ "warden", @@ -350,6 +360,8 @@ def outer() -> int: check=False, timeout=900, ) + if result.returncode != 0 and not DIAGNOSTIC_PATH.exists(): + write_diagnostic("forgejo-admin-route") return result.returncode @@ -362,7 +374,12 @@ def main() -> int: admin_token = os.environ.get("API_TOKEN", "") if not admin_token: raise ProvisionError("Warden did not provide API_TOKEN") - provision(admin_token) + try: + provision(admin_token) + except Exception as error: + write_diagnostic("provision", error) + raise + DIAGNOSTIC_PATH.unlink(missing_ok=True) return 0 diff --git a/tests/test_policy_nexus_forgejo_source_provision.py b/tests/test_policy_nexus_forgejo_source_provision.py index e731a8f..e1caa16 100644 --- a/tests/test_policy_nexus_forgejo_source_provision.py +++ b/tests/test_policy_nexus_forgejo_source_provision.py @@ -31,6 +31,23 @@ class PolicyNexusForgejoSourceProvisionTests(unittest.TestCase): MODULE.verify_source_token("candidate", ["read:repository", "write:repository"]) request.assert_not_called() + def test_diagnostic_redacts_unexpected_exception_details(self) -> None: + with self.subTest("unexpected"): + with mock.patch.object(MODULE, "DIAGNOSTIC_PATH") as path: + MODULE.write_diagnostic("provision", RuntimeError("sensitive detail")) + payload = path.write_text.call_args.args[0] + self.assertNotIn("sensitive detail", payload) + self.assertIn("unexpected internal error", payload) + + with self.subTest("bounded provision error"): + with mock.patch.object(MODULE, "DIAGNOSTIC_PATH") as path: + MODULE.write_diagnostic( + "provision", + MODULE.ProvisionError("PUT /bounded/path returned HTTP 403"), + ) + payload = path.write_text.call_args.args[0] + self.assertIn("PUT /bounded/path returned HTTP 403", payload) + def test_actions_failure_revokes_pat_and_removes_new_kv_value(self) -> None: calls: list[tuple[str, str]] = []