diff --git a/argocd/railiance01/applications/ops-mason-builder.application.yaml b/argocd/railiance01/applications/ops-mason-builder.application.yaml new file mode 100644 index 0000000..f14f5c0 --- /dev/null +++ b/argocd/railiance01/applications/ops-mason-builder.application.yaml @@ -0,0 +1,27 @@ +# railiance01 child Application (MASON-IN-0006 choice (b), decision +# 30d29060-8d14-4a8e-9cde-34aa826eb8d1). Scoped ops-mason builder identity. +# No automated sync, no finalizer; targetRevision is the commit that +# introduced the manifests. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: ops-mason-builder + namespace: argocd + labels: + app.kubernetes.io/part-of: railiance-gitops + railiance-platform/component: ops-mason-builder + annotations: + argocd.argoproj.io/sync-wave: "10" +spec: + project: railiance-platform-addons + source: + repoURL: https://forgejo.coulomb.social/coulomb/railiance-platform.git + targetRevision: bd6660a91672c76b78e017c22394705381d8767d + path: argocd/platform-addons/ops-mason-builder + destination: + server: https://kubernetes.default.svc + namespace: default + syncPolicy: + syncOptions: + - ApplyOutOfSyncOnly=true + - PruneLast=true diff --git a/tests/test_ops_mason_builder_rbac.py b/tests/test_ops_mason_builder_rbac.py index 1ab0f33..ab7e22b 100644 --- a/tests/test_ops_mason_builder_rbac.py +++ b/tests/test_ops_mason_builder_rbac.py @@ -2,14 +2,16 @@ Parses the GitOps manifests and asserts the founder's 2026-10-22 boundary: the five granted rules only, no forbidden resources, no escalate/bind/impersonate, -no wildcards, and a User subject with no ServiceAccount. +no wildcards, a User subject with no ServiceAccount, and a manual, pinned Application. """ from pathlib import Path +import re import yaml ROOT = Path(__file__).resolve().parents[1] ADDON = ROOT / "argocd/platform-addons/ops-mason-builder" +APP = ROOT / "argocd/railiance01/applications/ops-mason-builder.application.yaml" WRITE_VERBS = ["create", "get", "list", "watch", "update", "patch", "delete"] READ_VERBS = ["get", "list", "watch"] @@ -87,3 +89,13 @@ def test_binding_targets_only_the_user(): assert binding["subjects"] == [{"kind": "User", "name": "ops-mason-builder", "apiGroup": "rbac.authorization.k8s.io"}] assert all(s["kind"] != "ServiceAccount" for s in binding["subjects"]) + + +def test_application_manual_and_pinned(): + app = yaml.safe_load(APP.read_text()) + spec = app["spec"] + assert spec["project"] == "railiance-platform-addons" + assert spec["source"]["path"] == "argocd/platform-addons/ops-mason-builder" + assert re.fullmatch(r"[0-9a-f]{40}", spec["source"]["targetRevision"]) + assert "automated" not in spec.get("syncPolicy", {}) + assert "finalizers" not in app["metadata"]