Retain exact Policy Nexus publication proposal and rollback

This commit is contained in:
codex 2026-10-19 15:23:08 +02:00
parent dbf62aef47
commit dc585ab5b2
35 changed files with 1549 additions and 0 deletions

View file

@ -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.

View file

@ -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

View file

@ -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
}

View file

@ -0,0 +1,6 @@
image:
repository: forgejo.coulomb.social/coulomb/policy-nexus
digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1
publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e
sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd
sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,6 @@
image:
repository: forgejo.coulomb.social/coulomb/policy-nexus
digest: sha256:214b122c3d175563f114552fa1826dac9642433be019c736c3265d0a3ef379f1
publicationManifestDigest: 8c74b4e414f7760429600b7ba0b3627fcfe438417bfe6695f55acfa6905d352e
sourceInventoryDigest: e84453b6b411a7d66d2b5efbf083cd0033441d6b12983326442933da87bf61fd
sourceSetDigest: b00535063c56ede08f0a292b301a47add18bf70f81904bf3f434c8faa5ebe682

View file

@ -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"

View file

@ -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 }}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "policy-nexus.fullname" . }}
labels:
{{- include "policy-nexus.labels" . | nindent 4 }}
automountServiceAccountToken: false

View file

@ -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: {}

View file

@ -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}))

View file

@ -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
}

View file

@ -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"
}

View file

@ -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}))

View file

@ -0,0 +1,4 @@
{
"candidate_rejected_while_unapproved": true,
"returncode": 2
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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/"
}

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,6 @@
image:
repository: forgejo.coulomb.social/coulomb/policy-nexus
digest: sha256:4e0db6a57eb00f577159aa6ee10f910dd67b03fd0541c6ce849f5426fdb99d06
publicationManifestDigest: ba53cc4900e6bb9ab8aa4bac4e58cb5fe7a03d656bafb3f9cb3d9c8ebff7843a
sourceInventoryDigest: 40d9e8852fe4c9e75b71f371d0fdae38664b068e7498711b0ac5671d0f41efb5
sourceSetDigest: 15bda2e332285afc862df8974cf29de403737df5073fa362adfc6d203cf2f256

File diff suppressed because one or more lines are too long

View file

@ -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
}

View file

@ -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"
}
}
}
}

View file

@ -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
}