diff --git a/.kaizen/agents/custodian-codex/supervision.json b/.kaizen/agents/custodian-codex/supervision.json index ccbe2fc..64d0408 100644 --- a/.kaizen/agents/custodian-codex/supervision.json +++ b/.kaizen/agents/custodian-codex/supervision.json @@ -1132,6 +1132,29 @@ "execution_observation_note": "First postcheck ran before Forgejo readiness completed and failed its readiness assertion; retained failure. Re-observation after rollout success passed. No repeated effect, rollback or recovery.", "execution_finished_at": "2026-10-19T08:44:58.532576+00:00", "human_verification_ref": "docs/changes/netkingdom-target-2026-10-18/forgejo-good-case-preparation-r1/activation-r2/human-signin-2026-10-19.json" + }, + { + "proposal_id": "POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1", + "disposition": "pending", + "outcome": "not_executed", + "proposal_ref": "docs/changes/CUST-WP-0079/policy-publication-r1/PLAN.md", + "original_revision": 1, + "original_digest": "309ef01650b65bc6b28e86daad9b2835a242631cf60e0896e849461bb917504f", + "original_digest_sha256": "309ef01650b65bc6b28e86daad9b2835a242631cf60e0896e849461bb917504f", + "plan_digest_sha256": "6f8c7860b371460e1695027241d1d14b9ca5e46f7003ee92d4c717c26147740a", + "target": "railiance01 policy-nexus existing public host; paired rapp-policy-nexus/railiance-apps source", + "expected_result": "74 published documents; only accepted build-mode guardrail added; exact image 214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 and paired release hashes verified", + "verification_ref": "docs/changes/CUST-WP-0079/policy-publication-r1/PLAN.md exact post-approval sequence", + "rollback_ref": "docs/changes/CUST-WP-0079/policy-publication-r1/PLAN.md abort and rollback to verified prechange Helm revision 9", + "incremental_infrastructure_cost_eur": 0, + "cost_estimate_eur": null, + "risk_estimate_eur": null, + "risk_estimate": "Moderate public-content risk, low nonzero runtime risk; existing node 90% requested; fresh 10m/32Mi surge check required. One 5min upgrade plus up to 5min rollback, 15min attended verification estimate. No new spend or access policy.", + "supervisor": "Bernd Worsch", + "approved_revision": null, + "executed_revision": null, + "refinement_or_rescue": false, + "promotion_evidence": false } ], "trials": [ diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/PLAN.md b/docs/changes/CUST-WP-0079/policy-publication-r1/PLAN.md new file mode 100644 index 0000000..698fb33 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/PLAN.md @@ -0,0 +1,152 @@ +# POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1 + +Status: prepared, **not approved or executed**. Proposed founder batch: publish +one already-accepted canon guardrail through the existing policy host. Receipt +and source artifacts belong to this same proposal; refinements are not new +successful trials. The supervisor must bind the final packet digest and real +approval reference before execution. No old approval is reused. + +## Exact intended change + +Image `forgejo.coulomb.social/coulomb/policy-nexus@sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1`. +Paired publication `8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e`; +inventory `e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd`; +source set `b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682`; +raw lock `c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529`. +Source policy commit `9fabcce1cb4c83165bcaba8be58d76788b4d87a1`. + +74 documents replace73; exactly `canon-build-mode-change-authorization` is +added, with no existing document removal or source-digest change. Original local +OCI artifact and readback are in `/tmp/custodian-policy-image-20261019`. + +Source patches are prepared, not applied: + +* `rapp-policy-nexus.patch`: `bindings/reef-railiance.yaml` pins the proposed + artifact and marks its release proposed. Existing reef production admission + remains the environment classification, not approval of this release. +* `railiance-apps.patch`: production binding plus production/candidate values + carry the same four deployment pins. The binding explicitly clears previous + approval date/reference and live-verification claims and says release-proposed. + +The binding checker correctly refuses this unapproved candidate. After the +founder approves this exact packet, the supervisor records actual approval +date/reference and sets release-approved in both release metadata records; +no image/source/content field may change. This clerical metadata completion is +part of the approved action, not permission to choose another artifact. Native +verification fields remain unset until evidence exists. + +## Verified baseline and drift + +`live-observation.json` binds railiance01 SSH alias, expected node IP +92.205.62.239, host machine-ID digest and UTC capture. It reads only selected +image/release fields plus readiness and Helm metadata. Output contains equality +predicates, not raw annotations, Secrets or errors. + +Observed: Helm revision9 deployed, replicas1/ready1; image and three deployment +release digests equal the known rollback `4e0db6...99d06` and apps production +binding. The live public manifest matches its approved73-document release. + +Important source drift: `rapp-policy-nexus/bindings/reef-railiance.yaml` still +contains historical `23df0ab3...3cea` pins, while apps and live agree on4e0db6. +The proposed rApp patch reconciles that stale source as part of the new release. +Never reverse it blindly as a runtime rollback. `rollback-rapp-binding.yaml` +and the rollback patches target verified4e0db6, retaining its actual existing +approval reference from apps, not stale23df0ab3. + +`source-pins.json` records exact owner heads and original/changed file hashes. +Both patches pass `git apply --check`; neither owner checkout was edited. + +## Render and server verification + +`candidate-rendered.yaml`, `rollback-rendered.yaml`, `rendered.diff` use the +unchanged owner Helm chart. Nine resources render. Exactly seven fields differ, +all in Deployment/policy-nexus: container image and three release digest fields +on Deployment metadata and pod-template metadata. No replica, resource, service, +ingress, TLS, NetworkPolicy, service account or access-policy changes. + +`server-dry-run.json`: all nine exact candidate resources passed +`kubectl apply --dry-run=server --validate=true -f - -o name` on railiance01, +with no stderr and no persisted change. Raw errors are suppressed by the retained +recipe. This does not prove image pull availability or Helm upgrade success. +Owner `make check` passed9 packaging tests plus Helm lint; both checkouts pass +`git diff --check`. Registry candidate availability remains pending because +the exact OCI image has not been uploaded. + +Current headroom observation: CPU requests3605m (90%), memory9856Mi (61%). +The rollout asks for one additional10m CPU/32Mi request (limit100m/64Mi) because +maxSurge1/maxUnavailable0. Recheck before execution: stale headroom evidence is +not scheduling permission. Abort if spare requested capacity cannot fit this +surge; do not alter another workload to create capacity under this proposal. + +## Exact post-approval execution sequence + +1. Supervisor records founder approval, exact proposal revision/digest, target, + cost/risk and abort owner. Confirm source files/heads, chart content, live + revision9/rollback pins and host identity still match. If any differ, stop + and reconcile the proposal; do not silently substitute a newer candidate. +2. Artifact owner transfers the retained OCI candidate to Forgejo through its + scoped package-write route, preserving the manifest digest; no :main update + or fresh rebuild is required. Verify remote manifest and image release files + match all five pins. A rebuilt/converted digest is a different candidate and + stops this execution. No credential values enter the packet or logs. +3. Apply the exact paired source patches to their owners, complete real approval + metadata as above, run owner checks, and commit the production-tier source + changes. If the proposed metadata has changed meanwhile, regenerate the + reviewed patches rather than force-applying. Keep old approved evidence. +4. From `/home/worsch/railiance-apps`, run existing owner targets: + `make policy-nexus-check-binding`, `make policy-nexus-check-image`, + `make policy-nexus-render`, then recheck exact rendered field diff and current + headroom. Capture check-image errors privately and emit only bounded failure + classifications; its generic helper can otherwise echo raw errors. +5. Run `make policy-nexus-server-dry-run` (owner uses a nonpersistent default + namespace probe), plus the retained exact production-namespace server probe + if source/runtime preconditions changed. Require success before deployment. +6. Run `make policy-nexus-deploy POLICY_NEXUS_TARGET=railiance01` once. Existing + owner target packages chart0.2.0, copies it to the host, and uses Helm upgrade + with `--atomic --wait --timeout 5m`; no ArgoCD claim or manual kubectl apply. +7. Run `make policy-nexus-smoke` with the approved binding, keeping only bounded + expected-pin outcomes; independently hash public publication/inventory/lock, + require source-set equality, verify74 document metadata and the new guardrail + bytes/expiry banner against the candidate, confirm previous73 source hashes + unchanged, and confirm the deployed image/three release fields and1/1 ready. + Retain new Helm revision and safe verification evidence after success only. + +The transition gate is explicitly production-tier/direct-administer until +2026-12-21, per owner `docs/change-gate.md`. The final live record needs +`activation=APPROVED` and the real founder approval reference, not a fabricated +approval in this preparation packet. ArgoCD does not currently own this release. + +## Abort and rollback + +Abort owner: `rapp-policy-nexus` for actuation/runtime, coordinated by +`railiance-apps`; supervisor/residual-risk owner `the-custodian`. Stop before +actuation on any source/host/pin/registry/headroom/dry-run mismatch. +After actuation, stop on failed atomic upgrade, readiness timeout, incorrect +public hash/content, TLS/redirect failure or degraded existing pages. Do not +repeat an upgrade blindly. + +Helm's atomic rollback is the first failure recovery. If explicit recovery is +required, use the existing owner path: +`make -C /home/worsch/railiance-apps policy-nexus-rollback POLICY_NEXUS_REVISION=9 POLICY_NEXUS_TARGET=railiance01`. +This exact observed revision must still be the prechange approved release. +Verify4e0db6 image and all paired values from `rollback-binding.json`, public +73-document manifest and readiness. Reconcile owner source records to +`rollback-rapp-binding.yaml` and `rollback-binding.json`; rollback patch context +must account for newly recorded approval metadata (never force the preparation +patch if metadata differs). Retain failure/recovery outcomes and new Helm +revision; rollback can create a new revision carrying old content. + +## Estimated bounds and limitations + +Incremental infrastructure spend EUR0; no provider subscription, purchase or +external model call. One local26.6MB OCI transfer; unchanged persistent resources. +One upgrade <=5min plus, if needed, one rollback <=5min; allow15min attended +verification/recovery. Public-content/change risk moderate, runtime risk low +but nonzero on the already90%-requested node. No data migration, database, +credential, network exposure or storage change. Supervisor must accept these +estimates; they are not a cost guarantee. + +Existing runtime package database/nginx config equality is retained in image +evidence. No new vulnerability scan or native CI success is claimed. Source +commit9fabcce fixes the observed CI failure locally;65 tests and full owner build +passed. This packet is ready for approval review, not proof of public release. diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/SHA256SUMS b/docs/changes/CUST-WP-0079/policy-publication-r1/SHA256SUMS new file mode 100644 index 0000000..fc81ab4 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/SHA256SUMS @@ -0,0 +1,33 @@ +6f8c7860b371460e1695027241d1d14b9ca5e46f7003ee92d4c717c26147740a PLAN.md +ceb2451c3c236f196527718ee9f0148014aad4d66a15b77d8303c0df36848c04 candidate-binding.json +a9de1adb22d83fa47a676e3685edf4fad578e3215db2db493ef4a8ca138dd36e candidate-candidate-values.yaml +dfdbe7a570fe2910c67f9074050df10ddc560780cdfabe7bd0c2b4343329add8 candidate-rapp-binding.yaml +62b369b913d610508fb135834e7cb166f62649f3d9e61eddbe02e8fca542a953 candidate-rendered.yaml +a9de1adb22d83fa47a676e3685edf4fad578e3215db2db493ef4a8ca138dd36e candidate-values.yaml +fbe2fb76ba284a98c31ed0c412e7425de88e89d1f22eb86bf0b0110782ec8158 chart/Chart.yaml +39cf25665540a2a02f0b73962647cbfc3e95c92f4db38c4fcaa750fb272dab62 chart/templates/_helpers.tpl +eb32277328c67a5e3f1e0581569f935b9ec2194003392d856ed05274c36d1f9f chart/templates/deployment.yaml +b02907d7c7e0e13507fe33132032cac517012c142ed77c0fafe4d06d2eedf615 chart/templates/ingress.yaml +f5ff4ea020635906f4fff9c11ceabdbccbda1f4383902878f6d1c44120423752 chart/templates/networkpolicy.yaml +46cf8a2659d8cb35fe2f16cc4fa80dee3dfe97a8b37ad2b1ec10c13e1de3d371 chart/templates/service.yaml +a107006a0ad1c702f65e4c4eff0ad45f2c5ab2f401f5532a3ca14a406a9540cc chart/templates/serviceaccount.yaml +a53f7801a38451cf7d0da679a7fbe54666a7452e391326fa515e002bc970026d chart/values.yaml +2a5ab9ae708ee922c467234243c60df73ed21ca1be9f3cc365ede23b7509b051 headroom-recipe.py +9ad208bd65b644d1f41b2a1bbc269bed82ed6db50f20189c115a378187d73512 headroom.json +e438c8e207cdce2afb2cdf64bb9ce481887db9f3274b1f8de8ae2652ea15110a live-observation.json +4a6734aadabd0610cc8d1fb13338e3da88038ea4e047d866ebf38cb7fac0c88d observe_remote.py +226d0225e11e1088cda2aee4c83c5ce31d0fe0215bd01a371b380c2e8c7f1033 pending-binding-check.json +9c2ceb3db33317bb6c5e8c24ffb4f8f173a9e8e53926abccac98f09d48f41c15 railiance-apps-rollback.patch +63dc49fd7d4149eb7764da974f6dbd46b341a87a191f5944763aa4b1684cb1dc railiance-apps.patch +e20a28be6ef09fa1ae41c998a0caef1ece8a12d24741034f0898b5e536d50c9a rapp-policy-nexus-rollback.patch +4f4d8cf8765a75f5c9d1dbfb3e3187b027e5e2e368d1f1022b76187a141a2d51 rapp-policy-nexus.patch +cf6a13992ca364a08d326622b4853ecb501b8b410052665f02b196d871fec305 render-verification.json +b00de95ba86eeb50fe939dca94287d740bf524e7916af3b1f5ef39edb63b318b rendered.diff +65b8c1a339ed1e75cbf72d0f6ac474d72bad1be9c381ebbeea700c7a9455f33e rollback-binding.json +08a4c10423cb4e7673529a555bdcd0c4a3620daaf7594e26cab21183ef9ffb82 rollback-rapp-binding.yaml +df457588fea55d5c927d078e9231530c04ec7771a293cc644104e315db860187 rollback-rendered.yaml +6e0f5a529b450f6b8f00f6fc59c50a7e5b652520f0a370b199a49cb416fac062 rollback-values.yaml +cbdd40a12c9c6bf76f827fd1d788bb176c46abbd675ee6d4901bdfbadde67f31 server-dry-run-recipe.py +6e8c468604606b8982e53197e0d888429d56459fcfb35d1ed00ade2be4986df0 server-dry-run.json +fa622bfda8e40a45f451c9e8227fd348a76a177fa7ef01ccbe26e5b4a0eb5ef4 source-pins.json +8090c96d2bb869a7568c779156ed364b412a2e8b3ed3ba6481121e3d4ee443c4 validation.json diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-binding.json b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-binding.json new file mode 100644 index 0000000..b204a9b --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-binding.json @@ -0,0 +1,23 @@ +{ + "schema_version": "policy-nexus-production-binding/v1", + "status": "release-proposed", + "approved_on": null, + "rapp_repo": "rapp-policy-nexus", + "reef": "reef-railiance", + "rail": "rail-kubernetes", + "namespace": "policy-nexus", + "release": "policy-nexus", + "hostname": "policy.coulomb.social", + "image_repository": "forgejo.coulomb.social/coulomb/policy-nexus", + "image_digest": "sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1", + "publication_manifest_digest": "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e", + "source_inventory_digest": "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd", + "source_set_digest": "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682", + "residual_risk_owner": "the-custodian", + "proposal_id": "POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1", + "publication_source_revision": "9fabcce1cb4c83165bcaba8be58d76788b4d87a1", + "source_lock_digest": "c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529", + "approval_ref": null, + "verified_helm_revision": null, + "native_verification_ref": null +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-candidate-values.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-candidate-values.yaml new file mode 100644 index 0000000..98984f2 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-candidate-values.yaml @@ -0,0 +1,6 @@ +image: + repository: forgejo.coulomb.social/coulomb/policy-nexus + digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 +publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e +sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd +sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-rapp-binding.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-rapp-binding.yaml new file mode 100644 index 0000000..9dac416 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-rapp-binding.yaml @@ -0,0 +1,20 @@ +schema_version: rapp-binding/v1 +rapp_id: rapp-policy-nexus +reef_id: reef-railiance +rail_id: rail-kubernetes +admission: production-approved +approved_on: "2026-09-01" +namespace: policy-nexus +release: policy-nexus +hostname: policy.coulomb.social +cluster_issuer: letsencrypt-prod +image_repository: forgejo.coulomb.social/coulomb/policy-nexus +image_digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 +publication_manifest_digest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e +source_inventory_digest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd +source_set_digest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 +residual_risk_owner: the-custodian +release_status: proposed +release_proposal_id: POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1 +release_approval_ref: null +source_lock_digest: c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-rendered.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-rendered.yaml new file mode 100644 index 0000000..baa0797 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-rendered.yaml @@ -0,0 +1,280 @@ +--- +# Source: policy-nexus/templates/networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: policy-nexus-default-deny + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + podSelector: {} + policyTypes: + - Ingress + - Egress +--- +# Source: policy-nexus/templates/networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: policy-nexus-traefik + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - port: 8080 + protocol: TCP +--- +# Source: policy-nexus/templates/networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: policy-nexus-acme-solver + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + podSelector: + matchLabels: + acme.cert-manager.io/http01-solver: "true" + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - port: 8089 + protocol: TCP +--- +# Source: policy-nexus/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: policy-nexus + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +automountServiceAccountToken: false +--- +# Source: policy-nexus/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: policy-nexus + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + ports: + - name: http + port: 80 + targetPort: http + protocol: TCP +--- +# Source: policy-nexus/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: policy-nexus + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: + policy.coulomb.social/publication-manifest-digest: "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e" + policy.coulomb.social/source-inventory-digest: "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd" + policy.coulomb.social/source-set-digest: "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682" +spec: + replicas: 1 + revisionHistoryLimit: 10 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + selector: + matchLabels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + template: + metadata: + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + annotations: + policy.coulomb.social/publication-manifest-digest: "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e" + policy.coulomb.social/source-inventory-digest: "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd" + policy.coulomb.social/source-set-digest: "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682" + spec: + serviceAccountName: policy-nexus + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + runAsUser: 101 + runAsGroup: 101 + fsGroup: 101 + seccompProfile: + type: RuntimeDefault + containers: + - name: policy-nexus + image: "forgejo.coulomb.social/coulomb/policy-nexus@sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1" + imagePullPolicy: IfNotPresent + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + ports: + - name: http + containerPort: 8080 + protocol: TCP + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 + resources: + limits: + cpu: 100m + memory: 64Mi + requests: + cpu: 10m + memory: 32Mi + volumeMounts: + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: + sizeLimit: 16Mi +--- +# Source: policy-nexus/templates/ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: policy-nexus-http + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.middlewares: "policy-nexus-policy-nexus-https-redirect@kubernetescrd" +spec: + ingressClassName: traefik + rules: + - host: "policy.coulomb.social" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: policy-nexus + port: + name: http +--- +# Source: policy-nexus/templates/ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: policy-nexus-https + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + ingressClassName: traefik + tls: + - hosts: + - "policy.coulomb.social" + secretName: policy-coulomb-social-tls + rules: + - host: "policy.coulomb.social" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: policy-nexus + port: + name: http +--- +# Source: policy-nexus/templates/ingress.yaml +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: policy-nexus-https-redirect + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + redirectScheme: + scheme: https + permanent: true diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-values.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-values.yaml new file mode 100644 index 0000000..98984f2 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/candidate-values.yaml @@ -0,0 +1,6 @@ +image: + repository: forgejo.coulomb.social/coulomb/policy-nexus + digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 +publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e +sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd +sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/Chart.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/Chart.yaml new file mode 100644 index 0000000..32015c6 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: policy-nexus +description: Hardened public runtime for the immutable policy-nexus site artifact +type: application +version: 0.2.0 +appVersion: "0.2.0" diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/_helpers.tpl b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/_helpers.tpl new file mode 100644 index 0000000..8180543 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/_helpers.tpl @@ -0,0 +1,48 @@ +{{- define "policy-nexus.name" -}} +policy-nexus +{{- end }} + +{{- define "policy-nexus.fullname" -}} +{{- if .Release.Name }}{{ .Release.Name | trunc 63 | trimSuffix "-" }}{{ else }}policy-nexus{{ end }} +{{- end }} + +{{- define "policy-nexus.labels" -}} +app.kubernetes.io/name: {{ include "policy-nexus.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }} +{{- end }} + +{{- define "policy-nexus.selectorLabels" -}} +app.kubernetes.io/name: {{ include "policy-nexus.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{- define "policy-nexus.image" -}} +{{- if not (regexMatch "^sha256:[a-f0-9]{64}$" .Values.image.digest) -}} +{{- fail "image.digest must be an immutable lowercase sha256:<64-hex> OCI digest" -}} +{{- end -}} +{{- printf "%s@%s" .Values.image.repository .Values.image.digest -}} +{{- end }} + +{{- define "policy-nexus.publicationDigest" -}} +{{- if not (regexMatch "^[a-f0-9]{64}$" .Values.publicationManifestDigest) -}} +{{- fail "publicationManifestDigest must be the lowercase 64-hex SHA-256 of publication-manifest.json" -}} +{{- end -}} +{{- .Values.publicationManifestDigest -}} +{{- end }} + +{{- define "policy-nexus.sourceInventoryDigest" -}} +{{- if not (regexMatch "^[a-f0-9]{64}$" .Values.sourceInventoryDigest) -}} +{{- fail "sourceInventoryDigest must be the lowercase 64-hex SHA-256 of source-inventory.json" -}} +{{- end -}} +{{- .Values.sourceInventoryDigest -}} +{{- end }} + +{{- define "policy-nexus.sourceSetDigest" -}} +{{- if not (regexMatch "^[a-f0-9]{64}$" .Values.sourceSetDigest) -}} +{{- fail "sourceSetDigest must be the lowercase 64-hex digest recorded in source-inventory.json" -}} +{{- end -}} +{{- .Values.sourceSetDigest -}} +{{- end }} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/deployment.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/deployment.yaml new file mode 100644 index 0000000..7b7bf83 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/deployment.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "policy-nexus.fullname" . }} + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} + annotations: + policy.coulomb.social/publication-manifest-digest: {{ include "policy-nexus.publicationDigest" . | quote }} + policy.coulomb.social/source-inventory-digest: {{ include "policy-nexus.sourceInventoryDigest" . | quote }} + policy.coulomb.social/source-set-digest: {{ include "policy-nexus.sourceSetDigest" . | quote }} +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: 10 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + selector: + matchLabels: + {{- include "policy-nexus.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "policy-nexus.selectorLabels" . | nindent 8 }} + annotations: + policy.coulomb.social/publication-manifest-digest: {{ include "policy-nexus.publicationDigest" . | quote }} + policy.coulomb.social/source-inventory-digest: {{ include "policy-nexus.sourceInventoryDigest" . | quote }} + policy.coulomb.social/source-set-digest: {{ include "policy-nexus.sourceSetDigest" . | quote }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "policy-nexus.fullname" . }} + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + runAsUser: 101 + runAsGroup: 101 + fsGroup: 101 + seccompProfile: + type: RuntimeDefault + containers: + - name: policy-nexus + image: {{ include "policy-nexus.image" . | quote }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + ports: + - name: http + containerPort: 8080 + protocol: TCP + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: + sizeLimit: 16Mi diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/ingress.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/ingress.yaml new file mode 100644 index 0000000..cf6b472 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/ingress.yaml @@ -0,0 +1,61 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: {{ include "policy-nexus.fullname" . }}-https-redirect + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} +spec: + redirectScheme: + scheme: https + permanent: true +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "policy-nexus.fullname" . }}-http + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.middlewares: {{ printf "%s-%s-https-redirect@kubernetescrd" .Release.Namespace (include "policy-nexus.fullname" .) | quote }} +spec: + ingressClassName: traefik + rules: + - host: {{ .Values.site.hostname | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "policy-nexus.fullname" . }} + port: + name: http +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "policy-nexus.fullname" . }}-https + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} + annotations: + cert-manager.io/cluster-issuer: {{ .Values.tls.clusterIssuer | quote }} + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + ingressClassName: traefik + tls: + - hosts: + - {{ .Values.site.hostname | quote }} + secretName: {{ .Values.tls.secretName }} + rules: + - host: {{ .Values.site.hostname | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "policy-nexus.fullname" . }} + port: + name: http diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/networkpolicy.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/networkpolicy.yaml new file mode 100644 index 0000000..a6fce11 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/networkpolicy.yaml @@ -0,0 +1,59 @@ +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "policy-nexus.fullname" . }}-default-deny + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} +spec: + podSelector: {} + policyTypes: + - Ingress + - Egress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "policy-nexus.fullname" . }}-traefik + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "policy-nexus.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - port: 8080 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "policy-nexus.fullname" . }}-acme-solver + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + acme.cert-manager.io/http01-solver: "true" + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - port: 8089 + protocol: TCP diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/service.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/service.yaml new file mode 100644 index 0000000..492fab2 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "policy-nexus.fullname" . }} + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} +spec: + type: ClusterIP + selector: + {{- include "policy-nexus.selectorLabels" . | nindent 4 }} + ports: + - name: http + port: 80 + targetPort: http + protocol: TCP diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/serviceaccount.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/serviceaccount.yaml new file mode 100644 index 0000000..50ad7d9 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "policy-nexus.fullname" . }} + labels: + {{- include "policy-nexus.labels" . | nindent 4 }} +automountServiceAccountToken: false diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/chart/values.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/values.yaml new file mode 100644 index 0000000..d94ccc8 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/chart/values.yaml @@ -0,0 +1,27 @@ +replicaCount: 1 + +image: + repository: forgejo.coulomb.social/coulomb/policy-nexus + digest: "" + pullPolicy: IfNotPresent + +publicationManifestDigest: "" +sourceInventoryDigest: "" +sourceSetDigest: "" + +site: + hostname: policy.coulomb.social + +tls: + clusterIssuer: letsencrypt-prod + secretName: policy-coulomb-social-tls + +resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 100m + memory: 64Mi + +podAnnotations: {} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/headroom-recipe.py b/docs/changes/CUST-WP-0079/policy-publication-r1/headroom-recipe.py new file mode 100644 index 0000000..f5f825a --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/headroom-recipe.py @@ -0,0 +1,13 @@ +import subprocess,json,os,re,datetime +env=dict(os.environ,KUBECONFIG='/etc/rancher/k3s/k3s.yaml') +try: + p=subprocess.run(['kubectl','describe','nodes'],capture_output=True,text=True,env=env,timeout=20) + if p.returncode:raise ValueError() + block=p.stdout.split('Allocated resources:',1)[1].split('Events:',1)[0] + values={} + for kind in ['cpu','memory']: + m=re.search(r'^\s*'+kind+r'\s+(\S+)\s+\((\d+)%\)\s+(\S+)\s+\((\d+)%\)',block,re.M) + if not m:raise ValueError() + values[kind]={'requests':m[1],'requests_percent':int(m[2]),'limits':m[3],'limits_percent':int(m[4])} + print(json.dumps({'capture_utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'allocated_resources':values,'raw_output_suppressed':True})) +except Exception:print(json.dumps({'headroom_observed':False,'raw_errors_suppressed':True})) diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/headroom.json b/docs/changes/CUST-WP-0079/policy-publication-r1/headroom.json new file mode 100644 index 0000000..27bac26 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/headroom.json @@ -0,0 +1,18 @@ +{ + "capture_utc": "2026-10-19T13:19:05.475265+00:00", + "allocated_resources": { + "cpu": { + "requests": "3605m", + "requests_percent": 90, + "limits": "37500m", + "limits_percent": 937 + }, + "memory": { + "requests": "9856Mi", + "requests_percent": 61, + "limits": "34562Mi", + "limits_percent": 216 + } + }, + "raw_output_suppressed": true +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/live-observation.json b/docs/changes/CUST-WP-0079/policy-publication-r1/live-observation.json new file mode 100644 index 0000000..bcb69ac --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/live-observation.json @@ -0,0 +1,19 @@ +{ + "capture_utc": "2026-10-19T13:16:46.645924+00:00", + "cluster_mutated": false, + "expected_node_ip": "92.205.62.239", + "expected_node_ip_present": true, + "helm_revision": 9, + "helm_status": "deployed", + "image_matches_rollback": true, + "machine_id_sha256": "fe7367a60951922122af7ba18ed2cde65c7e0a232bbedfb045cb575de2094c2f", + "ready_replicas": 1, + "release_pin_matches": { + "publication-manifest-digest": true, + "source-inventory-digest": true, + "source-set-digest": true + }, + "replicas": 1, + "secret_values_observed": false, + "ssh_alias": "railiance01" +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/observe_remote.py b/docs/changes/CUST-WP-0079/policy-publication-r1/observe_remote.py new file mode 100644 index 0000000..739c589 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/observe_remote.py @@ -0,0 +1,31 @@ +import datetime,hashlib,json,os,pathlib,re,subprocess +EXPECTED={ + 'image':'forgejo.coulomb.social/coulomb/policy-nexus@sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06', + 'publication-manifest-digest':'ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a', + 'source-inventory-digest':'40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5', + 'source-set-digest':'15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256'} +def run(args): + p=subprocess.run(args,stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=dict(os.environ,KUBECONFIG='/etc/rancher/k3s/k3s.yaml'),timeout=20) + if p.returncode:raise ValueError('command_refused') + return p.stdout.decode().strip() +try: + out={'capture_utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'ssh_alias':'railiance01','expected_node_ip':'92.205.62.239','secret_values_observed':False,'cluster_mutated':False} + nodes=json.loads(run(['kubectl','get','nodes','-o','json'])) + out['expected_node_ip_present']=any(a.get('address')=='92.205.62.239' for n in nodes['items'] for a in n['status']['addresses']) + if not out['expected_node_ip_present']:raise ValueError('target_mismatch') + out['machine_id_sha256']=hashlib.sha256(pathlib.Path('/etc/machine-id').read_bytes()).hexdigest() + base=['kubectl','-n','policy-nexus','get','deployment','policy-nexus','-o'] + actual=run(base+['jsonpath={.spec.template.spec.containers[0].image}']) + out['image_matches_rollback']=actual==EXPECTED['image'] + out['release_pin_matches']={} + for key in list(EXPECTED)[1:]: + value=run(base+['jsonpath={.metadata.annotations.policy\\.coulomb\\.social/'+key+'}']) + out['release_pin_matches'][key]=value==EXPECTED[key] + for key,expr in [('replicas','.spec.replicas'),('ready_replicas','.status.readyReplicas')]: + value=run(base+['jsonpath={'+expr+'}']);out[key]=int(value) if value.isdigit() else None + releases=json.loads(run(['helm','list','--namespace','policy-nexus','--filter','^policy-nexus$','-o','json'])) + if len(releases)!=1:raise ValueError('release_count') + r=releases[0];out['helm_revision']=int(r['revision']);out['helm_status']=r['status'] if r['status'] in ['deployed','failed','pending-upgrade','pending-rollback'] else 'other' + print(json.dumps(out,sort_keys=True)) +except Exception: + print(json.dumps({'observation_completed':False,'reason':'bounded_read_failed','raw_errors_suppressed':True})) diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/pending-binding-check.json b/docs/changes/CUST-WP-0079/policy-publication-r1/pending-binding-check.json new file mode 100644 index 0000000..7727477 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/pending-binding-check.json @@ -0,0 +1,4 @@ +{ + "candidate_rejected_while_unapproved": true, + "returncode": 2 +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/railiance-apps-rollback.patch b/docs/changes/CUST-WP-0079/policy-publication-r1/railiance-apps-rollback.patch new file mode 100644 index 0000000..175640a --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/railiance-apps-rollback.patch @@ -0,0 +1,64 @@ +--- a/bindings/policy-nexus-production.json ++++ b/bindings/policy-nexus-production.json +@@ -1,7 +1,7 @@ + { + "schema_version": "policy-nexus-production-binding/v1", +- "status": "release-proposed", +- "approved_on": null, ++ "status": "release-approved", ++ "approved_on": "2026-10-11", + "rapp_repo": "rapp-policy-nexus", + "reef": "reef-railiance", + "rail": "rail-kubernetes", +@@ -9,15 +9,15 @@ + "release": "policy-nexus", + "hostname": "policy.coulomb.social", + "image_repository": "forgejo.coulomb.social/coulomb/policy-nexus", +- "image_digest": "sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1", +- "publication_manifest_digest": "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e", +- "source_inventory_digest": "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd", +- "source_set_digest": "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682", ++ "image_digest": "sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06", ++ "publication_manifest_digest": "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a", ++ "source_inventory_digest": "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5", ++ "source_set_digest": "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256", + "residual_risk_owner": "the-custodian", +- "proposal_id": "POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1", +- "publication_source_revision": "9fabcce1cb4c83165bcaba8be58d76788b4d87a1", +- "source_lock_digest": "c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529", +- "approval_ref": null, +- "verified_helm_revision": null, +- "native_verification_ref": null ++ "proposal_id": "POLICY-PUB-20261011-SECURITY-LAYER-V08-R1", ++ "publication_source_revision": "b64a0c52ec1ea8d1efa99dd7f870e580d7c60df8", ++ "source_lock_digest": "99c695f46a54ead4cfe8f560f3648bf4db19404fe198b156c740115c97d3ed40", ++ "approval_ref": "informed-decision:infd-20261011-policy-nexus-hosting-r1@1; approval:52a3c479-2cb1-4074-abec-6a88117ad596", ++ "verified_helm_revision": 9, ++ "native_verification_ref": "rapp-policy-nexus/docs/evidence/2026-10-11-security-layer-v08-native-hosting/" + } +--- a/values/policy-nexus-production.yaml ++++ b/values/policy-nexus-production.yaml +@@ -1,6 +1,6 @@ + image: + repository: forgejo.coulomb.social/coulomb/policy-nexus +- digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 +-publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e +-sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd +-sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 ++ digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 ++publicationManifestDigest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a ++sourceInventoryDigest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 ++sourceSetDigest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 +--- a/values/policy-nexus-production-candidate.yaml ++++ b/values/policy-nexus-production-candidate.yaml +@@ -1,6 +1,6 @@ + image: + repository: forgejo.coulomb.social/coulomb/policy-nexus +- digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 +-publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e +-sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd +-sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 ++ digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 ++publicationManifestDigest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a ++sourceInventoryDigest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 ++sourceSetDigest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/railiance-apps.patch b/docs/changes/CUST-WP-0079/policy-publication-r1/railiance-apps.patch new file mode 100644 index 0000000..6192975 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/railiance-apps.patch @@ -0,0 +1,64 @@ +--- a/bindings/policy-nexus-production.json ++++ b/bindings/policy-nexus-production.json +@@ -1,7 +1,7 @@ + { + "schema_version": "policy-nexus-production-binding/v1", +- "status": "release-approved", +- "approved_on": "2026-10-11", ++ "status": "release-proposed", ++ "approved_on": null, + "rapp_repo": "rapp-policy-nexus", + "reef": "reef-railiance", + "rail": "rail-kubernetes", +@@ -9,15 +9,15 @@ + "release": "policy-nexus", + "hostname": "policy.coulomb.social", + "image_repository": "forgejo.coulomb.social/coulomb/policy-nexus", +- "image_digest": "sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06", +- "publication_manifest_digest": "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a", +- "source_inventory_digest": "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5", +- "source_set_digest": "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256", ++ "image_digest": "sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1", ++ "publication_manifest_digest": "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e", ++ "source_inventory_digest": "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd", ++ "source_set_digest": "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682", + "residual_risk_owner": "the-custodian", +- "proposal_id": "POLICY-PUB-20261011-SECURITY-LAYER-V08-R1", +- "publication_source_revision": "b64a0c52ec1ea8d1efa99dd7f870e580d7c60df8", +- "source_lock_digest": "99c695f46a54ead4cfe8f560f3648bf4db19404fe198b156c740115c97d3ed40", +- "approval_ref": "informed-decision:infd-20261011-policy-nexus-hosting-r1@1; approval:52a3c479-2cb1-4074-abec-6a88117ad596", +- "verified_helm_revision": 9, +- "native_verification_ref": "rapp-policy-nexus/docs/evidence/2026-10-11-security-layer-v08-native-hosting/" ++ "proposal_id": "POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1", ++ "publication_source_revision": "9fabcce1cb4c83165bcaba8be58d76788b4d87a1", ++ "source_lock_digest": "c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529", ++ "approval_ref": null, ++ "verified_helm_revision": null, ++ "native_verification_ref": null + } +--- a/values/policy-nexus-production.yaml ++++ b/values/policy-nexus-production.yaml +@@ -1,6 +1,6 @@ + image: + repository: forgejo.coulomb.social/coulomb/policy-nexus +- digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 +-publicationManifestDigest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a +-sourceInventoryDigest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 +-sourceSetDigest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 ++ digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 ++publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e ++sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd ++sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 +--- a/values/policy-nexus-production-candidate.yaml ++++ b/values/policy-nexus-production-candidate.yaml +@@ -1,6 +1,6 @@ + image: + repository: forgejo.coulomb.social/coulomb/policy-nexus +- digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 +-publicationManifestDigest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a +-sourceInventoryDigest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 +-sourceSetDigest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 ++ digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 ++publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e ++sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd ++sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rapp-policy-nexus-rollback.patch b/docs/changes/CUST-WP-0079/policy-publication-r1/rapp-policy-nexus-rollback.patch new file mode 100644 index 0000000..c4a4681 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rapp-policy-nexus-rollback.patch @@ -0,0 +1,23 @@ +--- a/bindings/reef-railiance.yaml ++++ b/bindings/reef-railiance.yaml +@@ -9,12 +9,12 @@ + hostname: policy.coulomb.social + cluster_issuer: letsencrypt-prod + image_repository: forgejo.coulomb.social/coulomb/policy-nexus +-image_digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 +-publication_manifest_digest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e +-source_inventory_digest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd +-source_set_digest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 ++image_digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 ++publication_manifest_digest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a ++source_inventory_digest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 ++source_set_digest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 + residual_risk_owner: the-custodian +-release_status: proposed +-release_proposal_id: POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1 +-release_approval_ref: null +-source_lock_digest: c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529 ++release_status: release-approved ++release_proposal_id: POLICY-PUB-20261011-SECURITY-LAYER-V08-R1 ++release_approval_ref: "informed-decision:infd-20261011-policy-nexus-hosting-r1@1; approval:52a3c479-2cb1-4074-abec-6a88117ad596" ++source_lock_digest: 99c695f46a54ead4cfe8f560f3648bf4db19404fe198b156c740115c97d3ed40 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rapp-policy-nexus.patch b/docs/changes/CUST-WP-0079/policy-publication-r1/rapp-policy-nexus.patch new file mode 100644 index 0000000..08ad50f --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rapp-policy-nexus.patch @@ -0,0 +1,19 @@ +--- a/bindings/reef-railiance.yaml ++++ b/bindings/reef-railiance.yaml +@@ -9,8 +9,12 @@ + hostname: policy.coulomb.social + cluster_issuer: letsencrypt-prod + image_repository: forgejo.coulomb.social/coulomb/policy-nexus +-image_digest: sha256:23df0ab3dc80d2a92b8058eeb572c222ceb05d17434f173a24142b2450ab3cea +-publication_manifest_digest: 09f9f7edcc46e31d4b3f73b62d16fdf17808ae1f893f312242b7b9e2037319e0 +-source_inventory_digest: 9658803bc79d19cef1a9c842d1a8c161f1998d59ce6e4bc4df3c88aba2f4c9c4 +-source_set_digest: 03f04902a3559099433795453829d75470aa1490dd243b42e7703b6eab87772f ++image_digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1 ++publication_manifest_digest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e ++source_inventory_digest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd ++source_set_digest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682 + residual_risk_owner: the-custodian ++release_status: proposed ++release_proposal_id: POLICY-PUB-20261019-BUILD-MODE-GUARDRAIL-R1 ++release_approval_ref: null ++source_lock_digest: c150c6c0745441b4b69884ecc6cf55e97db26080fcf4c2224775b1f755580529 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/render-verification.json b/docs/changes/CUST-WP-0079/policy-publication-r1/render-verification.json new file mode 100644 index 0000000..b451770 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/render-verification.json @@ -0,0 +1,18 @@ +{ + "rendered_resources": 9, + "changed_paths": [ + "Deployment/policy-nexus/metadata/annotations/policy.coulomb.social/publication-manifest-digest", + "Deployment/policy-nexus/metadata/annotations/policy.coulomb.social/source-inventory-digest", + "Deployment/policy-nexus/metadata/annotations/policy.coulomb.social/source-set-digest", + "Deployment/policy-nexus/spec/template/metadata/annotations/policy.coulomb.social/publication-manifest-digest", + "Deployment/policy-nexus/spec/template/metadata/annotations/policy.coulomb.social/source-inventory-digest", + "Deployment/policy-nexus/spec/template/metadata/annotations/policy.coulomb.social/source-set-digest", + "Deployment/policy-nexus/spec/template/spec/containers/0/image" + ], + "other_resources_unchanged": true, + "replicas_changed": false, + "resource_requests_changed": false, + "network_exposure_changed": false, + "rbac_changed": false, + "approval_pending": true +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rendered.diff b/docs/changes/CUST-WP-0079/policy-publication-r1/rendered.diff new file mode 100644 index 0000000..f7ffb56 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rendered.diff @@ -0,0 +1,37 @@ +--- rollback-rendered.yaml ++++ candidate-rendered.yaml +@@ -122,9 +122,9 @@ + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: +- policy.coulomb.social/publication-manifest-digest: "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a" +- policy.coulomb.social/source-inventory-digest: "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5" +- policy.coulomb.social/source-set-digest: "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256" ++ policy.coulomb.social/publication-manifest-digest: "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e" ++ policy.coulomb.social/source-inventory-digest: "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd" ++ policy.coulomb.social/source-set-digest: "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682" + spec: + replicas: 1 + revisionHistoryLimit: 10 +@@ -143,9 +143,9 @@ + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + annotations: +- policy.coulomb.social/publication-manifest-digest: "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a" +- policy.coulomb.social/source-inventory-digest: "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5" +- policy.coulomb.social/source-set-digest: "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256" ++ policy.coulomb.social/publication-manifest-digest: "8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e" ++ policy.coulomb.social/source-inventory-digest: "e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd" ++ policy.coulomb.social/source-set-digest: "b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682" + spec: + serviceAccountName: policy-nexus + automountServiceAccountToken: false +@@ -159,7 +159,7 @@ + type: RuntimeDefault + containers: + - name: policy-nexus +- image: "forgejo.coulomb.social/coulomb/policy-nexus@sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06" ++ image: "forgejo.coulomb.social/coulomb/policy-nexus@sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1" + imagePullPolicy: IfNotPresent + securityContext: + allowPrivilegeEscalation: false diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-binding.json b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-binding.json new file mode 100644 index 0000000..3fddec0 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-binding.json @@ -0,0 +1,23 @@ +{ + "schema_version": "policy-nexus-production-binding/v1", + "status": "release-approved", + "approved_on": "2026-10-11", + "rapp_repo": "rapp-policy-nexus", + "reef": "reef-railiance", + "rail": "rail-kubernetes", + "namespace": "policy-nexus", + "release": "policy-nexus", + "hostname": "policy.coulomb.social", + "image_repository": "forgejo.coulomb.social/coulomb/policy-nexus", + "image_digest": "sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06", + "publication_manifest_digest": "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a", + "source_inventory_digest": "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5", + "source_set_digest": "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256", + "residual_risk_owner": "the-custodian", + "proposal_id": "POLICY-PUB-20261011-SECURITY-LAYER-V08-R1", + "publication_source_revision": "b64a0c52ec1ea8d1efa99dd7f870e580d7c60df8", + "source_lock_digest": "99c695f46a54ead4cfe8f560f3648bf4db19404fe198b156c740115c97d3ed40", + "approval_ref": "informed-decision:infd-20261011-policy-nexus-hosting-r1@1; approval:52a3c479-2cb1-4074-abec-6a88117ad596", + "verified_helm_revision": 9, + "native_verification_ref": "rapp-policy-nexus/docs/evidence/2026-10-11-security-layer-v08-native-hosting/" +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-rapp-binding.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-rapp-binding.yaml new file mode 100644 index 0000000..51e603f --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-rapp-binding.yaml @@ -0,0 +1,20 @@ +schema_version: rapp-binding/v1 +rapp_id: rapp-policy-nexus +reef_id: reef-railiance +rail_id: rail-kubernetes +admission: production-approved +approved_on: "2026-09-01" +namespace: policy-nexus +release: policy-nexus +hostname: policy.coulomb.social +cluster_issuer: letsencrypt-prod +image_repository: forgejo.coulomb.social/coulomb/policy-nexus +image_digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 +publication_manifest_digest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a +source_inventory_digest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 +source_set_digest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 +residual_risk_owner: the-custodian +release_status: release-approved +release_proposal_id: POLICY-PUB-20261011-SECURITY-LAYER-V08-R1 +release_approval_ref: "informed-decision:infd-20261011-policy-nexus-hosting-r1@1; approval:52a3c479-2cb1-4074-abec-6a88117ad596" +source_lock_digest: 99c695f46a54ead4cfe8f560f3648bf4db19404fe198b156c740115c97d3ed40 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-rendered.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-rendered.yaml new file mode 100644 index 0000000..733f7eb --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-rendered.yaml @@ -0,0 +1,280 @@ +--- +# Source: policy-nexus/templates/networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: policy-nexus-default-deny + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + podSelector: {} + policyTypes: + - Ingress + - Egress +--- +# Source: policy-nexus/templates/networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: policy-nexus-traefik + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - port: 8080 + protocol: TCP +--- +# Source: policy-nexus/templates/networkpolicy.yaml +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: policy-nexus-acme-solver + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + podSelector: + matchLabels: + acme.cert-manager.io/http01-solver: "true" + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: kube-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + ports: + - port: 8089 + protocol: TCP +--- +# Source: policy-nexus/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: policy-nexus + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +automountServiceAccountToken: false +--- +# Source: policy-nexus/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: policy-nexus + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + ports: + - name: http + port: 80 + targetPort: http + protocol: TCP +--- +# Source: policy-nexus/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: policy-nexus + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: + policy.coulomb.social/publication-manifest-digest: "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a" + policy.coulomb.social/source-inventory-digest: "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5" + policy.coulomb.social/source-set-digest: "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256" +spec: + replicas: 1 + revisionHistoryLimit: 10 + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + selector: + matchLabels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + template: + metadata: + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + annotations: + policy.coulomb.social/publication-manifest-digest: "ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a" + policy.coulomb.social/source-inventory-digest: "40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5" + policy.coulomb.social/source-set-digest: "15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256" + spec: + serviceAccountName: policy-nexus + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + runAsUser: 101 + runAsGroup: 101 + fsGroup: 101 + seccompProfile: + type: RuntimeDefault + containers: + - name: policy-nexus + image: "forgejo.coulomb.social/coulomb/policy-nexus@sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06" + imagePullPolicy: IfNotPresent + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + ports: + - name: http + containerPort: 8080 + protocol: TCP + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 2 + periodSeconds: 5 + timeoutSeconds: 2 + failureThreshold: 3 + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 2 + failureThreshold: 3 + resources: + limits: + cpu: 100m + memory: 64Mi + requests: + cpu: 10m + memory: 32Mi + volumeMounts: + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: + sizeLimit: 16Mi +--- +# Source: policy-nexus/templates/ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: policy-nexus-http + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.middlewares: "policy-nexus-policy-nexus-https-redirect@kubernetescrd" +spec: + ingressClassName: traefik + rules: + - host: "policy.coulomb.social" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: policy-nexus + port: + name: http +--- +# Source: policy-nexus/templates/ingress.yaml +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: policy-nexus-https + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + ingressClassName: traefik + tls: + - hosts: + - "policy.coulomb.social" + secretName: policy-coulomb-social-tls + rules: + - host: "policy.coulomb.social" + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: policy-nexus + port: + name: http +--- +# Source: policy-nexus/templates/ingress.yaml +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: policy-nexus-https-redirect + labels: + app.kubernetes.io/name: policy-nexus + app.kubernetes.io/instance: policy-nexus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: "0.2.0" + helm.sh/chart: policy-nexus-0.2.0 +spec: + redirectScheme: + scheme: https + permanent: true diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-values.yaml b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-values.yaml new file mode 100644 index 0000000..7261bcc --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/rollback-values.yaml @@ -0,0 +1,6 @@ +image: + repository: forgejo.coulomb.social/coulomb/policy-nexus + digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06 +publicationManifestDigest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a +sourceInventoryDigest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5 +sourceSetDigest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256 diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/server-dry-run-recipe.py b/docs/changes/CUST-WP-0079/policy-publication-r1/server-dry-run-recipe.py new file mode 100644 index 0000000..49cfd3d --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/server-dry-run-recipe.py @@ -0,0 +1,6 @@ +import base64,subprocess,os,json,datetime +manifest=base64.b64decode('LS0tCiMgU291cmNlOiBwb2xpY3ktbmV4dXMvdGVtcGxhdGVzL25ldHdvcmtwb2xpY3kueWFtbAphcGlWZXJzaW9uOiBuZXR3b3JraW5nLms4cy5pby92MQpraW5kOiBOZXR3b3JrUG9saWN5Cm1ldGFkYXRhOgogIG5hbWU6IHBvbGljeS1uZXh1cy1kZWZhdWx0LWRlbnkKICBsYWJlbHM6CiAgICBhcHAua3ViZXJuZXRlcy5pby9uYW1lOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL2luc3RhbmNlOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnk6IEhlbG0KICAgIGFwcC5rdWJlcm5ldGVzLmlvL3ZlcnNpb246ICIwLjIuMCIKICAgIGhlbG0uc2gvY2hhcnQ6IHBvbGljeS1uZXh1cy0wLjIuMApzcGVjOgogIHBvZFNlbGVjdG9yOiB7fQogIHBvbGljeVR5cGVzOgogICAgLSBJbmdyZXNzCiAgICAtIEVncmVzcwotLS0KIyBTb3VyY2U6IHBvbGljeS1uZXh1cy90ZW1wbGF0ZXMvbmV0d29ya3BvbGljeS55YW1sCmFwaVZlcnNpb246IG5ldHdvcmtpbmcuazhzLmlvL3YxCmtpbmQ6IE5ldHdvcmtQb2xpY3kKbWV0YWRhdGE6CiAgbmFtZTogcG9saWN5LW5leHVzLXRyYWVmaWsKICBsYWJlbHM6CiAgICBhcHAua3ViZXJuZXRlcy5pby9uYW1lOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL2luc3RhbmNlOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnk6IEhlbG0KICAgIGFwcC5rdWJlcm5ldGVzLmlvL3ZlcnNpb246ICIwLjIuMCIKICAgIGhlbG0uc2gvY2hhcnQ6IHBvbGljeS1uZXh1cy0wLjIuMApzcGVjOgogIHBvZFNlbGVjdG9yOgogICAgbWF0Y2hMYWJlbHM6CiAgICAgIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU6IHBvbGljeS1uZXh1cwogICAgICBhcHAua3ViZXJuZXRlcy5pby9pbnN0YW5jZTogcG9saWN5LW5leHVzCiAgcG9saWN5VHlwZXM6CiAgICAtIEluZ3Jlc3MKICBpbmdyZXNzOgogICAgLSBmcm9tOgogICAgICAgIC0gbmFtZXNwYWNlU2VsZWN0b3I6CiAgICAgICAgICAgIG1hdGNoTGFiZWxzOgogICAgICAgICAgICAgIGt1YmVybmV0ZXMuaW8vbWV0YWRhdGEubmFtZToga3ViZS1zeXN0ZW0KICAgICAgICAgIHBvZFNlbGVjdG9yOgogICAgICAgICAgICBtYXRjaExhYmVsczoKICAgICAgICAgICAgICBhcHAua3ViZXJuZXRlcy5pby9uYW1lOiB0cmFlZmlrCiAgICAgIHBvcnRzOgogICAgICAgIC0gcG9ydDogODA4MAogICAgICAgICAgcHJvdG9jb2w6IFRDUAotLS0KIyBTb3VyY2U6IHBvbGljeS1uZXh1cy90ZW1wbGF0ZXMvbmV0d29ya3BvbGljeS55YW1sCmFwaVZlcnNpb246IG5ldHdvcmtpbmcuazhzLmlvL3YxCmtpbmQ6IE5ldHdvcmtQb2xpY3kKbWV0YWRhdGE6CiAgbmFtZTogcG9saWN5LW5leHVzLWFjbWUtc29sdmVyCiAgbGFiZWxzOgogICAgYXBwLmt1YmVybmV0ZXMuaW8vbmFtZTogcG9saWN5LW5leHVzCiAgICBhcHAua3ViZXJuZXRlcy5pby9pbnN0YW5jZTogcG9saWN5LW5leHVzCiAgICBhcHAua3ViZXJuZXRlcy5pby9tYW5hZ2VkLWJ5OiBIZWxtCiAgICBhcHAua3ViZXJuZXRlcy5pby92ZXJzaW9uOiAiMC4yLjAiCiAgICBoZWxtLnNoL2NoYXJ0OiBwb2xpY3ktbmV4dXMtMC4yLjAKc3BlYzoKICBwb2RTZWxlY3RvcjoKICAgIG1hdGNoTGFiZWxzOgogICAgICBhY21lLmNlcnQtbWFuYWdlci5pby9odHRwMDEtc29sdmVyOiAidHJ1ZSIKICBwb2xpY3lUeXBlczoKICAgIC0gSW5ncmVzcwogIGluZ3Jlc3M6CiAgICAtIGZyb206CiAgICAgICAgLSBuYW1lc3BhY2VTZWxlY3RvcjoKICAgICAgICAgICAgbWF0Y2hMYWJlbHM6CiAgICAgICAgICAgICAga3ViZXJuZXRlcy5pby9tZXRhZGF0YS5uYW1lOiBrdWJlLXN5c3RlbQogICAgICAgICAgcG9kU2VsZWN0b3I6CiAgICAgICAgICAgIG1hdGNoTGFiZWxzOgogICAgICAgICAgICAgIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU6IHRyYWVmaWsKICAgICAgcG9ydHM6CiAgICAgICAgLSBwb3J0OiA4MDg5CiAgICAgICAgICBwcm90b2NvbDogVENQCi0tLQojIFNvdXJjZTogcG9saWN5LW5leHVzL3RlbXBsYXRlcy9zZXJ2aWNlYWNjb3VudC55YW1sCmFwaVZlcnNpb246IHYxCmtpbmQ6IFNlcnZpY2VBY2NvdW50Cm1ldGFkYXRhOgogIG5hbWU6IHBvbGljeS1uZXh1cwogIGxhYmVsczoKICAgIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU6IHBvbGljeS1uZXh1cwogICAgYXBwLmt1YmVybmV0ZXMuaW8vaW5zdGFuY2U6IHBvbGljeS1uZXh1cwogICAgYXBwLmt1YmVybmV0ZXMuaW8vbWFuYWdlZC1ieTogSGVsbQogICAgYXBwLmt1YmVybmV0ZXMuaW8vdmVyc2lvbjogIjAuMi4wIgogICAgaGVsbS5zaC9jaGFydDogcG9saWN5LW5leHVzLTAuMi4wCmF1dG9tb3VudFNlcnZpY2VBY2NvdW50VG9rZW46IGZhbHNlCi0tLQojIFNvdXJjZTogcG9saWN5LW5leHVzL3RlbXBsYXRlcy9zZXJ2aWNlLnlhbWwKYXBpVmVyc2lvbjogdjEKa2luZDogU2VydmljZQptZXRhZGF0YToKICBuYW1lOiBwb2xpY3ktbmV4dXMKICBsYWJlbHM6CiAgICBhcHAua3ViZXJuZXRlcy5pby9uYW1lOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL2luc3RhbmNlOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnk6IEhlbG0KICAgIGFwcC5rdWJlcm5ldGVzLmlvL3ZlcnNpb246ICIwLjIuMCIKICAgIGhlbG0uc2gvY2hhcnQ6IHBvbGljeS1uZXh1cy0wLjIuMApzcGVjOgogIHR5cGU6IENsdXN0ZXJJUAogIHNlbGVjdG9yOgogICAgYXBwLmt1YmVybmV0ZXMuaW8vbmFtZTogcG9saWN5LW5leHVzCiAgICBhcHAua3ViZXJuZXRlcy5pby9pbnN0YW5jZTogcG9saWN5LW5leHVzCiAgcG9ydHM6CiAgICAtIG5hbWU6IGh0dHAKICAgICAgcG9ydDogODAKICAgICAgdGFyZ2V0UG9ydDogaHR0cAogICAgICBwcm90b2NvbDogVENQCi0tLQojIFNvdXJjZTogcG9saWN5LW5leHVzL3RlbXBsYXRlcy9kZXBsb3ltZW50LnlhbWwKYXBpVmVyc2lvbjogYXBwcy92MQpraW5kOiBEZXBsb3ltZW50Cm1ldGFkYXRhOgogIG5hbWU6IHBvbGljeS1uZXh1cwogIGxhYmVsczoKICAgIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU6IHBvbGljeS1uZXh1cwogICAgYXBwLmt1YmVybmV0ZXMuaW8vaW5zdGFuY2U6IHBvbGljeS1uZXh1cwogICAgYXBwLmt1YmVybmV0ZXMuaW8vbWFuYWdlZC1ieTogSGVsbQogICAgYXBwLmt1YmVybmV0ZXMuaW8vdmVyc2lvbjogIjAuMi4wIgogICAgaGVsbS5zaC9jaGFydDogcG9saWN5LW5leHVzLTAuMi4wCiAgYW5ub3RhdGlvbnM6CiAgICBwb2xpY3kuY291bG9tYi5zb2NpYWwvcHVibGljYXRpb24tbWFuaWZlc3QtZGlnZXN0OiAiOGM3NGI0ZTQxNGY3NzYwNDI5NjAwYjdiYTBiMzYyN2ZjZmU0Mzg0MTdiZmU2Njk1ZjU1YWNmYTY5MDVkMzUyZSIKICAgIHBvbGljeS5jb3Vsb21iLnNvY2lhbC9zb3VyY2UtaW52ZW50b3J5LWRpZ2VzdDogImU4NDQ1M2I2YjQxMWE3ZDY2ZDJiNWVmYmYwODNjZDAwMzM0NDFkNmIxMjk4MzMyNjQ0MjkzM2RhODdiZjYxZmQiCiAgICBwb2xpY3kuY291bG9tYi5zb2NpYWwvc291cmNlLXNldC1kaWdlc3Q6ICJiMDA1MzUwNjNjNTZlZGUwOGYwYTI5MmIzMDFhNDdhZGQxOGJmNzBmODE5MDRiZjNmNDM0YzhmYWE1ZWJlNjgyIgpzcGVjOgogIHJlcGxpY2FzOiAxCiAgcmV2aXNpb25IaXN0b3J5TGltaXQ6IDEwCiAgc3RyYXRlZ3k6CiAgICB0eXBlOiBSb2xsaW5nVXBkYXRlCiAgICByb2xsaW5nVXBkYXRlOgogICAgICBtYXhVbmF2YWlsYWJsZTogMAogICAgICBtYXhTdXJnZTogMQogIHNlbGVjdG9yOgogICAgbWF0Y2hMYWJlbHM6CiAgICAgIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU6IHBvbGljeS1uZXh1cwogICAgICBhcHAua3ViZXJuZXRlcy5pby9pbnN0YW5jZTogcG9saWN5LW5leHVzCiAgdGVtcGxhdGU6CiAgICBtZXRhZGF0YToKICAgICAgbGFiZWxzOgogICAgICAgIGFwcC5rdWJlcm5ldGVzLmlvL25hbWU6IHBvbGljeS1uZXh1cwogICAgICAgIGFwcC5rdWJlcm5ldGVzLmlvL2luc3RhbmNlOiBwb2xpY3ktbmV4dXMKICAgICAgYW5ub3RhdGlvbnM6CiAgICAgICAgcG9saWN5LmNvdWxvbWIuc29jaWFsL3B1YmxpY2F0aW9uLW1hbmlmZXN0LWRpZ2VzdDogIjhjNzRiNGU0MTRmNzc2MDQyOTYwMGI3YmEwYjM2MjdmY2ZlNDM4NDE3YmZlNjY5NWY1NWFjZmE2OTA1ZDM1MmUiCiAgICAgICAgcG9saWN5LmNvdWxvbWIuc29jaWFsL3NvdXJjZS1pbnZlbnRvcnktZGlnZXN0OiAiZTg0NDUzYjZiNDExYTdkNjZkMmI1ZWZiZjA4M2NkMDAzMzQ0MWQ2YjEyOTgzMzI2NDQyOTMzZGE4N2JmNjFmZCIKICAgICAgICBwb2xpY3kuY291bG9tYi5zb2NpYWwvc291cmNlLXNldC1kaWdlc3Q6ICJiMDA1MzUwNjNjNTZlZGUwOGYwYTI5MmIzMDFhNDdhZGQxOGJmNzBmODE5MDRiZjNmNDM0YzhmYWE1ZWJlNjgyIgogICAgc3BlYzoKICAgICAgc2VydmljZUFjY291bnROYW1lOiBwb2xpY3ktbmV4dXMKICAgICAgYXV0b21vdW50U2VydmljZUFjY291bnRUb2tlbjogZmFsc2UKICAgICAgZW5hYmxlU2VydmljZUxpbmtzOiBmYWxzZQogICAgICBzZWN1cml0eUNvbnRleHQ6CiAgICAgICAgcnVuQXNOb25Sb290OiB0cnVlCiAgICAgICAgcnVuQXNVc2VyOiAxMDEKICAgICAgICBydW5Bc0dyb3VwOiAxMDEKICAgICAgICBmc0dyb3VwOiAxMDEKICAgICAgICBzZWNjb21wUHJvZmlsZToKICAgICAgICAgIHR5cGU6IFJ1bnRpbWVEZWZhdWx0CiAgICAgIGNvbnRhaW5lcnM6CiAgICAgICAgLSBuYW1lOiBwb2xpY3ktbmV4dXMKICAgICAgICAgIGltYWdlOiAiZm9yZ2Vqby5jb3Vsb21iLnNvY2lhbC9jb3Vsb21iL3BvbGljeS1uZXh1c0BzaGEyNTY6MjE0YjEyMmMzZDE3NTU2M2YxMTQ1NTJmYTE4MjZkYWM5NjQyNDMzYmUwMTljNzM2YzMyNjVkMGEzZWYzNzlmMSIKICAgICAgICAgIGltYWdlUHVsbFBvbGljeTogSWZOb3RQcmVzZW50CiAgICAgICAgICBzZWN1cml0eUNvbnRleHQ6CiAgICAgICAgICAgIGFsbG93UHJpdmlsZWdlRXNjYWxhdGlvbjogZmFsc2UKICAgICAgICAgICAgcmVhZE9ubHlSb290RmlsZXN5c3RlbTogdHJ1ZQogICAgICAgICAgICBjYXBhYmlsaXRpZXM6CiAgICAgICAgICAgICAgZHJvcDoKICAgICAgICAgICAgICAgIC0gQUxMCiAgICAgICAgICBwb3J0czoKICAgICAgICAgICAgLSBuYW1lOiBodHRwCiAgICAgICAgICAgICAgY29udGFpbmVyUG9ydDogODA4MAogICAgICAgICAgICAgIHByb3RvY29sOiBUQ1AKICAgICAgICAgIHJlYWRpbmVzc1Byb2JlOgogICAgICAgICAgICBodHRwR2V0OgogICAgICAgICAgICAgIHBhdGg6IC9oZWFsdGh6CiAgICAgICAgICAgICAgcG9ydDogaHR0cAogICAgICAgICAgICBpbml0aWFsRGVsYXlTZWNvbmRzOiAyCiAgICAgICAgICAgIHBlcmlvZFNlY29uZHM6IDUKICAgICAgICAgICAgdGltZW91dFNlY29uZHM6IDIKICAgICAgICAgICAgZmFpbHVyZVRocmVzaG9sZDogMwogICAgICAgICAgbGl2ZW5lc3NQcm9iZToKICAgICAgICAgICAgaHR0cEdldDoKICAgICAgICAgICAgICBwYXRoOiAvaGVhbHRoegogICAgICAgICAgICAgIHBvcnQ6IGh0dHAKICAgICAgICAgICAgaW5pdGlhbERlbGF5U2Vjb25kczogMTAKICAgICAgICAgICAgcGVyaW9kU2Vjb25kczogMTAKICAgICAgICAgICAgdGltZW91dFNlY29uZHM6IDIKICAgICAgICAgICAgZmFpbHVyZVRocmVzaG9sZDogMwogICAgICAgICAgcmVzb3VyY2VzOgogICAgICAgICAgICBsaW1pdHM6CiAgICAgICAgICAgICAgY3B1OiAxMDBtCiAgICAgICAgICAgICAgbWVtb3J5OiA2NE1pCiAgICAgICAgICAgIHJlcXVlc3RzOgogICAgICAgICAgICAgIGNwdTogMTBtCiAgICAgICAgICAgICAgbWVtb3J5OiAzMk1pCiAgICAgICAgICB2b2x1bWVNb3VudHM6CiAgICAgICAgICAgIC0gbmFtZTogdG1wCiAgICAgICAgICAgICAgbW91bnRQYXRoOiAvdG1wCiAgICAgIHZvbHVtZXM6CiAgICAgICAgLSBuYW1lOiB0bXAKICAgICAgICAgIGVtcHR5RGlyOgogICAgICAgICAgICBzaXplTGltaXQ6IDE2TWkKLS0tCiMgU291cmNlOiBwb2xpY3ktbmV4dXMvdGVtcGxhdGVzL2luZ3Jlc3MueWFtbAphcGlWZXJzaW9uOiBuZXR3b3JraW5nLms4cy5pby92MQpraW5kOiBJbmdyZXNzCm1ldGFkYXRhOgogIG5hbWU6IHBvbGljeS1uZXh1cy1odHRwCiAgbGFiZWxzOgogICAgYXBwLmt1YmVybmV0ZXMuaW8vbmFtZTogcG9saWN5LW5leHVzCiAgICBhcHAua3ViZXJuZXRlcy5pby9pbnN0YW5jZTogcG9saWN5LW5leHVzCiAgICBhcHAua3ViZXJuZXRlcy5pby9tYW5hZ2VkLWJ5OiBIZWxtCiAgICBhcHAua3ViZXJuZXRlcy5pby92ZXJzaW9uOiAiMC4yLjAiCiAgICBoZWxtLnNoL2NoYXJ0OiBwb2xpY3ktbmV4dXMtMC4yLjAKICBhbm5vdGF0aW9uczoKICAgIHRyYWVmaWsuaW5ncmVzcy5rdWJlcm5ldGVzLmlvL3JvdXRlci5lbnRyeXBvaW50czogd2ViCiAgICB0cmFlZmlrLmluZ3Jlc3Mua3ViZXJuZXRlcy5pby9yb3V0ZXIubWlkZGxld2FyZXM6ICJwb2xpY3ktbmV4dXMtcG9saWN5LW5leHVzLWh0dHBzLXJlZGlyZWN0QGt1YmVybmV0ZXNjcmQiCnNwZWM6CiAgaW5ncmVzc0NsYXNzTmFtZTogdHJhZWZpawogIHJ1bGVzOgogICAgLSBob3N0OiAicG9saWN5LmNvdWxvbWIuc29jaWFsIgogICAgICBodHRwOgogICAgICAgIHBhdGhzOgogICAgICAgICAgLSBwYXRoOiAvCiAgICAgICAgICAgIHBhdGhUeXBlOiBQcmVmaXgKICAgICAgICAgICAgYmFja2VuZDoKICAgICAgICAgICAgICBzZXJ2aWNlOgogICAgICAgICAgICAgICAgbmFtZTogcG9saWN5LW5leHVzCiAgICAgICAgICAgICAgICBwb3J0OgogICAgICAgICAgICAgICAgICBuYW1lOiBodHRwCi0tLQojIFNvdXJjZTogcG9saWN5LW5leHVzL3RlbXBsYXRlcy9pbmdyZXNzLnlhbWwKYXBpVmVyc2lvbjogbmV0d29ya2luZy5rOHMuaW8vdjEKa2luZDogSW5ncmVzcwptZXRhZGF0YToKICBuYW1lOiBwb2xpY3ktbmV4dXMtaHR0cHMKICBsYWJlbHM6CiAgICBhcHAua3ViZXJuZXRlcy5pby9uYW1lOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL2luc3RhbmNlOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnk6IEhlbG0KICAgIGFwcC5rdWJlcm5ldGVzLmlvL3ZlcnNpb246ICIwLjIuMCIKICAgIGhlbG0uc2gvY2hhcnQ6IHBvbGljeS1uZXh1cy0wLjIuMAogIGFubm90YXRpb25zOgogICAgY2VydC1tYW5hZ2VyLmlvL2NsdXN0ZXItaXNzdWVyOiAibGV0c2VuY3J5cHQtcHJvZCIKICAgIHRyYWVmaWsuaW5ncmVzcy5rdWJlcm5ldGVzLmlvL3JvdXRlci5lbnRyeXBvaW50czogd2Vic2VjdXJlCiAgICB0cmFlZmlrLmluZ3Jlc3Mua3ViZXJuZXRlcy5pby9yb3V0ZXIudGxzOiAidHJ1ZSIKc3BlYzoKICBpbmdyZXNzQ2xhc3NOYW1lOiB0cmFlZmlrCiAgdGxzOgogICAgLSBob3N0czoKICAgICAgICAtICJwb2xpY3kuY291bG9tYi5zb2NpYWwiCiAgICAgIHNlY3JldE5hbWU6IHBvbGljeS1jb3Vsb21iLXNvY2lhbC10bHMKICBydWxlczoKICAgIC0gaG9zdDogInBvbGljeS5jb3Vsb21iLnNvY2lhbCIKICAgICAgaHR0cDoKICAgICAgICBwYXRoczoKICAgICAgICAgIC0gcGF0aDogLwogICAgICAgICAgICBwYXRoVHlwZTogUHJlZml4CiAgICAgICAgICAgIGJhY2tlbmQ6CiAgICAgICAgICAgICAgc2VydmljZToKICAgICAgICAgICAgICAgIG5hbWU6IHBvbGljeS1uZXh1cwogICAgICAgICAgICAgICAgcG9ydDoKICAgICAgICAgICAgICAgICAgbmFtZTogaHR0cAotLS0KIyBTb3VyY2U6IHBvbGljeS1uZXh1cy90ZW1wbGF0ZXMvaW5ncmVzcy55YW1sCmFwaVZlcnNpb246IHRyYWVmaWsuaW8vdjFhbHBoYTEKa2luZDogTWlkZGxld2FyZQptZXRhZGF0YToKICBuYW1lOiBwb2xpY3ktbmV4dXMtaHR0cHMtcmVkaXJlY3QKICBsYWJlbHM6CiAgICBhcHAua3ViZXJuZXRlcy5pby9uYW1lOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL2luc3RhbmNlOiBwb2xpY3ktbmV4dXMKICAgIGFwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnk6IEhlbG0KICAgIGFwcC5rdWJlcm5ldGVzLmlvL3ZlcnNpb246ICIwLjIuMCIKICAgIGhlbG0uc2gvY2hhcnQ6IHBvbGljeS1uZXh1cy0wLjIuMApzcGVjOgogIHJlZGlyZWN0U2NoZW1lOgogICAgc2NoZW1lOiBodHRwcwogICAgcGVybWFuZW50OiB0cnVlCg==') +p=subprocess.run(['kubectl','apply','--dry-run=server','--validate=true','-f','-','-o','name'],input=manifest,stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=dict(os.environ,KUBECONFIG='/etc/rancher/k3s/k3s.yaml'),timeout=60) +lines=p.stdout.decode().splitlines() +expected={'networkpolicy.networking.k8s.io/policy-nexus-default-deny','networkpolicy.networking.k8s.io/policy-nexus-traefik','networkpolicy.networking.k8s.io/policy-nexus-acme-solver','serviceaccount/policy-nexus','service/policy-nexus','deployment.apps/policy-nexus','ingress.networking.k8s.io/policy-nexus-http','ingress.networking.k8s.io/policy-nexus-https','middleware.traefik.io/policy-nexus-https-redirect'} +print(json.dumps({'capture_utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'returncode':p.returncode,'server_dry_run_passed':p.returncode==0 and set(lines)==expected,'resource_names_match':set(lines)==expected,'resource_count':len(lines),'stderr_present':bool(p.stderr),'raw_errors_suppressed':True,'cluster_mutated':False})) diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/server-dry-run.json b/docs/changes/CUST-WP-0079/policy-publication-r1/server-dry-run.json new file mode 100644 index 0000000..4b9f50b --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/server-dry-run.json @@ -0,0 +1,10 @@ +{ + "capture_utc": "2026-10-19T13:18:34.372960+00:00", + "returncode": 0, + "server_dry_run_passed": true, + "resource_names_match": true, + "resource_count": 9, + "stderr_present": false, + "raw_errors_suppressed": true, + "cluster_mutated": false +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/source-pins.json b/docs/changes/CUST-WP-0079/policy-publication-r1/source-pins.json new file mode 100644 index 0000000..62004c4 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/source-pins.json @@ -0,0 +1,28 @@ +{ + "railiance-apps": { + "head": "0e1d2b3cfe426d2404ec52fecbb6fd8ca6462288", + "files": { + "bindings/policy-nexus-production.json": { + "before_sha256": "65b8c1a339ed1e75cbf72d0f6ac474d72bad1be9c381ebbeea700c7a9455f33e", + "after_sha256": "ceb2451c3c236f196527718ee9f0148014aad4d66a15b77d8303c0df36848c04" + }, + "values/policy-nexus-production.yaml": { + "before_sha256": "6e0f5a529b450f6b8f00f6fc59c50a7e5b652520f0a370b199a49cb416fac062", + "after_sha256": "a9de1adb22d83fa47a676e3685edf4fad578e3215db2db493ef4a8ca138dd36e" + }, + "values/policy-nexus-production-candidate.yaml": { + "before_sha256": "6e0f5a529b450f6b8f00f6fc59c50a7e5b652520f0a370b199a49cb416fac062", + "after_sha256": "a9de1adb22d83fa47a676e3685edf4fad578e3215db2db493ef4a8ca138dd36e" + } + } + }, + "rapp-policy-nexus": { + "head": "333f5fa9acb9c169bef4ef84aca0258d43688e50", + "files": { + "bindings/reef-railiance.yaml": { + "before_sha256": "237ce7297b0806f995247c6ae01d489213120afa89808067021817cce82f3e1e", + "after_sha256": "dfdbe7a570fe2910c67f9074050df10ddc560780cdfabe7bd0c2b4343329add8" + } + } + } +} diff --git a/docs/changes/CUST-WP-0079/policy-publication-r1/validation.json b/docs/changes/CUST-WP-0079/policy-publication-r1/validation.json new file mode 100644 index 0000000..ae41457 --- /dev/null +++ b/docs/changes/CUST-WP-0079/policy-publication-r1/validation.json @@ -0,0 +1,18 @@ +{ + "capture_utc": "2026-10-19T13:21:47.091266+00:00", + "owner_packaging_tests_passed": 9, + "helm_lint_passed": true, + "rendered_resources": 9, + "expected_changed_fields": 7, + "server_dry_run_passed": true, + "both_patch_apply_checks_passed": true, + "unapproved_binding_rejected": true, + "owner_checkouts_clean": { + "rapp-policy-nexus": true, + "railiance-apps": true + }, + "hosting_source_applied": false, + "hosting_source_pushed": false, + "cluster_mutated": false, + "public_release": false +}