Freeze reviewed Helm and signer custody preparation successors
This commit is contained in:
parent
50de8be7f9
commit
3291a660ae
30 changed files with 2000 additions and 2 deletions
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"schema": "railiance-cluster.formal-custody-packet-source-owner-review.v1",
|
||||
"review_id": "RCLUSTER17-SIGNER-PACKET-P4-20261016",
|
||||
"reviewer": "railiance-cluster-owner (agent railiance-cluster, codex)",
|
||||
"native_review_role": "cluster-runtime-storage-owner",
|
||||
"decision": "approved",
|
||||
"scope": "exact P4 source-selection/ownership/readiness-preparation join only; not completed native admission or live custody/rollout/founder approval",
|
||||
"own_work_item": "RCLUSTER-WP-0017-T01",
|
||||
"own_checkout": "/home/worsch/railiance-cluster",
|
||||
"own_record_commit": "523669fba57c3785afc30b934ccdcb34a8871bf6",
|
||||
"reviewed_at": "2026-10-16T18:36:31.649560+00:00",
|
||||
"reviewed_proposal_id": "RPF35-PDP-SIGNER-NATIVE-PACKET-20261016-P4",
|
||||
"reviewed_manifest_sha256": "sha256:9eec861838a8e9138f2c821cff3014998fbe74bb01447642bf50d44e8b3b7cb3",
|
||||
"platform_source_git_revision": "84c529f239c81e6d3ca337015700b03e3a862f53",
|
||||
"rollout_r2_manifest_sha256": "sha256:5be7a7f438624dcb35b7dbc96e7c9e5a8e2d5d1b1966cb4338aa5aecbe3a8b59",
|
||||
"source_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"consumer_baseline_sha256": "sha256:72521ff7729f8ddf5176092f3949cd50ac5f9241b0a5d1d30f3c63ce1d83091b",
|
||||
"comment": "INTENT Core Principles1 Runtime Not Workloads and2 Healthy by Verification support the exact P4 runtime/storage-only boundary under RCLUSTER-WP-0017-T01. All source-selection joins and corrected rollback/freeze scope reviewed fresh in the ownrepo checkout. Cluster owns runtime/storage/headroom/PV retention, never workload/Helm or GitOps Application controllers; Access, Platform and Secrets retain their own respective semantics. P4 fixes preserved P3 prose, keeps source scope/assembler unchanged, and explicitly leaves actual held window/fence/expiry/founder/CCR dispositions absent. This approves the source join only and cannot fill the completed-scope cluster native review slot.",
|
||||
"checks": {
|
||||
"all_manifest_file_hashes_verified": true,
|
||||
"six_source_bundle_hashes_against_git_commit_verified": true,
|
||||
"executed_source_bundle_digest_verified": true,
|
||||
"native_plan_digest_verified": true,
|
||||
"rollout_r2_source_projection_join_verified": true,
|
||||
"selected_consumer_baseline_join_verified": true,
|
||||
"corrected_exact_five_owner_roles_verified": true,
|
||||
"actual_native_inputs_unfilled": true,
|
||||
"independent_assembler_tests": "8passed0.914s; synthetic test reviews never native authority"
|
||||
},
|
||||
"source_findings": [
|
||||
"README/remaining-inputs ownership audit assigns Application sync/freeze/restoration to Platform, signer workload/Helm/rollback to Access, consumer/trust to Secrets, runtime/storage/PV preservation/retention to cluster. Conditional Enablement covers only separately proposed actual ArgoCD installation/controller changes, excluded here.",
|
||||
"P4 pins exact R5 commit84c529 and source bundle, rolloutR2 manifest5be7a7/chartdc042/image84/projection8ce375, pre-key baseline72521. Source selection is not installed/public-key trust or native stopped projection.",
|
||||
"WaitForFirstConsumer stopped Helm semantics and ready rollback controls remain governed by reviewed rolloutR2; no P4 text grants current command execution or automatic predecessor restart.",
|
||||
"Fresh exact native preflight/held window/fence/PV Retain/dispositions remain open; source review completion does not close T02/T03.",
|
||||
"Absolute child120second timing and expiry, unknown-CAS/no-retry/forward-only recovery, retained outbox/evidence and strict failclosed trust remain unchanged."
|
||||
],
|
||||
"completed_native_scope_sha256": null,
|
||||
"native_admission": false,
|
||||
"founder_approval": false,
|
||||
"other_owner_assent": false,
|
||||
"T01_source_scope_satisfied": true,
|
||||
"T02_T03_native_scope_satisfied": false
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"schema": "railiance-cluster.formal-rollout-source-owner-review.v1",
|
||||
"review_id": "RCLUSTER17-SIGNER-ROLLOUT-R2-20261016",
|
||||
"reviewer": "railiance-cluster-owner (agent railiance-cluster, codex)",
|
||||
"native_review_role": "cluster-runtime-storage-owner",
|
||||
"decision": "approved",
|
||||
"scope": "exact rollout R2 runtime/storage and Helm maintenance source proposal only; no live action/current-fence/binding/custody/public-trust acceptance",
|
||||
"own_work_item": "RCLUSTER-WP-0017-T01",
|
||||
"own_checkout": "/home/worsch/railiance-cluster",
|
||||
"own_record_commit": "523669fba57c3785afc30b934ccdcb34a8871bf6",
|
||||
"reviewed_at": "2026-10-16T18:32:18.904019+00:00",
|
||||
"reviewed_manifest_sha256": "sha256:5be7a7f438624dcb35b7dbc96e7c9e5a8e2d5d1b1966cb4338aa5aecbe3a8b59",
|
||||
"rollout_proposal_id": "FLEX24-SIGNER-ROLLOUT-20261016-R1",
|
||||
"rollout_revision": "R2",
|
||||
"chart_git_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_git_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"platform_git_revision": "84c529f239c81e6d3ca337015700b03e3a862f53",
|
||||
"source_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"comment": "INTENT principles Runtime Not Workloads and Healthy by Verification support this precise runtime/storage source scope under RCLUSTER-WP-0017-T01. Actual Helm-rendered replicas0/1 make stopped candidate installation representable without a post-render spec mutation. Source Recreate/exact projection/no hooks/bounded request are consistent with runtime constraints. Cluster approves this exact source maintenance proposal only; Access release semantics and Platform Application freeze remain independently owned. Dated native snapshots and source projection grant no live fence or storage acceptance.",
|
||||
"independent_verification": "rollout-r2-independent-verification.json",
|
||||
"source_findings": [
|
||||
"All frozen manifest and exact archived input hashes verified; independent retained/stopped/ready renders byte-equal; Deployment differs only replica count; native encoded projection identical.",
|
||||
"Stop explicitly --reset-values --no-hooks --wait=false; no atomic/force/cleanup-on-fail/reuse-values. This avoids WFFC PVC wait deadlock and automatic rollback to running predecessor. Exact chart has no hooks; source success is not actual fence.",
|
||||
"Ready atomic/wait only after actual newly established stopped Helm revision independently captured and shown to be the rollback target with identical candidate template; never auto-rollback to observed running revision4. No executable current command is approved.",
|
||||
"1Gi RWO local-path/Helmkeep request preserves actual PV UID/binding/claimRef/node-affinity and Retain readback as later independent gates; request is not hard quota, backup, node-loss durability or process exclusion.",
|
||||
"Canonical local d52/source2b/current05a remains frozen; exact image84 provenance and chartdc0420 are distinct pins; no package placement/adoption inferred.",
|
||||
"Exact caller/policy/registry/resources preserved;64MiB process bound and restart/lock/storage-failure proofs remain native gates.",
|
||||
"Numeric integral YAML0.0/1.0 acceptance is an explicit Helm representation limit; unsafe bool/string/fractional/other numeric values refused by independent render cases."
|
||||
],
|
||||
"required_later_controls": [
|
||||
"Authenticate exact completed successor scope, source/image/CCR/projection/trust/window/expiry and distinct founder/owner dispositions; frozen P2 is not upgraded.",
|
||||
"Access fences consumer acceptance first and owns manual/CI/workload writers; Platform authenticates actual GitOps/Application freeze. Unknown writer, HPA, second signer or uncertain inventory holds fence.",
|
||||
"Refresh cluster identity/node/current Helm revision+allowlisted configuration, quota/headroom/disk and sanitized native server dry-run/client diff. Reconcile admission/defaulting projection drift before CAS.",
|
||||
"After stop, actual generation caught up, zero Deployment/UID-owned ReplicaSet spec/status replicas, no live/terminating owned/signer-SA/seed-mount pods; recheck fence+projection immediately before CAS; hold across custody/delivery/trust.",
|
||||
"WFFC binding/start occurs only through separately approved transition with consumers still fenced; actual exact PV Retain before durable acceptance.",
|
||||
"Ready120seconds and recovery decision600seconds; partial writes/timeouts/ambiguous CAS stay fenced preserving unknown/evidence; no auto CAS retry/remint, cursor reset, PVC deletion, seed restoration or unsigned trust fallback."
|
||||
],
|
||||
"completed_native_scope_sha256": null,
|
||||
"native_admission": false,
|
||||
"founder_approval": false,
|
||||
"other_owner_assent": false,
|
||||
"frozen_r1_p2_changed": false
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Access signer rollout preparation R2
|
||||
|
||||
Existing work: FLEX-WP-0024-T06. Access deployment source preparation only. Native admission and execution remain withheld. Frozen rollout R1, stopped-chart R1/R2 and Platform P2 remain unchanged.
|
||||
|
||||
## Exact separate pins
|
||||
|
||||
- Chart/retained values/policy/registry: Access commit `dc042022f7c30671cf0a7605cf43ef6d96d04242`, `charts/flex-auth`, release `flex-auth-secrets-engine`, namespace `flex-auth`. Source archive file hashes are in render-evidence.json.
|
||||
- Image: `forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f`, built from Access `84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0`. Independently verified ordinary main-push CI402 receipt is `../image-84c78e0/candidate-receipt.json`. The chart-only successor does not rebuild this image or change its source label. Policy and registry source bytes match the selected image revision. Chart/test/workplan-only changes do not trigger the existing image workflow.
|
||||
- Projection implementation: committed Platform R5 `84c529f239c81e6d3ca337015700b03e3a862f53`, `scripts/flex_auth_signer_native.py` SHA256 `4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f`. The renderer verifies this exact committed module before calling its projection/encoding implementation.
|
||||
- Managed package remains local `d52f811ed5ec0be27c9c367e71d476125b3228be`, tree `d4fbad71bdc8ef870603526ccd1f53195d0322af`, readiness draft/no reef binding, with frozen extraction2b/current05a source/image. R2 is a separate proposed signer successor, not execution through the extraction-only contract or evidence of central/private availability, placement or runtime package adoption.
|
||||
|
||||
Both `stopped-source-render.yaml` and `activation-source-render.yaml` are actual Helm renders with their corresponding exact values overlays. The complete parsed Deployment differs only in replicas0 versus1; no post-render scale/spec patch is used. The new chart accepts numeric exactly0/1, rejects unsafe replica values, retains Recreate and the source process lock. Helm cannot distinguish numeric integral YAML0.0/1.0 from0/1; this semantic limit is documented and tested in the stopped-chart proposal.
|
||||
|
||||
The canonical encoded source projection is `source-projection.canonical.json`, SHA256 `8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c`. Its digest equals both R2 states and frozen rollout R1. It includes immutable image, exact caller flags, SA, pod UID/GID/fsGroup65532, read-only seed directory0440, reviewer projection and PVC mount. The pretty JSON file has a different byte hash; use canonical encoding for the native contract. A source projection is not a stopped native fence. The future observed stopped Deployment must match this exact projection after API admission/defaulting; drift requires explicit review.
|
||||
|
||||
`source-render.diff` compares the ready proposal with retained values rendered by the same exact new chart. Service, ServiceAccount, RBAC and NetworkPolicy objects are unchanged. Existing caller mode enforce, audience flex-auth, binding `secrets-engine=system:serviceaccount:secrets-engine:secrets-engine`, Kubernetes API URL, lifecycle policy and registry paths and25m/32Mi requests/300m/192Mi limits are unchanged. No Secret or Ingress is generated. Seed/kid coordinates remain proposed; audit delivery stays disabled and no task source is enabled.
|
||||
|
||||
Reproduce offline with `python3 prepare.py --image-receipt ../image-84c78e0/candidate-receipt.json` from this directory. The script uses disposable source archives and local Helm only. No native dry-run, apply, diff, token request or credential access occurred.
|
||||
|
||||
## Owner split and proposed maintenance path
|
||||
|
||||
Access owns workload/chart/Helm release, delivery mount semantics, competing manual/CI/workload writers, process/outbox fencing and rollback. Platform owns OpenBao custody/read delivery and existing ArgoCD Applications and their sync/freeze integration, with actual identified writer coordination with Access. Cluster owns runtime/node identity, admission, scheduling/headroom, local-path provisioning and actual PV retention. Enablement reviews an ArgoCD installation/controller configuration change only; this scope excludes such a change. No combined cluster/GitOps assent or other-owner review is authored here.
|
||||
|
||||
The proposed argument arrays in command-plan.proposed.json use a future verified source-materialization root. They are review shapes, not runnable approved commands. The actual root/executor/window and native preflight receipts remain absent. Both transitions explicitly use `--reset-values` and `--no-hooks`: exact chart defaults plus retained file plus phase overlay, with no persisted override inheritance or hook execution. No hook annotation exists in any exact archived render. No `--reuse-values`, `--force`, `--cleanup-on-fail`, mutable tag, namespace creation, alternate policy or unsigned consumer fallback is included.
|
||||
|
||||
1. Collect exact independent founder, Access, Platform, Secrets and cluster-runtime-storage dispositions for the completed successor scope. Authenticate actual Helm/workload and Application writers, freeze only those in scope with their owners, capture prior states/no in-flight operation/restoration criteria. Stop affected protected-consumer acceptance first. Any unknown writer, HPA, job, second signer-SA/seed-mount pod or missing owner disposition holds the fence closed.
|
||||
2. Refresh actual target identity, Deployment UID/release revision and allowlisted nonsecret config, quota/storage/headroom and package availability. Review sanitized client diff and server dry-run of exact nonsecret resources; admission changes must be explicitly reconciled. Do not capture raw Helm values, Secret objects/annotations/errors, env, logs or tokens. Existing18:01/18:02UTC snapshots are dated inputs, not a reservation or live fence.
|
||||
3. Under the approved maintenance path, Helm installs the exact candidate template at replicas0 using stopped-values.proposed.yaml. This new WaitForFirstConsumer PVC can remain Pending while stopped. Use `--wait=false` without `--atomic` for this transition: installed Helm help explicitly includes PVCs in wait and enables wait for atomic. Instead independently observe generation caught up, zero desired/status replicas, every UID-owned ReplicaSet at spec/status0 and no live or terminating UID-owned/signer-SA/seed-mount pods within the reviewed120-second stop budget. Helm command success alone is insufficient. A failure after partial apply preserves the fence and requires exact observed-state reconciliation; it must not automatically restore running predecessor05a.
|
||||
4. Hold the same independently authenticated exclusive window through the separately approved Platform custody/read-lane ceremony, ESO delivery and independent Secrets public trust. Recheck native projection and all stopped-fence observations immediately before custody CAS. Exact founder entity, absolute expiry, source/CCR/image/trust/window hashes and five actual external scope-bound dispositions are mandatory; this packet fills none of them. Ambiguous CAS/readback/fsync outcomes keep original unknown evidence and fence; no remint or replay.
|
||||
5. Capture the newly established stopped Helm revision and prove its rollback target remains replicas0 with identical exact candidate template. Only then may a separately approved ready transition use activation-values.proposed.yaml with atomic/wait120s: an automatic rollback must return to the reviewed stopped state, never the old running unsigned state. Protected consumers remain fenced during WaitForFirstConsumer binding/startup. Capture actual PVC/PV identifiers and have the authorized cluster owner set and verify exact PV Retain before durable acceptance. If binding cannot be safely completed in that window, stay stopped; do not guess a PV or extend the scope silently.
|
||||
6. Require Ready within120seconds and recovery decision within600seconds, exact image/pod UID/SA/startup mount/UID/GID/kid verification and independent public-trust delivery. Then record native signed lifecycle ALLOW/DENY with original durable records and installed Secrets verifier; require caller negatives, wrong-tenant/task refusal, restart signature/sequence/cursor preservation and separately admitted actual lock/capacity/unwritable/fsync negatives. Initial proof causes no protected backend effect and claims no audit receiver acceptance. Reopen protected acceptance only after those distinct gates pass.
|
||||
|
||||
## Dated resources, storage and rollback
|
||||
|
||||
Cluster observation at18:01:45/18:02:04UTC16October2026 identified node92.205.62.239, kube-system UIDa553c742-0115-43d4-99a4-a5ca56fe0786, Deployment UIDf83a5f5c-7dd7-4aac-bc02-d447e423e6ae generation4 and running unsigned05a pod; Helm revision4 deployed. This is not stopped state or rollback authorization. No namespace ResourceQuota, LimitRange or PVC was present. Thus no namespace-enforced storage quota was observed then, rather than an invented numeric quota. Source receipts/hash references are in dated-metadata-inputs.json; refresh at the actual window.
|
||||
|
||||
The exact new claim request is1Gi (1073741824 bytes), RWO, local-path, `flex-auth/flex-auth-secrets-engine-outbox`, with Helmkeep. Observed free filesystem bytes were125827354624 (about117.2GiB), exceeding this request by124753612800 bytes then; no reservation or hard quota follows. Observed requested node CPU3580m/4000m left420m; memory request9760Mi and limits were overcommitted. Ready state retains the old25m/32Mi request and Recreate avoids intentional surge, but current fit and disk remain cluster-owned native checks.
|
||||
|
||||
Storage class local-path used WaitForFirstConsumer/Delete. Neither1Gi request nor RWO/Recreate provides a hard filesystem quota, backup, node-loss recovery or process exclusion. The independent source limit is64MiB/67108864 bytes and needs native failure/restart proof. Actual dynamically bound PV name/UID/claimRef UID cannot exist in this source packet. Capture exact actual binding, capacity/node affinity and cluster-owned Retain mutation/readback before durable acceptance. Helmkeep does not override Delete reclaim or protect manual deletion. Backup/restore and off-node evidence continuity remain open.
|
||||
|
||||
Rollback keeps protected consumers fenced, stops candidate through exact reviewed replicas0 Helm path, observes all relevant pods gone and lock released, and retains PVC/log/cursor/signatures/receipts. Reconcile partial stop/upgrade failures before any restart. Restore the captured stopped revision only after checking exact current source/config and evidence-format compatibility. Historic observed revision4/current05a is an unsigned availability option only after separate reviewed compatibility disposition; it cannot satisfy the strict signed consumer or mutate new outbox evidence by assumption. If exclusion/format is uncertain, stay unavailable. No uninstall, PVC/PV deletion, cursor reset, caller/trust weakening, old-seed restore or automatic CAS retry. Compromise requires public trust withdrawal and separately approved forward-only successor. Restore each controller only through its actual owner's recorded criteria.
|
||||
|
||||
Source preparation costs EUR0 incremental infrastructure. The proposed resource addition is one1Gi local-path request with unchanged workload resources. Founder native spend/risk-loss ceiling, outage and evidence-loss disposition remain absent. Neither source approval nor preapproved shell prefixes grant native authority.
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
---
|
||||
# Source: flex-auth/templates/networkpolicy.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
egress:
|
||||
- ports:
|
||||
- port: 443
|
||||
protocol: TCP
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: secrets-engine
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: secrets-engine
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
---
|
||||
# Source: flex-auth/templates/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
automountServiceAccountToken: false
|
||||
---
|
||||
# Source: flex-auth/templates/outbox-pvc.yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-outbox
|
||||
annotations:
|
||||
helm.sh/resource-policy: keep
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: "local-path"
|
||||
resources:
|
||||
requests:
|
||||
storage: "1Gi"
|
||||
---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
rules:
|
||||
- apiGroups:
|
||||
- authentication.k8s.io
|
||||
resources:
|
||||
- tokenreviews
|
||||
verbs:
|
||||
- create
|
||||
---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: flex-auth-secrets-engine
|
||||
namespace: flex-auth
|
||||
---
|
||||
# Source: flex-auth/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: http
|
||||
---
|
||||
# Source: flex-auth/templates/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountName: flex-auth-secrets-engine
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
fsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: flex-auth
|
||||
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
- 0.0.0.0:8080
|
||||
- --registry
|
||||
- /opt/flex-auth/examples/secrets-engine/registry_snapshot.json
|
||||
- --policy
|
||||
- /opt/flex-auth/examples/secrets-engine/policy_package.md
|
||||
- --envelope-signing-key-file
|
||||
- "/var/run/secrets/decision-envelope-signing/seed"
|
||||
- --envelope-signing-kid
|
||||
- "flex-auth-lifecycle-20261016-r1"
|
||||
- --outbox-max-bytes
|
||||
- "67108864"
|
||||
- --outbox-dir
|
||||
- "/var/lib/flex-auth/outbox"
|
||||
- --emission-source
|
||||
- "flex-auth.secrets-engine"
|
||||
- --caller-audience
|
||||
- "flex-auth"
|
||||
- --caller-auth-mode
|
||||
- "enforce"
|
||||
- --caller-kubernetes-url
|
||||
- "https://10.43.0.1"
|
||||
- --caller-binding
|
||||
- "secrets-engine=system:serviceaccount:secrets-engine:secrets-engine"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 300m
|
||||
memory: 192Mi
|
||||
requests:
|
||||
cpu: 25m
|
||||
memory: 32Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
volumeMounts:
|
||||
- mountPath: "/var/run/secrets/decision-envelope-signing"
|
||||
name: flex-auth-envelope-signing
|
||||
readOnly: true
|
||||
- mountPath: "/var/lib/flex-auth/outbox"
|
||||
name: flex-auth-outbox
|
||||
- mountPath: /var/run/secrets/flex-auth-reviewer
|
||||
name: flex-auth-reviewer
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: flex-auth-envelope-signing
|
||||
secret:
|
||||
secretName: "flex-auth-secrets-engine-envelope-signing"
|
||||
defaultMode: 0440
|
||||
items:
|
||||
- key: "seed"
|
||||
path: seed
|
||||
- name: flex-auth-outbox
|
||||
persistentVolumeClaim:
|
||||
claimName: "flex-auth-secrets-engine-outbox"
|
||||
- name: flex-auth-reviewer
|
||||
projected:
|
||||
defaultMode: 0440
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
expirationSeconds: 3600
|
||||
path: token
|
||||
- configMap:
|
||||
name: kube-root-ca.crt
|
||||
items:
|
||||
- key: ca.crt
|
||||
path: ca.crt
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f
|
||||
replicaCount: 1
|
||||
envelopeSigning:
|
||||
enabled: true
|
||||
kid: flex-auth-lifecycle-20261016-r1
|
||||
secretName: flex-auth-secrets-engine-envelope-signing
|
||||
secretKey: seed
|
||||
mountPath: /var/run/secrets/decision-envelope-signing
|
||||
outbox:
|
||||
enabled: true
|
||||
source: flex-auth.secrets-engine
|
||||
mountPath: /var/lib/flex-auth/outbox
|
||||
size: 1Gi
|
||||
maxBytes: 67108864
|
||||
storageClassName: local-path
|
||||
existingClaim: ''
|
||||
auditDelivery:
|
||||
enabled: false
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"schema": "access-engine.signer-helm-maintenance-plan.v1",
|
||||
"state": "unapproved argument shapes; no invocation ready",
|
||||
"verified_source_root": null,
|
||||
"frozen_rollout_root": null,
|
||||
"executor": null,
|
||||
"chart_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"stop": {
|
||||
"argv": [
|
||||
"helm",
|
||||
"upgrade",
|
||||
"flex-auth-secrets-engine",
|
||||
"OWNER_REVIEWED_VERIFIED_SOURCE_ROOT/charts/flex-auth",
|
||||
"--namespace",
|
||||
"flex-auth",
|
||||
"-f",
|
||||
"OWNER_REVIEWED_VERIFIED_SOURCE_ROOT/values/secrets-engine.yaml",
|
||||
"-f",
|
||||
"OWNER_REVIEWED_FROZEN_ROLLOUT_R2_ROOT/stopped-values.proposed.yaml",
|
||||
"--wait=false",
|
||||
"--timeout",
|
||||
"120s",
|
||||
"--reset-values",
|
||||
"--no-hooks"
|
||||
],
|
||||
"atomic": false,
|
||||
"reason": "Helm wait includes PVCs; WaitForFirstConsumer unbound claim must not block maintenance stop",
|
||||
"required_followup": "within120s observedGeneration caught up and all UID-owned/SA/seed-mount pods absent; source projection match; retain unknown partial failures fenced",
|
||||
"forbidden_flags": [
|
||||
"--atomic",
|
||||
"--wait=true",
|
||||
"--force",
|
||||
"--cleanup-on-fail",
|
||||
"--reuse-values"
|
||||
]
|
||||
},
|
||||
"ready": {
|
||||
"argv": [
|
||||
"helm",
|
||||
"upgrade",
|
||||
"flex-auth-secrets-engine",
|
||||
"OWNER_REVIEWED_VERIFIED_SOURCE_ROOT/charts/flex-auth",
|
||||
"--namespace",
|
||||
"flex-auth",
|
||||
"-f",
|
||||
"OWNER_REVIEWED_VERIFIED_SOURCE_ROOT/values/secrets-engine.yaml",
|
||||
"-f",
|
||||
"OWNER_REVIEWED_FROZEN_ROLLOUT_R2_ROOT/activation-values.proposed.yaml",
|
||||
"--atomic",
|
||||
"--wait",
|
||||
"--timeout",
|
||||
"120s",
|
||||
"--reset-values",
|
||||
"--no-hooks"
|
||||
],
|
||||
"preconditions": [
|
||||
"exact newly recorded stopped Helm rollback revision verified",
|
||||
"separate custody/read delivery/public trust/native scope admitted",
|
||||
"protected consumers still fenced",
|
||||
"runtime binding/provisioning/headroom authorized; exact PV Retain before durable acceptance"
|
||||
],
|
||||
"automatic_rollback_target_revision": null,
|
||||
"forbidden_flags": [
|
||||
"--force",
|
||||
"--cleanup-on-fail",
|
||||
"--reuse-values"
|
||||
]
|
||||
},
|
||||
"previous_observed_revision": {
|
||||
"revision": 4,
|
||||
"observed_at": "2026-10-16T18:02:04.834187+00:00",
|
||||
"authorization": "none; refresh/config/format compatibility review required before any rollback"
|
||||
},
|
||||
"sanitization": "future execution wrapper suppresses raw Helm/Kubernetes object/error values; returns allowlisted receipt only",
|
||||
"no_live_execution": true,
|
||||
"values_semantics": "--reset-values discards persisted overrides and starts from exact chart defaults plus retained values file and frozen phase overlay; allowlisted current/native diff remains mandatory",
|
||||
"hook_semantics": "--no-hooks explicitly skips hook execution in both transitions; exact archived source renders contain no helm.sh/hook annotations",
|
||||
"source_hook_absence_verified": true
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"schema": "access-engine.signer-dated-inputs.v1",
|
||||
"new_observations_made": false,
|
||||
"refresh_at_actual_window": true,
|
||||
"inputs": {
|
||||
"cluster-review-r1/runtime-observation.json": "sha256:63a637ea32aadc3358ba55dc5b46f86c67df3d6c80ea00e3aee68bfa38fd3e58",
|
||||
"cluster-review-r1/prechange-resources.json": "sha256:4886fe8a899e949c17464a8271b09830917dd3e9251fb97e17076291d8f4842d",
|
||||
"cluster-review-r1/review.json": "sha256:959b526cb77f530de15aa6f3172e26971803e8ae67e6945d996de0621f657c8a",
|
||||
"image-84c78e0/candidate-receipt.json": "sha256:af8e032d28776722ccf2bfe0f884577e568d8d0fb3713aa869e1d7d1c77c576f"
|
||||
},
|
||||
"dated_observations": {
|
||||
"runtime": "2026-10-16T18:01:45Z",
|
||||
"resources": "2026-10-16T18:02:04.834187+00:00",
|
||||
"namespace_quota": "No ResourceQuota or LimitRange observed; not unlimited physical capacity or native approval",
|
||||
"free_bytes": 125827354624,
|
||||
"pvc_request_bytes": 1073741824,
|
||||
"free_minus_request_bytes": 124753612800,
|
||||
"helm_revision": 4,
|
||||
"deployment_uid": "f83a5f5c-7dd7-4aac-bc02-d447e423e6ae",
|
||||
"kube_system_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786"
|
||||
},
|
||||
"limits": "Source-only preparation uses prior independently retained selected metadata; these are neither current resource reservations nor a stopped/native exclusive-window receipt."
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
{
|
||||
"schema": "access-engine.signer-exclusive-window-proposal.v2",
|
||||
"proposal_id": "FLEX24-SIGNER-ROLLOUT-20261016-R1",
|
||||
"status": "proposed-incomplete-native-window-not-held",
|
||||
"owner_work": "FLEX-WP-0024-T06",
|
||||
"target": {
|
||||
"cluster": "railiance01",
|
||||
"node_ip": "92.205.62.239",
|
||||
"kube_system_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786",
|
||||
"namespace": "flex-auth",
|
||||
"deployment": "flex-auth-secrets-engine",
|
||||
"observed_predecessor_deployment_uid": "f83a5f5c-7dd7-4aac-bc02-d447e423e6ae",
|
||||
"service_account": "flex-auth-secrets-engine"
|
||||
},
|
||||
"executor": null,
|
||||
"abort_owner": "founder",
|
||||
"access_preparation_owner": "access-engine",
|
||||
"founder_disposition": null,
|
||||
"absolute_window_start": null,
|
||||
"absolute_window_end": null,
|
||||
"ready_timeout_seconds": 120,
|
||||
"recovery_decision_seconds": 600,
|
||||
"competing_controllers": null,
|
||||
"actual_prechange_helm_revision": null,
|
||||
"consumer_stop_receipt": null,
|
||||
"native_stopped_fence_receipt": null,
|
||||
"conditions": [
|
||||
"Protected consumers fenced before template/stop or custody changes",
|
||||
"Exact Deployment replicas0; observedGeneration equals generation; no status replicas",
|
||||
"All owned ReplicaSets spec/status replicas0; no live or terminating owned pods",
|
||||
"No signer-SA or seed-mount pods anywhere in target namespace; no HPA targeting signer",
|
||||
"Access freezes actual Helm/CI/workload writers; Platform authenticates/freezes actual in-scope Application sync writers. Record identity/revision/prior state/no in-flight operation/restore criteria; no controller-installation change.",
|
||||
"Native stopped Deployment projection equals reviewed source projection immediately before custody CAS",
|
||||
"Remain fenced until independently authenticated public trust/delivery/runtime proof",
|
||||
"Any uncertain write/readback/identity/volume or readiness outcome keeps fence closed",
|
||||
"Stopped Helm transition uses wait=false without atomic while WaitForFirstConsumer PVC is unbound; separate stop/fence observations are required",
|
||||
"Ready atomic transition may only target a recorded current stopped rollback revision, with consumers fenced and exact binding/Retain verified before durable acceptance"
|
||||
],
|
||||
"storage": {
|
||||
"pvc": "flex-auth-secrets-engine-outbox",
|
||||
"request": "1Gi",
|
||||
"request_bytes": 1073741824,
|
||||
"outbox_hard_ceiling_bytes": 67108864,
|
||||
"storage_class": "local-path",
|
||||
"helm_keep": true,
|
||||
"pv_reclaim_required": "Retain",
|
||||
"pv_name": null,
|
||||
"pv_uid": null,
|
||||
"claim_uid": null,
|
||||
"namespace_storage_quota_remaining_bytes": null,
|
||||
"node_free_filesystem_bytes": null,
|
||||
"binding": "WaitForFirstConsumer; exact actual binding and Retain verification required before durable acceptance",
|
||||
"dated_namespace_quota_observation": "No ResourceQuota or LimitRange observed at18:01:45UTC; no numeric quota was present, refresh required",
|
||||
"dated_node_free_filesystem_bytes": 125827354624,
|
||||
"dated_free_minus_request_bytes": 124753612800
|
||||
},
|
||||
"cost": {
|
||||
"source_preparation_incremental_eur": 0,
|
||||
"native_spend_authority": false,
|
||||
"native_incremental_resources": "one1Gi local-path request; unchanged25m/32Mi workload request",
|
||||
"risk_loss_ceiling_eur": null
|
||||
},
|
||||
"authority_granted": false,
|
||||
"revision": "R2",
|
||||
"owner_dispositions": {
|
||||
"founder": null,
|
||||
"access-engine-owner": null,
|
||||
"railiance-platform-owner": null,
|
||||
"secrets-engine-owner": null,
|
||||
"cluster-runtime-storage-owner": null
|
||||
},
|
||||
"owner_scope": {
|
||||
"access-engine-owner": "workload/chart/Helm release and competing workload/manual/CI writers, signer mount/process/outbox fencing and rollback",
|
||||
"railiance-platform-owner": "OpenBao custody/read delivery and existing ArgoCD Applications and their sync/freeze integration",
|
||||
"cluster-runtime-storage-owner": "runtime/node identity, admission/scheduling/headroom, provisioning and exact actual PV retention",
|
||||
"enablement": "only an ArgoCD installation/controller configuration change, excluded from this scope"
|
||||
},
|
||||
"dated_prechange_helm_revision": 4,
|
||||
"actual_stopped_helm_revision": null,
|
||||
"source_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"chart_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"live_window_held": false
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"schema": "access-engine.signer-rollout-preparation.v2",
|
||||
"proposal_id": "FLEX24-SIGNER-ROLLOUT-20261016-R1",
|
||||
"revision": "R2",
|
||||
"role": "access-engine-deployment-preparation-only",
|
||||
"owner_work": "FLEX-WP-0024-T06",
|
||||
"chart_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"platform_revision": "84c529f239c81e6d3ca337015700b03e3a862f53",
|
||||
"source_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"prior_R1_manifest_sha256": "sha256:6b9292aab59f9ca8012be00f50027ded6a12018a3b36b011ef953d448e75e3dc",
|
||||
"disposition": "source-checks-pass-native-gates-open",
|
||||
"native_window_held": false,
|
||||
"native_stopped_fence_verified": false,
|
||||
"other_owner_assent": false,
|
||||
"execution_authorized": false,
|
||||
"files": {
|
||||
"README.md": "sha256:bae015d61c04fb761ea468a422b9fbb4ecae404b898c0eab2653ad2cae7b8370",
|
||||
"activation-source-render.yaml": "sha256:b7edecb8ec50a6d2db7623a3d962dbece46de81d3809d5f73b3aca20ff76b8c7",
|
||||
"activation-values.proposed.yaml": "sha256:e76a30967add800ed8b588368757e7a5fa0ce4d8305ef658b5a4a08e377eb5b8",
|
||||
"command-plan.proposed.json": "sha256:6e8dfd087dee349dde04995b84a1e2dd4aaa74a26150b23e6f8fd9313632f089",
|
||||
"dated-metadata-inputs.json": "sha256:68fc91c39ce8ef9029b37867f4e77d043e8c8fd42eedfe3c9e703509f6d6028e",
|
||||
"exclusive-window.proposed.json": "sha256:15a063dfe1b4237c458ce3e12ec1a19e87bf2a3b98f97fbe7dcdcdb8d121a675",
|
||||
"owner-source-review.json": "sha256:b125d139273b88a8ed4e09f8fccf59fcd11ec75b49ee1e6593598543aeed38a9",
|
||||
"prepare.py": "sha256:c7dbaac542f1e9c3c869e896f848eed16769b93e29a4ef1c3031d71e10c3dcd7",
|
||||
"render-evidence.json": "sha256:bc1084fe03491b713b3a73b970082735324a0d99a27e07845515d8878525b626",
|
||||
"retained-source-render.yaml": "sha256:f979f7d05d5b0a54e3b8ac7c413aa4d401139f991b43412cdbde3d63249b0dd9",
|
||||
"source-deployment-projection.json": "sha256:056b6bf842713fb9a328dae901401d6867da47da68bfb8a4904bb0d7b8d9e912",
|
||||
"source-projection.canonical.json": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"source-render.diff": "sha256:d510bbe9ff280f49f86ad67355774fbf76e32c36c129bd593b4be5b257dccd67",
|
||||
"stopped-source-render.yaml": "sha256:03b631f0fe17c63494c14619199f69f2a2a9ab245d00f1ec441248868b24c071",
|
||||
"stopped-values.proposed.yaml": "sha256:6e6f4bdd6ed1f9994f87e51b24186ba923515419b30d9c187c288f7db05e3a77"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"schema": "access-engine.signer-rollout-source-review.v1",
|
||||
"proposal_id": "FLEX24-SIGNER-ROLLOUT-20261016-R1",
|
||||
"revision": "R2",
|
||||
"reviewer_role": "access-engine-owner",
|
||||
"existing_own_work": "FLEX-WP-0024-T06",
|
||||
"disposition": "approve-source-preparation-only-for-independent-review",
|
||||
"scope": "retained Access Helm release/chart/values/image, signer mount, single-writer/outbox source fencing and rollback proposal only",
|
||||
"input_hashes": {
|
||||
"prepare.py": "sha256:c7dbaac542f1e9c3c869e896f848eed16769b93e29a4ef1c3031d71e10c3dcd7",
|
||||
"README.md": "sha256:bae015d61c04fb761ea468a422b9fbb4ecae404b898c0eab2653ad2cae7b8370",
|
||||
"render-evidence.json": "sha256:bc1084fe03491b713b3a73b970082735324a0d99a27e07845515d8878525b626",
|
||||
"exclusive-window.proposed.json": "sha256:15a063dfe1b4237c458ce3e12ec1a19e87bf2a3b98f97fbe7dcdcdb8d121a675",
|
||||
"command-plan.proposed.json": "sha256:6e8dfd087dee349dde04995b84a1e2dd4aaa74a26150b23e6f8fd9313632f089",
|
||||
"dated-metadata-inputs.json": "sha256:68fc91c39ce8ef9029b37867f4e77d043e8c8fd42eedfe3c9e703509f6d6028e",
|
||||
"source-projection.canonical.json": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c"
|
||||
},
|
||||
"source_checks": {
|
||||
"actual_helm_replicas0_and1": true,
|
||||
"only_deployment_replicas_differs_between_states": true,
|
||||
"platform_R5_projection_hash_matches_frozen_R1": true,
|
||||
"unchanged_caller_policy_registry_resources": true,
|
||||
"nondeployment_resources_unchanged_except_new_PVC": true,
|
||||
"ordinary_verified_image84_selected_separately_from_chart_dc0420": true,
|
||||
"no_hooks_in_source_and_explicit_no_hooks_reset_values": true
|
||||
},
|
||||
"held_native_window": false,
|
||||
"native_stopped_fence": false,
|
||||
"native_disposition": "withheld: exact completed authenticated scope, independent owner/founder dispositions, runtime/controller/storage/custody/trust/session/record gates remain open",
|
||||
"other_owner_assents_authored": false,
|
||||
"execution_authorized": false,
|
||||
"source_preparation_incremental_eur": 0
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Offline source render only. Image receipt is deliberately a separate input."""
|
||||
import argparse
|
||||
import difflib
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import io
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import tempfile
|
||||
import yaml
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
SOURCE = Path('/home/worsch/access-engine')
|
||||
REVISION = 'dc042022f7c30671cf0a7605cf43ef6d96d04242'
|
||||
IMAGE_REVISION = '84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0'
|
||||
PLATFORM_REVISION = '84c529f239c81e6d3ca337015700b03e3a862f53'
|
||||
NATIVE_SHA256 = 'sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f'
|
||||
NATIVE = Path('/home/worsch/railiance-platform/scripts/flex_auth_signer_native.py')
|
||||
PATHS = ['charts/flex-auth', 'values/secrets-engine.yaml',
|
||||
'examples/secrets-engine/policy_package.md', 'examples/secrets-engine/registry_snapshot.json']
|
||||
|
||||
def sha(data):
|
||||
return 'sha256:' + hashlib.sha256(data).hexdigest()
|
||||
|
||||
def write_json(name, value):
|
||||
(HERE / name).write_text(json.dumps(value, indent=2) + '\n')
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--image-receipt', type=Path)
|
||||
args = parser.parse_args()
|
||||
assert args.image_receipt, 'verified separately pinned immutable image receipt required'
|
||||
receipt = json.loads(args.image_receipt.read_text())
|
||||
assert receipt['source_revision'] == IMAGE_REVISION
|
||||
assert receipt['ordinary_push'] is True and receipt['terminal_status'] == 'success'
|
||||
digest = receipt['manifest_digest']
|
||||
assert receipt['publisher_receipt']['revision'] == IMAGE_REVISION
|
||||
assert receipt['publisher_receipt']['manifest_digest'] == digest
|
||||
assert receipt['independent_public_registry_package']['explicit_revision_label'] == IMAGE_REVISION
|
||||
assert receipt['independent_public_registry_package']['sole_manifest_digest'] == digest
|
||||
assert receipt['immutable_image'] == 'forgejo.coulomb.social/coulomb/flex-auth@' + digest
|
||||
assert re.fullmatch(r'sha256:[0-9a-f]{64}', digest) and digest != 'sha256:' + '0' * 64
|
||||
overlay = {
|
||||
'image': {'repository': 'forgejo.coulomb.social/coulomb/flex-auth', 'digest': digest},
|
||||
'replicaCount': 1,
|
||||
'envelopeSigning': {'enabled': True, 'kid': 'flex-auth-lifecycle-20261016-r1',
|
||||
'secretName': 'flex-auth-secrets-engine-envelope-signing', 'secretKey': 'seed',
|
||||
'mountPath': '/var/run/secrets/decision-envelope-signing'},
|
||||
'outbox': {'enabled': True, 'source': 'flex-auth.secrets-engine',
|
||||
'mountPath': '/var/lib/flex-auth/outbox', 'size': '1Gi', 'maxBytes': 67108864,
|
||||
'storageClassName': 'local-path', 'existingClaim': ''},
|
||||
'auditDelivery': {'enabled': False},
|
||||
}
|
||||
(HERE / 'activation-values.proposed.yaml').write_text(yaml.safe_dump(overlay, sort_keys=False))
|
||||
stopped_overlay = dict(overlay, replicaCount=0)
|
||||
(HERE / 'stopped-values.proposed.yaml').write_text(yaml.safe_dump(stopped_overlay, sort_keys=False))
|
||||
archive = subprocess.run(['git', '-C', str(SOURCE), 'archive', REVISION, *PATHS],
|
||||
capture_output=True, check=True).stdout
|
||||
with tempfile.TemporaryDirectory(prefix='access-signer-rollout-r2-') as directory:
|
||||
source = Path(directory)
|
||||
with tarfile.open(fileobj=io.BytesIO(archive)) as tar:
|
||||
files = {m.name: sha(tar.extractfile(m).read()) for m in tar.getmembers() if m.isfile()}
|
||||
tar.extractall(source, filter='data')
|
||||
base = ['helm', 'template', 'flex-auth-secrets-engine', str(source / 'charts/flex-auth'),
|
||||
'--namespace', 'flex-auth', '-f', str(source / 'values/secrets-engine.yaml')]
|
||||
retained = subprocess.run(base, capture_output=True, check=True, text=True).stdout
|
||||
def render(replicas):
|
||||
return subprocess.run(base + ['-f', str(HERE / ('activation-values.proposed.yaml' if replicas else 'stopped-values.proposed.yaml'))], capture_output=True, check=True, text=True).stdout
|
||||
ready, stopped = render(1), render(0)
|
||||
# No PodTemplate mutation: Helm alone renders the maintenance state.
|
||||
(HERE / 'retained-source-render.yaml').write_text(retained)
|
||||
(HERE / 'activation-source-render.yaml').write_text(ready)
|
||||
(HERE / 'stopped-source-render.yaml').write_text(stopped)
|
||||
(HERE / 'source-render.diff').write_text(''.join(difflib.unified_diff(retained.splitlines(True),
|
||||
ready.splitlines(True), fromfile='retained-values-chart-dc0420', tofile='proposed-signer-image84-chart-dc0420')))
|
||||
# Call the actual committed Platform algorithm, rather than copy its projection.
|
||||
committed_native = subprocess.run(['git', '-C', str(NATIVE.parents[1]), 'show', PLATFORM_REVISION + ':scripts/flex_auth_signer_native.py'], capture_output=True, check=True).stdout
|
||||
assert sha(committed_native) == sha(NATIVE.read_bytes()) == NATIVE_SHA256
|
||||
sys.path.insert(0, str(NATIVE.parent))
|
||||
spec = importlib.util.spec_from_file_location('rollout_native_projection', NATIVE)
|
||||
native = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(native)
|
||||
docs = [d for d in yaml.safe_load_all(ready) if d]
|
||||
dep = next(d for d in docs if d['kind'] == 'Deployment')
|
||||
stopped_dep = next(d for d in yaml.safe_load_all(stopped) if d and d['kind'] == 'Deployment')
|
||||
projection = native.deployment_projection(dep)
|
||||
assert projection == native.deployment_projection(stopped_dep)
|
||||
normalized = json.loads(json.dumps(dep))
|
||||
normalized['spec']['replicas'] = 0
|
||||
assert normalized == stopped_dep
|
||||
assert sha((HERE.parent / 'rollout-r1/manifest.json').read_bytes()) == 'sha256:6b9292aab59f9ca8012be00f50027ded6a12018a3b36b011ef953d448e75e3dc'
|
||||
assert native.digest(native.encoded(projection)) == 'sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c'
|
||||
c = dep['spec']['template']['spec']['containers'][0]
|
||||
old = next(d for d in yaml.safe_load_all(retained) if d and d['kind'] == 'Deployment')
|
||||
oldc = old['spec']['template']['spec']['containers'][0]
|
||||
assert c['resources'] == oldc['resources']
|
||||
for flag in ['--caller-audience', '--caller-auth-mode', '--caller-binding', '--caller-kubernetes-url', '--policy', '--registry']:
|
||||
assert c['args'][c['args'].index(flag)+1] == oldc['args'][oldc['args'].index(flag)+1]
|
||||
assert dep['spec']['strategy'] == {'type': 'Recreate'}
|
||||
assert all(d['kind'] != 'Secret' for d in docs)
|
||||
assert all(d['kind'] != 'Ingress' for d in docs)
|
||||
other = lambda ds: [d for d in ds if d['kind'] not in ('Deployment', 'PersistentVolumeClaim')]
|
||||
assert other(docs) == other([d for d in yaml.safe_load_all(retained) if d])
|
||||
write_json('source-deployment-projection.json', projection)
|
||||
(HERE / 'source-projection.canonical.json').write_bytes(native.encoded(projection))
|
||||
for path in PATHS[2:]:
|
||||
image_bytes = subprocess.run(['git', '-C', str(SOURCE), 'show', IMAGE_REVISION + ':' + path], capture_output=True, check=True).stdout
|
||||
assert sha(image_bytes) == files[path], 'image and chart source policy/registry differ'
|
||||
write_json('render-evidence.json', {
|
||||
'schema': 'access-engine.signer-rollout-source-render.v2',
|
||||
'source_revision': REVISION, 'image_source_revision': IMAGE_REVISION,
|
||||
'platform_source_revision': PLATFORM_REVISION, 'source_files': files,
|
||||
'package_revision': 'd52f811ed5ec0be27c9c367e71d476125b3228be',
|
||||
'package_baseline': 'extraction2b/current05a; unchanged, not this activation successor',
|
||||
'image_state': 'separately-pinned-verified-ordinary-ci-source-candidate',
|
||||
'image_receipt_sha256': sha(args.image_receipt.read_bytes()),
|
||||
'source_rendered_projection_sha256': native.digest(native.encoded(projection)),
|
||||
'deployment_projection_sha256': native.digest(native.encoded(projection)),
|
||||
'projection_algorithm_sha256': sha(NATIVE.read_bytes()),
|
||||
'native_stopped_projection_verified': False,
|
||||
'native_admission': False, 'execution_authorized': False,
|
||||
'source_checks': {'both_states_actual_helm_render': True, 'caller_policy_registry_resources_unchanged': True,
|
||||
'nondeployment_resources_unchanged_except_new_pvc': True,
|
||||
'replicas0_and1_projection_equal': True, 'no_secret_generated': True},
|
||||
'artifacts': {name: sha((HERE / name).read_bytes()) for name in [
|
||||
'activation-values.proposed.yaml', 'stopped-values.proposed.yaml', 'source-projection.canonical.json', 'retained-source-render.yaml', 'activation-source-render.yaml',
|
||||
'stopped-source-render.yaml', 'source-render.diff', 'source-deployment-projection.json']},
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"schema": "access-engine.signer-rollout-source-render.v2",
|
||||
"source_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_source_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"platform_source_revision": "84c529f239c81e6d3ca337015700b03e3a862f53",
|
||||
"source_files": {
|
||||
"charts/flex-auth/Chart.yaml": "sha256:e8e00d968a8ba2783f81312cebe27f0315e29f0b663033886d4104bab6a1b455",
|
||||
"charts/flex-auth/templates/_helpers.tpl": "sha256:1e4a3ef486202b54d245060d2ee357880ee5b117732b2152bb4f75b489e0dc81",
|
||||
"charts/flex-auth/templates/deployment.yaml": "sha256:26e29618b9110bdd9d8aa73aae432a95c757a4f46e567ce4fe429c60bd519026",
|
||||
"charts/flex-auth/templates/networkpolicy.yaml": "sha256:53d8ae1851b66c8c9f990fc56bc8ad9076741e2684f39470a7e1583b093d9c14",
|
||||
"charts/flex-auth/templates/outbox-pvc.yaml": "sha256:284a78b0fd10537490f4f62e58c0cd85eb07b4222e932eb098c1bc5ddda8387d",
|
||||
"charts/flex-auth/templates/rbac.yaml": "sha256:07033364ec9624f25e0a4ebaac9c29bc25edac93fde2c514fd946596e428e580",
|
||||
"charts/flex-auth/templates/service.yaml": "sha256:9af858c02268d0492352ebe09efe7b6750711d48624a054b05e85707bf6a4e97",
|
||||
"charts/flex-auth/templates/serviceaccount.yaml": "sha256:a62caa647b4a55f0092214c6a200bd3a6f34fa97d8989c55a387429a487bd6c8",
|
||||
"charts/flex-auth/values.yaml": "sha256:0d5c3fa0c52d87ff6350d8f92527814b74bb8b7adadc92ded71856d9c83b1b03",
|
||||
"examples/secrets-engine/policy_package.md": "sha256:657fa9312c9dcabee059ec31c89ee13396fe9aa54d852edc9e6559a74bbc139a",
|
||||
"examples/secrets-engine/registry_snapshot.json": "sha256:37fba44ec0e0fd9b1e17a05ad1b7e4f9bb6ec9e0fc0bb3133e8af2ac6f832d7c",
|
||||
"values/secrets-engine.yaml": "sha256:567189d14467815a77df5ad7e0f22e7184c8e5bb9f814cbc0fbb99102b3cfd55"
|
||||
},
|
||||
"package_revision": "d52f811ed5ec0be27c9c367e71d476125b3228be",
|
||||
"package_baseline": "extraction2b/current05a; unchanged, not this activation successor",
|
||||
"image_state": "separately-pinned-verified-ordinary-ci-source-candidate",
|
||||
"image_receipt_sha256": "sha256:af8e032d28776722ccf2bfe0f884577e568d8d0fb3713aa869e1d7d1c77c576f",
|
||||
"source_rendered_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"deployment_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"projection_algorithm_sha256": "sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f",
|
||||
"native_stopped_projection_verified": false,
|
||||
"native_admission": false,
|
||||
"execution_authorized": false,
|
||||
"source_checks": {
|
||||
"both_states_actual_helm_render": true,
|
||||
"caller_policy_registry_resources_unchanged": true,
|
||||
"nondeployment_resources_unchanged_except_new_pvc": true,
|
||||
"replicas0_and1_projection_equal": true,
|
||||
"no_secret_generated": true
|
||||
},
|
||||
"artifacts": {
|
||||
"activation-values.proposed.yaml": "sha256:e76a30967add800ed8b588368757e7a5fa0ce4d8305ef658b5a4a08e377eb5b8",
|
||||
"stopped-values.proposed.yaml": "sha256:6e6f4bdd6ed1f9994f87e51b24186ba923515419b30d9c187c288f7db05e3a77",
|
||||
"source-projection.canonical.json": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"retained-source-render.yaml": "sha256:f979f7d05d5b0a54e3b8ac7c413aa4d401139f991b43412cdbde3d63249b0dd9",
|
||||
"activation-source-render.yaml": "sha256:b7edecb8ec50a6d2db7623a3d962dbece46de81d3809d5f73b3aca20ff76b8c7",
|
||||
"stopped-source-render.yaml": "sha256:03b631f0fe17c63494c14619199f69f2a2a9ab245d00f1ec441248868b24c071",
|
||||
"source-render.diff": "sha256:d510bbe9ff280f49f86ad67355774fbf76e32c36c129bd593b4be5b257dccd67",
|
||||
"source-deployment-projection.json": "sha256:056b6bf842713fb9a328dae901401d6867da47da68bfb8a4904bb0d7b8d9e912"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
---
|
||||
# Source: flex-auth/templates/networkpolicy.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
egress:
|
||||
- ports:
|
||||
- port: 443
|
||||
protocol: TCP
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: secrets-engine
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: secrets-engine
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
---
|
||||
# Source: flex-auth/templates/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
automountServiceAccountToken: false
|
||||
---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
rules:
|
||||
- apiGroups:
|
||||
- authentication.k8s.io
|
||||
resources:
|
||||
- tokenreviews
|
||||
verbs:
|
||||
- create
|
||||
---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: flex-auth-secrets-engine
|
||||
namespace: flex-auth
|
||||
---
|
||||
# Source: flex-auth/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: http
|
||||
---
|
||||
# Source: flex-auth/templates/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountName: flex-auth-secrets-engine
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
fsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: flex-auth
|
||||
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:05a03a8790c2210c48ea92391441c77ddf640d0cd32f5ec09838f5393171fcbd
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
- 0.0.0.0:8080
|
||||
- --registry
|
||||
- /opt/flex-auth/examples/secrets-engine/registry_snapshot.json
|
||||
- --policy
|
||||
- /opt/flex-auth/examples/secrets-engine/policy_package.md
|
||||
- --caller-audience
|
||||
- "flex-auth"
|
||||
- --caller-auth-mode
|
||||
- "enforce"
|
||||
- --caller-kubernetes-url
|
||||
- "https://10.43.0.1"
|
||||
- --caller-binding
|
||||
- "secrets-engine=system:serviceaccount:secrets-engine:secrets-engine"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 300m
|
||||
memory: 192Mi
|
||||
requests:
|
||||
cpu: 25m
|
||||
memory: 32Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
volumeMounts:
|
||||
- mountPath: /var/run/secrets/flex-auth-reviewer
|
||||
name: flex-auth-reviewer
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: flex-auth-reviewer
|
||||
projected:
|
||||
defaultMode: 0440
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
expirationSeconds: 3600
|
||||
path: token
|
||||
- configMap:
|
||||
name: kube-root-ca.crt
|
||||
items:
|
||||
- key: ca.crt
|
||||
path: ca.crt
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
{
|
||||
"service_account": "flex-auth-secrets-engine",
|
||||
"image": "forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"args": [
|
||||
"serve",
|
||||
"--addr",
|
||||
"0.0.0.0:8080",
|
||||
"--registry",
|
||||
"/opt/flex-auth/examples/secrets-engine/registry_snapshot.json",
|
||||
"--policy",
|
||||
"/opt/flex-auth/examples/secrets-engine/policy_package.md",
|
||||
"--envelope-signing-key-file",
|
||||
"/var/run/secrets/decision-envelope-signing/seed",
|
||||
"--envelope-signing-kid",
|
||||
"flex-auth-lifecycle-20261016-r1",
|
||||
"--outbox-max-bytes",
|
||||
"67108864",
|
||||
"--outbox-dir",
|
||||
"/var/lib/flex-auth/outbox",
|
||||
"--emission-source",
|
||||
"flex-auth.secrets-engine",
|
||||
"--caller-audience",
|
||||
"flex-auth",
|
||||
"--caller-auth-mode",
|
||||
"enforce",
|
||||
"--caller-kubernetes-url",
|
||||
"https://10.43.0.1",
|
||||
"--caller-binding",
|
||||
"secrets-engine=system:serviceaccount:secrets-engine:secrets-engine"
|
||||
],
|
||||
"volume_mounts": [
|
||||
{
|
||||
"mountPath": "/var/run/secrets/decision-envelope-signing",
|
||||
"name": "flex-auth-envelope-signing",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"mountPath": "/var/lib/flex-auth/outbox",
|
||||
"name": "flex-auth-outbox"
|
||||
},
|
||||
{
|
||||
"mountPath": "/var/run/secrets/flex-auth-reviewer",
|
||||
"name": "flex-auth-reviewer",
|
||||
"readOnly": true
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"name": "flex-auth-envelope-signing",
|
||||
"secret": {
|
||||
"secretName": "flex-auth-secrets-engine-envelope-signing",
|
||||
"defaultMode": 288,
|
||||
"items": [
|
||||
{
|
||||
"key": "seed",
|
||||
"path": "seed"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "flex-auth-outbox",
|
||||
"persistentVolumeClaim": {
|
||||
"claimName": "flex-auth-secrets-engine-outbox"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "flex-auth-reviewer",
|
||||
"projected": {
|
||||
"defaultMode": 288,
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3600,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"security_context": {
|
||||
"runAsNonRoot": true,
|
||||
"runAsUser": 65532,
|
||||
"runAsGroup": 65532,
|
||||
"fsGroup": 65532,
|
||||
"seccompProfile": {
|
||||
"type": "RuntimeDefault"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"args":["serve","--addr","0.0.0.0:8080","--registry","/opt/flex-auth/examples/secrets-engine/registry_snapshot.json","--policy","/opt/flex-auth/examples/secrets-engine/policy_package.md","--envelope-signing-key-file","/var/run/secrets/decision-envelope-signing/seed","--envelope-signing-kid","flex-auth-lifecycle-20261016-r1","--outbox-max-bytes","67108864","--outbox-dir","/var/lib/flex-auth/outbox","--emission-source","flex-auth.secrets-engine","--caller-audience","flex-auth","--caller-auth-mode","enforce","--caller-kubernetes-url","https://10.43.0.1","--caller-binding","secrets-engine=system:serviceaccount:secrets-engine:secrets-engine"],"image":"forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f","security_context":{"fsGroup":65532,"runAsGroup":65532,"runAsNonRoot":true,"runAsUser":65532,"seccompProfile":{"type":"RuntimeDefault"}},"service_account":"flex-auth-secrets-engine","volume_mounts":[{"mountPath":"/var/run/secrets/decision-envelope-signing","name":"flex-auth-envelope-signing","readOnly":true},{"mountPath":"/var/lib/flex-auth/outbox","name":"flex-auth-outbox"},{"mountPath":"/var/run/secrets/flex-auth-reviewer","name":"flex-auth-reviewer","readOnly":true}],"volumes":[{"name":"flex-auth-envelope-signing","secret":{"defaultMode":288,"items":[{"key":"seed","path":"seed"}],"secretName":"flex-auth-secrets-engine-envelope-signing"}},{"name":"flex-auth-outbox","persistentVolumeClaim":{"claimName":"flex-auth-secrets-engine-outbox"}},{"name":"flex-auth-reviewer","projected":{"defaultMode":288,"sources":[{"serviceAccountToken":{"expirationSeconds":3600,"path":"token"}},{"configMap":{"items":[{"key":"ca.crt","path":"ca.crt"}],"name":"kube-root-ca.crt"}}]}}]}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
--- retained-values-chart-dc0420
|
||||
+++ proposed-signer-image84-chart-dc0420
|
||||
@@ -44,6 +44,25 @@
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
automountServiceAccountToken: false
|
||||
---
|
||||
+# Source: flex-auth/templates/outbox-pvc.yaml
|
||||
+apiVersion: v1
|
||||
+kind: PersistentVolumeClaim
|
||||
+metadata:
|
||||
+ name: flex-auth-secrets-engine-outbox
|
||||
+ annotations:
|
||||
+ helm.sh/resource-policy: keep
|
||||
+ labels:
|
||||
+ app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
+ app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
+ app.kubernetes.io/part-of: flex-auth
|
||||
+spec:
|
||||
+ accessModes:
|
||||
+ - ReadWriteOnce
|
||||
+ storageClassName: "local-path"
|
||||
+ resources:
|
||||
+ requests:
|
||||
+ storage: "1Gi"
|
||||
+---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
@@ -106,6 +125,8 @@
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
+ strategy:
|
||||
+ type: Recreate
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
@@ -128,7 +149,7 @@
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: flex-auth
|
||||
- image: forgejo.coulomb.social/coulomb/flex-auth@sha256:05a03a8790c2210c48ea92391441c77ddf640d0cd32f5ec09838f5393171fcbd
|
||||
+ image: forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- serve
|
||||
@@ -138,6 +159,16 @@
|
||||
- /opt/flex-auth/examples/secrets-engine/registry_snapshot.json
|
||||
- --policy
|
||||
- /opt/flex-auth/examples/secrets-engine/policy_package.md
|
||||
+ - --envelope-signing-key-file
|
||||
+ - "/var/run/secrets/decision-envelope-signing/seed"
|
||||
+ - --envelope-signing-kid
|
||||
+ - "flex-auth-lifecycle-20261016-r1"
|
||||
+ - --outbox-max-bytes
|
||||
+ - "67108864"
|
||||
+ - --outbox-dir
|
||||
+ - "/var/lib/flex-auth/outbox"
|
||||
+ - --emission-source
|
||||
+ - "flex-auth.secrets-engine"
|
||||
- --caller-audience
|
||||
- "flex-auth"
|
||||
- --caller-auth-mode
|
||||
@@ -173,10 +204,25 @@
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
volumeMounts:
|
||||
+ - mountPath: "/var/run/secrets/decision-envelope-signing"
|
||||
+ name: flex-auth-envelope-signing
|
||||
+ readOnly: true
|
||||
+ - mountPath: "/var/lib/flex-auth/outbox"
|
||||
+ name: flex-auth-outbox
|
||||
- mountPath: /var/run/secrets/flex-auth-reviewer
|
||||
name: flex-auth-reviewer
|
||||
readOnly: true
|
||||
volumes:
|
||||
+ - name: flex-auth-envelope-signing
|
||||
+ secret:
|
||||
+ secretName: "flex-auth-secrets-engine-envelope-signing"
|
||||
+ defaultMode: 0440
|
||||
+ items:
|
||||
+ - key: "seed"
|
||||
+ path: seed
|
||||
+ - name: flex-auth-outbox
|
||||
+ persistentVolumeClaim:
|
||||
+ claimName: "flex-auth-secrets-engine-outbox"
|
||||
- name: flex-auth-reviewer
|
||||
projected:
|
||||
defaultMode: 0440
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
---
|
||||
# Source: flex-auth/templates/networkpolicy.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
egress:
|
||||
- ports:
|
||||
- port: 443
|
||||
protocol: TCP
|
||||
- port: 6443
|
||||
protocol: TCP
|
||||
ingress:
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
kubernetes.io/metadata.name: secrets-engine
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: secrets-engine
|
||||
ports:
|
||||
- port: 8080
|
||||
protocol: TCP
|
||||
---
|
||||
# Source: flex-auth/templates/serviceaccount.yaml
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
automountServiceAccountToken: false
|
||||
---
|
||||
# Source: flex-auth/templates/outbox-pvc.yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-outbox
|
||||
annotations:
|
||||
helm.sh/resource-policy: keep
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: "local-path"
|
||||
resources:
|
||||
requests:
|
||||
storage: "1Gi"
|
||||
---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
rules:
|
||||
- apiGroups:
|
||||
- authentication.k8s.io
|
||||
resources:
|
||||
- tokenreviews
|
||||
verbs:
|
||||
- create
|
||||
---
|
||||
# Source: flex-auth/templates/rbac.yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: flex-auth-secrets-engine-tokenreviewer
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: flex-auth-secrets-engine
|
||||
namespace: flex-auth
|
||||
---
|
||||
# Source: flex-auth/templates/service.yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
selector:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: http
|
||||
---
|
||||
# Source: flex-auth/templates/deployment.yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: flex-auth-secrets-engine
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
strategy:
|
||||
type: Recreate
|
||||
replicas: 0
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: flex-auth-secrets-engine
|
||||
app.kubernetes.io/instance: flex-auth-secrets-engine
|
||||
app.kubernetes.io/part-of: flex-auth
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
serviceAccountName: flex-auth-secrets-engine
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
fsGroup: 65532
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: flex-auth
|
||||
image: forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
- serve
|
||||
- --addr
|
||||
- 0.0.0.0:8080
|
||||
- --registry
|
||||
- /opt/flex-auth/examples/secrets-engine/registry_snapshot.json
|
||||
- --policy
|
||||
- /opt/flex-auth/examples/secrets-engine/policy_package.md
|
||||
- --envelope-signing-key-file
|
||||
- "/var/run/secrets/decision-envelope-signing/seed"
|
||||
- --envelope-signing-kid
|
||||
- "flex-auth-lifecycle-20261016-r1"
|
||||
- --outbox-max-bytes
|
||||
- "67108864"
|
||||
- --outbox-dir
|
||||
- "/var/lib/flex-auth/outbox"
|
||||
- --emission-source
|
||||
- "flex-auth.secrets-engine"
|
||||
- --caller-audience
|
||||
- "flex-auth"
|
||||
- --caller-auth-mode
|
||||
- "enforce"
|
||||
- --caller-kubernetes-url
|
||||
- "https://10.43.0.1"
|
||||
- --caller-binding
|
||||
- "secrets-engine=system:serviceaccount:secrets-engine:secrets-engine"
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
periodSeconds: 5
|
||||
resources:
|
||||
limits:
|
||||
cpu: 300m
|
||||
memory: 192Mi
|
||||
requests:
|
||||
cpu: 25m
|
||||
memory: 32Mi
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
volumeMounts:
|
||||
- mountPath: "/var/run/secrets/decision-envelope-signing"
|
||||
name: flex-auth-envelope-signing
|
||||
readOnly: true
|
||||
- mountPath: "/var/lib/flex-auth/outbox"
|
||||
name: flex-auth-outbox
|
||||
- mountPath: /var/run/secrets/flex-auth-reviewer
|
||||
name: flex-auth-reviewer
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: flex-auth-envelope-signing
|
||||
secret:
|
||||
secretName: "flex-auth-secrets-engine-envelope-signing"
|
||||
defaultMode: 0440
|
||||
items:
|
||||
- key: "seed"
|
||||
path: seed
|
||||
- name: flex-auth-outbox
|
||||
persistentVolumeClaim:
|
||||
claimName: "flex-auth-secrets-engine-outbox"
|
||||
- name: flex-auth-reviewer
|
||||
projected:
|
||||
defaultMode: 0440
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
expirationSeconds: 3600
|
||||
path: token
|
||||
- configMap:
|
||||
name: kube-root-ca.crt
|
||||
items:
|
||||
- key: ca.crt
|
||||
path: ca.crt
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/flex-auth
|
||||
digest: sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f
|
||||
replicaCount: 0
|
||||
envelopeSigning:
|
||||
enabled: true
|
||||
kid: flex-auth-lifecycle-20261016-r1
|
||||
secretName: flex-auth-secrets-engine-envelope-signing
|
||||
secretKey: seed
|
||||
mountPath: /var/run/secrets/decision-envelope-signing
|
||||
outbox:
|
||||
enabled: true
|
||||
source: flex-auth.secrets-engine
|
||||
mountPath: /var/lib/flex-auth/outbox
|
||||
size: 1Gi
|
||||
maxBytes: 67108864
|
||||
storageClassName: local-path
|
||||
existingClaim: ''
|
||||
auditDelivery:
|
||||
enabled: false
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"session_id": 79088,
|
||||
"exit_code": 0,
|
||||
"source_revision": "50de8be7f9c03e22ccd377ebd64c54171ecd2248",
|
||||
"summary": {
|
||||
"fail": 0,
|
||||
"automation_error": 0,
|
||||
"warn": 7,
|
||||
"info": 4
|
||||
},
|
||||
"bindings": "89/89",
|
||||
"pushed": true,
|
||||
"generated_only_commit_refused": true,
|
||||
"unrelated_staging_preserved": true,
|
||||
"native_acceptance": false
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"checked_at": "2026-10-16T18:36:16.650310+00:00",
|
||||
"rollout_r2": {
|
||||
"manifest_sha256": "sha256:5be7a7f438624dcb35b7dbc96e7c9e5a8e2d5d1b1966cb4338aa5aecbe3a8b59",
|
||||
"all_manifest_hashes_verified": true,
|
||||
"fresh_root_helm_renders_byte_identical": true,
|
||||
"chart_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"projection": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"source_only": true,
|
||||
"native_fence": false
|
||||
},
|
||||
"platform_p4": {
|
||||
"manifest_sha256": "sha256:9eec861838a8e9138f2c821cff3014998fbe74bb01447642bf50d44e8b3b7cb3",
|
||||
"all_manifest_hashes_verified": true,
|
||||
"root_p3_assembler_tests": 8,
|
||||
"p4_executor_tests_scope_byte_identical": true,
|
||||
"p3_finding": "README stale cluster controller ownership corrected in preserved P4 successor",
|
||||
"native_authority_fields_null": true,
|
||||
"approval_authenticated": false
|
||||
},
|
||||
"closed_tsa_gates": 0
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# Exact Platform custody packet P4
|
||||
|
||||
`RPF35-PDP-SIGNER-NATIVE-PACKET-20261016-P4` proposes one attended bootstrap under native action `RPF35-PDP-SIGNER-NATIVE-20261016-R1`. It selects the existing legacy flex-auth repository's immutable candidate `forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f`, source `84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0`. Ordinary publisher402 and both Smoke401 jobs succeeded; independent public package metadata reports the same sole digest and explicit revision label. P1/P2 candidate/source/review and failed400 evidence stay unchanged. Candidate provenance grants no runtime/custody/trust admission.
|
||||
|
||||
`evidence-pins.json` binds exact committed Platform R5 `84c529f239c81e6d3ca337015700b03e3a862f53` source modules/plan, installed routing receipt, published candidate and local package d52/tree d4fb. Package baseline2b/current05a remains frozen; its local draft resolution is not adoption of84 or signer activation. `admission-scope.incomplete.json` is approval-free preparation and intentionally cannot execute. Missing nulls require the separate inputs below. Proposed failclosed pre-key consumer baseline and source projection, if filled, are pinned for review; they do not attest live installation or actual native fence. No new public key/fingerprint exists before custody.
|
||||
|
||||
## Next actual scoped owner-review inputs
|
||||
|
||||
1. Platform + founder: independently disposition exact CCR0050/read-policy/role/delivery scope and distinct one-use CAS0 writer scope. Current CCR remains proposed with bound_claims_confirmed=false; its current hash is evidence only and is not inserted as an approved CCR hash. After separately authorized apply/readback, bind exact approved/binding-confirmed bytes in ccr_sha256. Verify dedicated ESO SA/namespace/audience, exact policy, role15m ttl/max/explicit-max/no-default, no metadata/list/sibling/write grants. Source status edits are not native binding evidence.
|
||||
2. Access (workload/Helm), Platform (GitOps Application/sync-freeze integration), and cluster-runtime-storage-owner (runtime/storage/headroom), each within its separate scope: review exact P4 rollout source render and candidate image/kid/caller/mount/security/outbox values. Approve actual stopped deployment/frozen competing writers, stopped consumer, zero signer-SA/seed-mount/owned or terminating pods, no HPA, all owned ReplicaSets0 and deployment observed generation caught up. Supply authenticated exact future native deployment_projection artifact computed by the committed projection function and show it equals the proposed hash. A local source projection cannot establish these current observations. Supply exclusive-window artifact/hash naming founder executor/abort owner, competing controllers, readiness120s abort and recovery10m holdfenced. PVC1Gi/local-path/Helmkeep plus actual dynamically bound PV Retain, headroom/server-dry-run/client-diff and rollback are distinct approvals.
|
||||
3. Secrets: review exact built-wheel/helper/verifier/config/empty-trust baseline and planned install location. Pre-key empty trust is proposed failclosed and grants no signer acceptance. After authenticating Platform's public receipt, independently admit new key/kid/publickey fingerprint and successor trust, never discover from KV/responder. Fingerprint is SHA256 of canonical unpadded base64url public-key ASCII43bytes. Bounded TokenRequest/callerfile custody/installed trust/named-pod literal-loopback session remain separate approvals; no session is minted here.
|
||||
4. Founder/Platform: independently identify exact non-root OpenBao founder entity UUID, trusted runtime/dependencies/private custody directory, exact fixed command and admission file hash. No agent token lookup/login is required to prepare it. The child later verifies auth/netkingdom/platform-admin/entity and backend identity. Existing supervised record and Warden containment do not establish same-UID hostile-code isolation.
|
||||
5. Five distinct owner dispositions (Platform, Access, Secrets, cluster-runtime-storage-owner, founder) must bind the completed approval-free scope SHA256, including exact approved CCR, source/image/projection/trust/window/expiry/entity. Platform's packet assent is preparation only. Collect actual external reference strings after their reviews; never manufacture them. Founder disposition must approve the exact private file hash and command/source plus high-risk custody/outage/loss scope.
|
||||
6. Select a future absolute UTC expires_at after coordinating the ceremony, not by auto-filling now+120. Reviews may finish before its window. Warden OIDC precedes child without proven timing bound; child must start at5<remaining<=120s, aim near120s. Native fixed path26 calls each capped2s (52s) plus local work, all under remaining absolute time. Too early/late, changed bytes or inadequate remaining time refuses; new expiry changes scope and needs new explicit dispositions. No post-login refresh, TTL widening or start-only reinterpretation.
|
||||
|
||||
## Final artifact and execution shape
|
||||
|
||||
Complete scope only from authenticated owner evidence. `finalize.py` is an offline assembler, not an approval authenticator; it rejects changed fixed candidate/source/lifecycle pins and selected baseline/projection pins, mismatched five external scope references and existing/symlink output. It creates0600 under permissive umask, flushes/fsyncs, and reports exact file SHA256. Native admission/source validation remains authoritative, including fresh expiry/CCR/native identity/fence checks. Keep input/output in an owner-private0700 directory outside Git. Do not submit this incomplete scope or synthetic test references as execution inputs.
|
||||
|
||||
After all scopes are actually approved, the exact argv shape to review is:
|
||||
|
||||
`warden access openbao-platform-admin-login --exec -- python3 /home/worsch/railiance-platform/scripts/flex_auth_signer_native.py --admission ABSOLUTE_OWNER_PRIVATE_APPROVED_FILE --admission-sha256 EXACT_APPROVED_FILE_SHA256 --receipt-directory /home/worsch/.local/state/railiance-platform/flex-auth-envelope-signing`
|
||||
|
||||
The two uppercase arguments remain ceremony outputs; no command is ready until established. Founder performs attended OIDC from their terminal; child is silent. Warden printed completion/revocation result is authoritative beyond exit code. No private seed, session or custody directory becomes shared intake. Expected result is independently authenticated public-only durable receipt with version1/kid/publickey/fingerprint, exact executed lineage and fence/readback; independent consumer trust and rollout proofs still follow.
|
||||
|
||||
## Verification, rollback, costs and risk
|
||||
|
||||
Target primary/railiance01 kube-system `a553c742-0115-43d4-99a4-a5ca56fe0786`, OpenBao `fd28df5d-98ec-57dd-42ec-9b3e4f4e53bf`, fixed loopback18200. One fixed metadata setup, in-memory Ed25519 seed CAS0 and exact version1 private correspondence readback; seed never crosses output/argv/env/local files. Final durable receipt/source/CCR/metadata/public correspondence must all verify before custody success; success still waits independent public admission.
|
||||
|
||||
Founder owns abort disposition. Platform reconciles custody and owns existing GitOps Application sync/freeze and restoration. Access owns signer workload/Helm stop and release rollback, with Secrets separately owning consumer stop/failclosed and trust disposition. The cluster runtime/storage owner owns runtime/storage/PV scope and retention review; it owns neither workload/Helm nor GitOps Application controllers. Enablement is required only for an actual separately proposed ArgoCD installation/controller configuration change, excluded here. Before CAS abort preserves intent/fence. Any ambiguous metadata/write/readback/fsync remains unknown; no retry/remint. Fresh R2 read-only recovery binds immutable original receipt and original/current lineages: current absent, metadata-only0 and seed1 results do not rewrite historical unknown. Metadata-only confirmation does not authorize bootstrap; subsequent write needs separately reviewed source/action. No automatic cleanup/seed restoration/rotation.
|
||||
|
||||
Access rollback stops the workload writer, preserves outbox/cursor/receipts, verifies lock release and restores only separately reviewed format-compatible prior workload image/Helm values. Platform separately restores reviewed GitOps Application/sync-freeze state when safe; the cluster owner preserves PVC/PV and reviews runtime/storage retention. Secrets keeps the consumer failclosed and separately owns any reviewed trust restoration. Prior unsigned05a cannot satisfy strict signed consumer trust; holdfailclosed. On compromise Secrets withdraws online trust and keeps its consumer failclosed; Access stops/fences signer workload, Platform holds relevant GitOps Application sync/freeze, and the cluster owner preserves runtime/storage/PV evidence. Platform custody proceeds only through a separately reviewed forward-only successor. Never restore compromised seed.
|
||||
|
||||
Preparation and Platform custody add EUR0 infrastructure/no new resource. Access's separate proposed1Gi local-path PVC is not quota/backup/node-loss durability; current StorageClass Delete/WaitForFirstConsumer requires actual binding/PV Retain disposition before durable acceptance. Outbox source64MiB/OS-lock hardening is published, native behavior remains unaccepted. Seed compromise may forge lifecycle decisions; controlled outage/local evidence loss remain high-risk. No monetary risk ceiling or autopilot grant exists; founder must explicitly disposition this exact risk/resource scope. No taskpilot/audit egress/new public package/standing writer permission is included.
|
||||
|
||||
Platform disposition: approve P4 preparation/source evidence selection for independent review only. Native execution, custody activation and other-owner dispositions remain withheld.
|
||||
|
||||
## Corrected authority boundary and source lineage
|
||||
|
||||
Platform R5 commit `84c529f239c81e6d3ca337015700b03e3a862f53` replaces the conflated historical review role with `cluster-runtime-storage-owner`. No frozen P1/P2/P3 disposition is reinterpreted. Platform owns custody/read-lane and existing GitOps Application/sync-freeze integration; Access owns workload/Helm release semantics and freeze of competing workload writers; cluster reviews runtime/storage/headroom/PV retention only. Enablement reviews only a separately proposed actual ArgoCD installation/controller configuration change, excluded here. New exact scope requires corrected five-role dispositions; none are supplied.
|
||||
|
||||
Image source Git revision84c78e0 and chart source Git revisiondc0420 are separate identities; successful image CI does not authenticate a chart pin or stopped native fence. RolloutR2 supplies the final reviewed source projection only. Actual founder entity, absolute expiry, held exclusive-window and native dispositions remain null. Actual native fence evidence is explicitly null in evidence-pins, even when the source projection hash is preselected for exact review. Approved CCR bytes remain null until actual approval/binding evidence exists.
|
||||
|
||||
Final rolloutR2 manifest `sha256:5be7a7f438624dcb35b7dbc96e7c9e5a8e2d5d1b1966cb4338aa5aecbe3a8b59` verified in full. Canonical source projection `sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c` is preselected for proposed scope. Chart Git revision `dc042022f7c30671cf0a7605cf43ef6d96d04242` renders actual source replicas0 and1; image Git revision84 and immutable09a83b remain independently pinned. The old R1 maintenance-stop limitation is superseded by source chartR2 capability only; no native stop was performed. Held window remains false and native stopped fence absent; incomplete window draft cannot fill the admission window hash.
|
||||
|
||||
## P4 responsibility reconciliation
|
||||
|
||||
P4 corrects P3 prose that assigned controllers generically to cluster. P3 remains frozen as the original finding. No executor, admission scope, image/chart/source/CCR/projection/trust pin or native role changed. Every rollback/freeze statement now assigns workload/Helm to Access, GitOps Application/sync-freeze to Platform, runtime/storage/PV to cluster, and consumer/trust to Secrets. Enablement is conditional on actual installation/controller configuration changes, not a blanket reviewer. Preparation does not establish any live approval or held fence.
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"schema": "railiance-platform.signer-native-admission.v1",
|
||||
"action": "bootstrap",
|
||||
"operation_id": "RPF35-PDP-SIGNER-NATIVE-20261016-R1",
|
||||
"kid": "flex-auth-lifecycle-20261016-r1",
|
||||
"expires_at": null,
|
||||
"founder_entity_id": null,
|
||||
"ccr_sha256": null,
|
||||
"source_bundle": {
|
||||
"scripts/flex_auth_signer_native.py": "sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f",
|
||||
"scripts/flex_auth_signer_custody.py": "sha256:f169ad12f90d729b647085c3bed2c0d8d005db23a2341b6d3d5f1793bcfd110c",
|
||||
"scripts/task_execution_native_fixture.py": "sha256:6d4e4132cd749aafd07c608c261902a2c347a9782f51fe275466f5bb800c68e8",
|
||||
"scripts/task_execution_journal.py": "sha256:604cf285286a8a1be23d9bc0d8a547bd1195b7f80286778e1d4f30c711fd6a7e",
|
||||
"scripts/task_execution_recovery.py": "sha256:910f38919a8b6f57591366a2ef4da40d1ed7dfd7556c845a4b89496eca39ce1c",
|
||||
"scripts/credential-change.py": "sha256:54ca1bc33ed4bb7807917f71ed45b6b35da978bc789e013386e1e90a20bee06d"
|
||||
},
|
||||
"bindings": {
|
||||
"proposal_sha256": "sha256:22306d50e082fc35c5ff22c31e739a53c7584176969063f7907bc01d77e506e5",
|
||||
"executed_revision_sha256": "sha256:addde682d0e1993f665d05e66dcd9ab56ead72f0b85f292201a46ea494e56b71",
|
||||
"deployment_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"image_sha256": "sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"policy_sha256": "sha256:bd11c5fe77ce6439c65fea225ad6b71d2110efc5e7b5bc9b499c59cd0a53b8b4",
|
||||
"trust_sha256": "sha256:72521ff7729f8ddf5176092f3949cd50ac5f9241b0a5d1d30f3c63ce1d83091b"
|
||||
},
|
||||
"producer_image": "forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"caller_binding": "secrets-engine=system:serviceaccount:secrets-engine:secrets-engine",
|
||||
"deployment_projection_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"authority": "founder-attended-exact-source-scope; no standing grant",
|
||||
"routing": {
|
||||
"lane_id": "openbao-platform-admin-login",
|
||||
"verdict": "founder_required",
|
||||
"founder_act": "oidc_login",
|
||||
"receipt_sha256": "sha256:31df44742dc1abc37c6cb13554eacb37b8c0cabe9e2e4d23908e03d80c6ba238"
|
||||
},
|
||||
"exclusive_window_sha256": null,
|
||||
"consumer_trust_sha256": "sha256:72521ff7729f8ddf5176092f3949cd50ac5f9241b0a5d1d30f3c63ce1d83091b",
|
||||
"original_receipt_sha256": null,
|
||||
"original_execution": null
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
"schema": "railiance-platform.native-packet-preparation.v1",
|
||||
"proposal_id": "RPF35-PDP-SIGNER-NATIVE-PACKET-20261016-P4",
|
||||
"state": "incomplete preparation; never pass to native executor",
|
||||
"platform_commit": "84c529f239c81e6d3ca337015700b03e3a862f53",
|
||||
"source_bundle": {
|
||||
"scripts/flex_auth_signer_native.py": "sha256:4fb9ce6608ad04c4f5dc98a95796dc88a08a2453dc15c0d40c5c688fc02f573f",
|
||||
"scripts/flex_auth_signer_custody.py": "sha256:f169ad12f90d729b647085c3bed2c0d8d005db23a2341b6d3d5f1793bcfd110c",
|
||||
"scripts/task_execution_native_fixture.py": "sha256:6d4e4132cd749aafd07c608c261902a2c347a9782f51fe275466f5bb800c68e8",
|
||||
"scripts/task_execution_journal.py": "sha256:604cf285286a8a1be23d9bc0d8a547bd1195b7f80286778e1d4f30c711fd6a7e",
|
||||
"scripts/task_execution_recovery.py": "sha256:910f38919a8b6f57591366a2ef4da40d1ed7dfd7556c845a4b89496eca39ce1c",
|
||||
"scripts/credential-change.py": "sha256:54ca1bc33ed4bb7807917f71ed45b6b35da978bc789e013386e1e90a20bee06d"
|
||||
},
|
||||
"native_plan_sha256": "sha256:22306d50e082fc35c5ff22c31e739a53c7584176969063f7907bc01d77e506e5",
|
||||
"current_proposed_ccr_sha256": "sha256:44bbbf4aff84c3b085afdb14708106fd9a12ac03a0c47774913931a87fb94ada",
|
||||
"ccr_state": "proposed; bound_claims_confirmed false; intentionally not substituted for approved CCR pin",
|
||||
"published_image_candidate": {
|
||||
"schema": "access-engine.ordinary-ci-published-candidate.v1",
|
||||
"observed_at": "2026-10-16T17:55:53.102623+00:00",
|
||||
"source_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"ordinary_push": true,
|
||||
"run_url": "https://forgejo.coulomb.social/coulomb/access-engine/actions/runs/402",
|
||||
"job_url": "https://forgejo.coulomb.social/coulomb/access-engine/actions/runs/402/jobs/0",
|
||||
"terminal_status": "success",
|
||||
"latest_commit_statuses": [
|
||||
{
|
||||
"id": 6,
|
||||
"status": "success",
|
||||
"context": "Build and Publish Container Image / build-and-push (push)",
|
||||
"description": "Successful in 58s",
|
||||
"target_url": "/coulomb/access-engine/actions/runs/402/jobs/0",
|
||||
"created_at": "2026-10-16T17:55:15Z",
|
||||
"updated_at": "2026-10-16T17:55:15Z"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"status": "success",
|
||||
"context": "CI Smoke / container-smoke (push)",
|
||||
"description": "Successful in 2s",
|
||||
"target_url": "/coulomb/access-engine/actions/runs/401/jobs/1",
|
||||
"created_at": "2026-10-16T17:54:17Z",
|
||||
"updated_at": "2026-10-16T17:54:17Z"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"status": "success",
|
||||
"context": "CI Smoke / host-smoke (push)",
|
||||
"description": "Successful in 0s",
|
||||
"target_url": "/coulomb/access-engine/actions/runs/401/jobs/0",
|
||||
"created_at": "2026-10-16T17:54:14Z",
|
||||
"updated_at": "2026-10-16T17:54:14Z"
|
||||
}
|
||||
],
|
||||
"registry_repository": "forgejo.coulomb.social/coulomb/flex-auth",
|
||||
"immutable_image": "forgejo.coulomb.social/coulomb/flex-auth@sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"manifest_digest": "sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"publisher_receipt": {
|
||||
"mode": "legacy",
|
||||
"revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"manifest_digest": "sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"verified_repositories": 1,
|
||||
"pulled_revision_label_check": "Passed by reviewed publisher before this final receipt; exact84 source script captured in source-facts.json.",
|
||||
"logs_url": "https://forgejo.coulomb.social/coulomb/access-engine/actions/runs/402/jobs/0/logs",
|
||||
"response_sha256": "e86883ca7b2d2c4fd9dc63be49b6840ea6e2e6f03807c97e0af52825631a8e42",
|
||||
"raw_log_retained": false
|
||||
},
|
||||
"independent_public_registry_package": {
|
||||
"url": "https://forgejo.coulomb.social/coulomb/-/packages/container/flex-auth/main-84c78e0",
|
||||
"http_status": 200,
|
||||
"sole_manifest_digest": "sha256:09a83b273740133518cc7e7915fb211381e06545d347d2dd1974042525ac981f",
|
||||
"explicit_revision_label": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"response_sha256": "4e7b2487509b1e58d12388db2a4c48b0c9c2df88ceaeeb53fde2d79ded5c677b"
|
||||
},
|
||||
"scope": {
|
||||
"published_by": "Existing normal main-push legacy publisher, not observer",
|
||||
"observer_actions": "Anonymous public metadata reads only; no dispatch/push/credential/login/deploy/trust operation.",
|
||||
"native_admitted": false,
|
||||
"limits": "Published source/image provenance is verified; exact runtime package/config/mount/caller/trust/record/PVC and owner scope admission remain separate.",
|
||||
"package_extraction_unchanged": "source2b064ee/current05a frozen; future84 adoption is a separate reviewed package/config revision.",
|
||||
"historical_failure_retained": "../image-0a05383/normal-ci-run400-failure.json"
|
||||
}
|
||||
},
|
||||
"managed_package": {
|
||||
"schema": "custodian.local-canonical-package.v1",
|
||||
"destination": "/home/worsch/rapp-flex-auth-secrets-engine",
|
||||
"commit": "d52f811ed5ec0be27c9c367e71d476125b3228be",
|
||||
"tree": "d4fbad71bdc8ef870603526ccd1f53195d0322af",
|
||||
"archive_sha256": "sha256:766279e86749bde4e25aafcb3989134e9879564667dd46a55be29bc995f66d8d",
|
||||
"files_sha256": {
|
||||
".repo-classification.yaml": "sha256:99a5c80dda99a732563dbb64b8ce8b8663d9d619b919f9fed96cb7a63598fbb4",
|
||||
"AGENTS.md": "sha256:a02928b531ce61765bfb09bb1abea548ddcb589ecef7c762a1851d8e7745c7c7",
|
||||
"CLAUDE.md": "sha256:70f13f7bdd8c420fe2820ac879e464e7333c4547a5b0adf1b5e5a7a14113fa00",
|
||||
"INTENT.md": "sha256:a40ff791a4070bcdc59b7f889412d2558c5cd943308890bc0bf0690ea78c3f67",
|
||||
"README.md": "sha256:d8f096b22d4e67ce6eb2a2e201720fbbf3bc54059fec98ddf3f6ec4229087361",
|
||||
"SCOPE.md": "sha256:6167744e2b3f4b82a38f4950463068966fe595c7d62d3674813a0e8ed66789de",
|
||||
"declarations/rapp.yaml": "sha256:0b722431bc5162dd86f72b15f12424e149aca8f2a8790adf2c57e8511ea73b4c",
|
||||
"docs/operations.md": "sha256:690c2140d86c68edcc09d9c9acda10f0a4f14723c4236d02dd9f832e74651d6e",
|
||||
"source-pin.json": "sha256:d28e8ce2f83ebb8dd8bfd2cd03d8308405d189a77d05f7294439ba1da31e1818",
|
||||
"tests/test_render.py": "sha256:5e7cfe42249eda989813275b5cd307e7a2b0be9696443e566d30578b720c8c6a",
|
||||
"tools/render.py": "sha256:93ca85ddd8036952ae98e31ac1f36ebfb1ac9ad0a2f73b1e90dcf067f4ae544c",
|
||||
"workplans/README.md": "sha256:29f2194b1cf0981172cd28928f74224c72778c1771413006a92e4b4ed8214511",
|
||||
"workplans/archived/.gitkeep": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"clean": true,
|
||||
"remote_configured": false,
|
||||
"published": false,
|
||||
"native_accepted": false,
|
||||
"scope": "Reviewed source package locally committed; resolver validation recorded separately. No placement, custody, trust or runtime admission."
|
||||
},
|
||||
"routing_receipt_sha256": "sha256:31df44742dc1abc37c6cb13554eacb37b8c0cabe9e2e4d23908e03d80c6ba238",
|
||||
"supersession": "P4 corrects rollback responsibility prose only; PlatformR5, image84/chartdc0420, proposed baseline/projection/native action scope and executor unchanged. Frozen P1/P2/P3 and refusal history preserved; no native approval inferred.",
|
||||
"execution_authorized": false,
|
||||
"native_accepted": false,
|
||||
"credentials_requested_or_read": false,
|
||||
"incremental_infrastructure_spend_eur": 0,
|
||||
"predecessor": {
|
||||
"proposal_id": "RPF35-PDP-SIGNER-NATIVE-PACKET-20261016-P3",
|
||||
"manifest_sha256": "sha256:f23c8f63ebcf62f161c63e5899251e4869f6977377321c0f35732537c21c0160",
|
||||
"preserved": true
|
||||
},
|
||||
"candidate_manifest_sha256": "sha256:4f71eec333ee9bea798f22dc9190a08e0c3251f2f303d6bec636d1e82842efa5",
|
||||
"candidate_receipt_sha256": "sha256:af8e032d28776722ccf2bfe0f884577e568d8d0fb3713aa869e1d7d1c77c576f",
|
||||
"source_projection_selection": {
|
||||
"manifest_sha256": "sha256:5be7a7f438624dcb35b7dbc96e7c9e5a8e2d5d1b1966cb4338aa5aecbe3a8b59",
|
||||
"path": "docs/changes/netkingdom-target-2026-10-16/access-native-admission/rollout-r2",
|
||||
"projection_native_encoded_sha256": "sha256:8ce375f065552c551538f3acc7300c427407057eeff1d0b43755bfdf8a46169c",
|
||||
"canonical_projection_file": "source-projection.canonical.json",
|
||||
"chart_source_revision": "dc042022f7c30671cf0a7605cf43ef6d96d04242",
|
||||
"image_source_revision": "84c78e072c8f3daf2bc3b90f8efc8fbeb16c3cf0",
|
||||
"state": "proposed exact Helm-rendered0/1 source projection only; actual stopped native fence absent",
|
||||
"held_exclusive_window": false,
|
||||
"exclusive_window_sha256": null,
|
||||
"incomplete_window_proposal_sha256": "sha256:15a063dfe1b4237c458ce3e12ec1a19e87bf2a3b98f97fbe7dcdcdb8d121a675",
|
||||
"source_projection_module_platform_revision": "84c529f239c81e6d3ca337015700b03e3a862f53"
|
||||
},
|
||||
"consumer_baseline_selection": {
|
||||
"manifest_sha256": "sha256:7f4a49064b459a3b087943a00241eb9f744e3768f5c4139d1821d799ff2e584a",
|
||||
"consumer_baseline_sha256": "sha256:72521ff7729f8ddf5176092f3949cd50ac5f9241b0a5d1d30f3c63ce1d83091b",
|
||||
"path": "docs/changes/netkingdom-target-2026-10-16/decision-native-preparation/consumer-admission-r1",
|
||||
"state": "proposed pre-key empty-trust source/config baseline only; no live installation, public key, post-key trust or owner approval"
|
||||
},
|
||||
"actual_native_fence_receipt": null,
|
||||
"native_owner_reviews": null,
|
||||
"native_expires_at": null,
|
||||
"founder_entity_id": null,
|
||||
"corrected_owner_roles": [
|
||||
"founder",
|
||||
"railiance-platform-owner",
|
||||
"access-engine-owner",
|
||||
"secrets-engine-owner",
|
||||
"cluster-runtime-storage-owner"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
"""Offline assembler only. Receives externally reviewed facts; never approves or executes."""
|
||||
import hashlib,json,os,sys
|
||||
from pathlib import Path
|
||||
|
||||
def enc(x): return json.dumps(x,sort_keys=True,separators=(',',':'),allow_nan=False).encode()
|
||||
def digest(x): return 'sha256:'+hashlib.sha256(x).hexdigest()
|
||||
def contains_null(x):
|
||||
if isinstance(x,dict): return any(contains_null(v) for k,v in x.items() if k not in {'original_receipt_sha256','original_execution'})
|
||||
if isinstance(x,list): return any(map(contains_null,x))
|
||||
return x is None
|
||||
base=Path(__file__).parent
|
||||
if len(sys.argv)!=4: raise SystemExit('Usage: finalize.py complete-scope.json external-reviews.json output.json')
|
||||
scope=json.loads(Path(sys.argv[1]).read_text()); template=json.loads((base/'admission-scope.incomplete.json').read_text())
|
||||
if set(scope)!=set(template) or contains_null(scope): raise SystemExit('incomplete/extraneous scope')
|
||||
for name in ('schema','action','operation_id','kid','source_bundle','producer_image','caller_binding','authority','routing','original_receipt_sha256','original_execution'):
|
||||
if scope[name]!=template[name]: raise SystemExit('changed prepared scope requires new preparation review: '+name)
|
||||
for name in ('consumer_trust_sha256','deployment_projection_sha256'):
|
||||
if template[name] is not None and scope[name]!=template[name]: raise SystemExit('changed selected baseline requires new preparation review: '+name)
|
||||
for name in ('proposal_sha256','executed_revision_sha256','image_sha256','policy_sha256'):
|
||||
if scope['bindings'][name]!=template['bindings'][name]: raise SystemExit('changed binding requires new preparation review: '+name)
|
||||
if scope['bindings']['deployment_sha256']!=scope['deployment_projection_sha256'] or scope['bindings']['trust_sha256']!=scope['consumer_trust_sha256']: raise SystemExit('binding correspondence')
|
||||
reviews=json.loads(Path(sys.argv[2]).read_text())
|
||||
if set(reviews)!={'founder','railiance-platform-owner','access-engine-owner','secrets-engine-owner','cluster-runtime-storage-owner'}: raise SystemExit('distinct external dispositions required')
|
||||
for review in reviews.values():
|
||||
if set(review)!={'approved_admission_sha256','approval_ref'} or review['approved_admission_sha256']!=digest(enc(scope)) or not review['approval_ref']: raise SystemExit('external review does not bind scope')
|
||||
admission=dict(scope,owner_reviews=reviews); raw=enc(admission)+b'\n'
|
||||
# Native validator remains authoritative, including fresh expiry and approved CCR checks.
|
||||
fd=os.open(sys.argv[3],os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
|
||||
with os.fdopen(fd,'wb') as out:
|
||||
os.fchmod(out.fileno(),0o600)
|
||||
out.write(raw)
|
||||
out.flush()
|
||||
os.fsync(out.fileno())
|
||||
print(json.dumps({'scope_sha256':digest(enc(scope)),'admission_file_sha256':digest(raw),'authority':'No approval authenticated by assembler; external governance and native validation still required'}))
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"schema": "railiance-platform.native-packet-preparation-manifest.v1",
|
||||
"proposal_id": "RPF35-PDP-SIGNER-NATIVE-PACKET-20261016-P4",
|
||||
"owner": "railiance-platform-owner",
|
||||
"disposition": "approve-preparation/responsibility-prose-correction-for-independent-review-only",
|
||||
"files_sha256": {
|
||||
"README.md": "sha256:32ae1e783f3c98b6f6db74cbf1b88000c218ce0498014781bf44a7b0a449dae2",
|
||||
"admission-scope.incomplete.json": "sha256:2531f29734540d9206cddf946faed6b6cf8599e78c737b2c2d7fecf8f614e6a6",
|
||||
"evidence-pins.json": "sha256:94335bbdd57851ed42e969a31a571fed54b145673ed3646bec4a50142e6a2cee",
|
||||
"finalize.py": "sha256:1d61324628d77a44aeddd1d1a7e8e413986e2018ac67a1ad715717732c9b0d1c",
|
||||
"remaining-inputs.json": "sha256:898d9d046d9e8218f5715300c3bf806a838ba1eec6eaec27c2976a436fae7b55",
|
||||
"test_finalize.py": "sha256:6c19aebac6ae3b8d76d25278bb45be1c14fe2e9c1a22ff2cafede9d96db09e00",
|
||||
"verification.json": "sha256:bc4e90e1cfe53f203e64c597f15f3607eea5fa67f2b646088e7af8852d8fb61a"
|
||||
},
|
||||
"predecessors_p1_p2_p3_changed": false,
|
||||
"native_execution_authorized": false,
|
||||
"approval_authenticated": false,
|
||||
"source_projection_is_actual_native_fence": false,
|
||||
"pre_key_baseline_is_admitted_online_trust": false,
|
||||
"executor_and_scope_unchanged_from_p3": true
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"schema": "railiance-platform.native-packet-owner-inputs.v1",
|
||||
"proposal_id": "RPF35-PDP-SIGNER-NATIVE-PACKET-20261016-P4",
|
||||
"inputs": [
|
||||
{
|
||||
"owner": "Platform+founder",
|
||||
"input": "Actual exact CCR0050 read-lane disposition, native role/policy/bound-claims readback, approved/binding-confirmed CCR bytes and hash; separate fixed one-use CAS0 writer approval",
|
||||
"fills": [
|
||||
"ccr_sha256"
|
||||
],
|
||||
"state": "open; source CCR remains proposed"
|
||||
},
|
||||
{
|
||||
"owner": "Access owner",
|
||||
"input": "Exact workload/Helm candidate release/delivery/mount/outbox and stopped workload writers; authenticated actual stopped signer native projection/fence; source render is proposed only",
|
||||
"fills": [
|
||||
"exclusive_window_sha256 supporting workload observations"
|
||||
],
|
||||
"state": "native fence and approved execution open"
|
||||
},
|
||||
{
|
||||
"owner": "Platform owner",
|
||||
"input": "Existing GitOps Application/sync-freeze integration; identify/freeze competing Application writers under separate exact scope; no ArgoCD install/controller configuration change included",
|
||||
"fills": [
|
||||
"exclusive_window_sha256 supporting Application observations"
|
||||
],
|
||||
"state": "actual held window open"
|
||||
},
|
||||
{
|
||||
"owner": "cluster-runtime-storage-owner",
|
||||
"input": "Actual runtime identity/headroom/storage/PVC1Gi and bound PV retention review; excludes workload or GitOps Application authority. Enablement review only for a separately proposed actual ArgoCD installation/controller change.",
|
||||
"fills": [
|
||||
"exclusive_window_sha256 supporting runtime/storage observations"
|
||||
],
|
||||
"state": "independent runtime/storage scope, not combined assent"
|
||||
},
|
||||
{
|
||||
"owner": "Secrets",
|
||||
"input": "Independently disposition exact proposed pre-key empty-trust baseline and installed bundle/config/custody/transport; post-custody authenticate public receipt and independently approve successor trust/key",
|
||||
"fills": [
|
||||
"consumer_trust_sha256"
|
||||
],
|
||||
"state": "proposed failclosed baseline selection only; no installation/key admission"
|
||||
},
|
||||
{
|
||||
"owner": "founder+Platform attended identity",
|
||||
"input": "Independently established exact non-root OIDC entity and trusted custody execution runtime/private paths; no agent token lookup or login",
|
||||
"fills": [
|
||||
"founder_entity_id"
|
||||
],
|
||||
"state": "open"
|
||||
},
|
||||
{
|
||||
"owner": "all five reviewers+founder",
|
||||
"input": "Coordinated future absolute expiry and exact claim-free scope digest, five distinct externally established dispositions, founder exact file/command/risk/resource approval",
|
||||
"fills": [
|
||||
"expires_at",
|
||||
"owner_reviews",
|
||||
"final admission file SHA256"
|
||||
],
|
||||
"state": "open; no approvals authenticated by assembler"
|
||||
}
|
||||
],
|
||||
"source_projection_selected_not_observed": true,
|
||||
"pre_key_baseline_selected_not_admitted": true,
|
||||
"actual_native_authority": false,
|
||||
"public_key_or_fingerprint_available": false,
|
||||
"rollback_owner_scopes": {
|
||||
"founder": "abort disposition",
|
||||
"railiance-platform-owner": "custody reconciliation; existing GitOps Application sync/freeze and reviewed restoration",
|
||||
"access-engine-owner": "signer workload/Helm stop, release rollback, writer lock release and local outbox evidence",
|
||||
"secrets-engine-owner": "consumer failclosed and independent public trust withdrawal/restoration",
|
||||
"cluster-runtime-storage-owner": "runtime/storage/PVC/PV preservation and retention review; excludes workload and Application controllers",
|
||||
"enablement_condition": "only actual separately proposed ArgoCD installation/controller configuration change; excluded from fixed action"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
"""Disposable assembler checks; synthetic approvals are never native authority."""
|
||||
import copy,hashlib,json,os,stat,subprocess,sys,tempfile,unittest
|
||||
from pathlib import Path
|
||||
BASE=Path(__file__).resolve().parent
|
||||
|
||||
def enc(x): return json.dumps(x,sort_keys=True,separators=(',',':'),allow_nan=False).encode()
|
||||
class FinalizeTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp=tempfile.TemporaryDirectory();self.addCleanup(self.tmp.cleanup)
|
||||
self.root=Path(self.tmp.name)
|
||||
self.scope=json.loads((BASE/'admission-scope.incomplete.json').read_text())
|
||||
self.scope.update(expires_at='2000-01-01T00:00:00Z',founder_entity_id='00000000-0000-0000-0000-000000000000',ccr_sha256='sha256:'+'1'*64,deployment_projection_sha256='sha256:'+'2'*64,consumer_trust_sha256='sha256:'+'3'*64,exclusive_window_sha256='sha256:'+'4'*64)
|
||||
self.scope['deployment_projection_sha256']=json.loads((BASE/'admission-scope.incomplete.json').read_text())['deployment_projection_sha256'] or self.scope['deployment_projection_sha256']
|
||||
self.scope['consumer_trust_sha256']=json.loads((BASE/'admission-scope.incomplete.json').read_text())['consumer_trust_sha256'] or self.scope['consumer_trust_sha256']
|
||||
self.scope['bindings']['deployment_sha256']=self.scope['deployment_projection_sha256']
|
||||
self.scope['bindings']['trust_sha256']=self.scope['consumer_trust_sha256']
|
||||
def run_assembler(self,scope=None,target=None,legacy_role=False):
|
||||
scope=self.scope if scope is None else scope
|
||||
(self.root/'scope.json').write_text(json.dumps(scope))
|
||||
pin='sha256:'+hashlib.sha256(enc(scope)).hexdigest()
|
||||
reviews={role:{'approved_admission_sha256':pin,'approval_ref':'synthetic-test-only'} for role in ('founder','railiance-platform-owner','access-engine-owner','secrets-engine-owner','cluster-runtime-storage-owner')}
|
||||
if legacy_role: reviews['cluster-gitops-owner']=reviews.pop('cluster-runtime-storage-owner')
|
||||
(self.root/'reviews.json').write_text(json.dumps(reviews))
|
||||
return subprocess.run([sys.executable,str(BASE/'finalize.py'),str(self.root/'scope.json'),str(self.root/'reviews.json'),str(target or self.root/'out.json')],capture_output=True,preexec_fn=lambda:os.umask(0))
|
||||
def test_legacy_combined_owner_role_refused(self):
|
||||
self.assertNotEqual(self.run_assembler(legacy_role=True).returncode,0)
|
||||
self.assertFalse((self.root/'out.json').exists())
|
||||
def test_incomplete_preparation_refused(self):
|
||||
scope=json.loads((BASE/'admission-scope.incomplete.json').read_text())
|
||||
self.assertNotEqual(self.run_assembler(scope).returncode,0)
|
||||
self.assertFalse((self.root/'out.json').exists())
|
||||
def test_exact_bytes_and_private_mode_under_permissive_umask(self):
|
||||
result=self.run_assembler();self.assertEqual(result.returncode,0,result.stderr)
|
||||
path=self.root/'out.json';self.assertEqual(stat.S_IMODE(path.stat().st_mode),0o600)
|
||||
value=json.loads(path.read_bytes());self.assertEqual({k:v for k,v in value.items() if k!='owner_reviews'},self.scope)
|
||||
receipt=json.loads(result.stdout);self.assertEqual(receipt['admission_file_sha256'],'sha256:'+hashlib.sha256(path.read_bytes()).hexdigest())
|
||||
self.assertIn('No approval authenticated',receipt['authority'])
|
||||
def test_existing_output_refused_unchanged(self):
|
||||
target=self.root/'out.json';target.write_bytes(b'original');os.chmod(target,0o640)
|
||||
self.assertNotEqual(self.run_assembler().returncode,0)
|
||||
self.assertEqual(target.read_bytes(),b'original');self.assertEqual(stat.S_IMODE(target.stat().st_mode),0o640)
|
||||
def test_symlink_output_refused_without_target_change(self):
|
||||
target=self.root/'original';target.write_bytes(b'original');(self.root/'out.json').symlink_to(target)
|
||||
self.assertNotEqual(self.run_assembler().returncode,0);self.assertEqual(target.read_bytes(),b'original')
|
||||
def test_altered_fixed_bindings_refused_before_output(self):
|
||||
for field in ('proposal_sha256','executed_revision_sha256','image_sha256','policy_sha256'):
|
||||
with self.subTest(field=field):
|
||||
scope=copy.deepcopy(self.scope);scope['bindings'][field]='sha256:'+'f'*64
|
||||
self.assertNotEqual(self.run_assembler(scope).returncode,0)
|
||||
self.assertFalse((self.root/'out.json').exists())
|
||||
def test_selected_baselines_refused_if_changed(self):
|
||||
for field,binding in (('deployment_projection_sha256','deployment_sha256'),('consumer_trust_sha256','trust_sha256')):
|
||||
if json.loads((BASE/'admission-scope.incomplete.json').read_text())[field] is None: continue
|
||||
with self.subTest(field=field):
|
||||
scope=copy.deepcopy(self.scope);scope[field]='sha256:'+'f'*64;scope['bindings'][binding]=scope[field]
|
||||
self.assertNotEqual(self.run_assembler(scope).returncode,0);self.assertFalse((self.root/'out.json').exists())
|
||||
def test_altered_fixed_image_refused_even_matching_reviews(self):
|
||||
scope=copy.deepcopy(self.scope);scope['producer_image']='forgejo.coulomb.social/coulomb/flex-auth@sha256:'+'f'*64
|
||||
self.assertNotEqual(self.run_assembler(scope).returncode,0);self.assertFalse((self.root/'out.json').exists())
|
||||
if __name__=='__main__': unittest.main()
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"schema": "railiance-platform.packet-preparation-verification.v1",
|
||||
"tests": 8,
|
||||
"result": "passed",
|
||||
"command": "python3 test_finalize.py",
|
||||
"checks": [
|
||||
"actual0600 under umask000",
|
||||
"exact output digest",
|
||||
"incomplete scope refused",
|
||||
"overwrite and symlink target preserved",
|
||||
"fixed four bindings and image alteration refused despite synthetic matching reviews",
|
||||
"selected baseline/projection changes refused",
|
||||
"legacy cluster-gitops-owner role refused"
|
||||
],
|
||||
"canonical_R5_six_module_hashes_verified": true,
|
||||
"candidate_manifest_files_verified": "P2 exact unchanged evidence retained",
|
||||
"consumer_final_manifest_sha256": "sha256:7f4a49064b459a3b087943a00241eb9f744e3768f5c4139d1821d799ff2e584a",
|
||||
"rollout_r2_all_manifest_files_verified": true,
|
||||
"canonical_projection_encoding_recomputed": true,
|
||||
"actual_native_fence": null,
|
||||
"owner_dispositions": null,
|
||||
"founder_entity_id": null,
|
||||
"native_expiry": null,
|
||||
"held_window": false,
|
||||
"native_execution": false,
|
||||
"synthetic_reviews": "test-only; not authenticated approval",
|
||||
"responsibility_audit": {
|
||||
"files_audited": [
|
||||
"test_finalize.py",
|
||||
"remaining-inputs.json",
|
||||
"finalize.py",
|
||||
"README.md",
|
||||
"admission-scope.incomplete.json",
|
||||
"evidence-pins.json"
|
||||
],
|
||||
"result": "All P4 prose assigns Access workload/Helm, Platform GitOps Application/freeze, cluster runtime/storage/PV and Secrets consumer/trust; legacy combined role appears only in refusal test/history. No blanket Enablement role.",
|
||||
"p3_finding_preserved": true
|
||||
},
|
||||
"unchanged_from_p3": {
|
||||
"admission-scope.incomplete.json": "sha256:2531f29734540d9206cddf946faed6b6cf8599e78c737b2c2d7fecf8f614e6a6",
|
||||
"finalize.py": "sha256:1d61324628d77a44aeddd1d1a7e8e413986e2018ac67a1ad715717732c9b0d1c",
|
||||
"test_finalize.py": "sha256:6c19aebac6ae3b8d76d25278bb45be1c14fe2e9c1a22ff2cafede9d96db09e00"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue