Prepare scoped reuse reader release with qualified content digests

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a137ca-5c77-7a71-b9ae-23ad9b0b5684
This commit is contained in:
tegwick 2026-10-15 01:47:29 +02:00
parent 72bcad86d7
commit fb7d56d3dc
22 changed files with 1937 additions and 0 deletions

View file

@ -32,11 +32,21 @@ app.kubernetes.io/component: landing
{{- end -}}
{{- define "reuse.image" -}}
{{- if and .Values.authSourceAllowlist (not .Values.image.digest) -}}
{{- fail "authenticated source allowlist requires reviewed hardened image.digest" -}}
{{- end -}}
{{- if .Values.image.digest -}}
{{- if not (regexMatch "^sha256:[a-f0-9]{64}$" .Values.image.digest) -}}
{{- fail "image.digest must be sha256 plus 64 lowercase hex characters" -}}
{{- end -}}
{{- printf "%s@%s" .Values.image.repository .Values.image.digest -}}
{{- else -}}
{{- if not .Values.image.tag -}}
{{- fail "image.tag is required - pin it in helm/reuse-surface-values.yaml" -}}
{{- end -}}
{{- printf "%s:%s" .Values.image.repository .Values.image.tag -}}
{{- end -}}
{{- end -}}
{{- define "reuse.landingImage" -}}
{{- if not .Values.landing.image.tag -}}

View file

@ -36,6 +36,8 @@ spec:
- secretRef:
name: {{ .Values.envSecretName | quote }}
env:
- name: REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST
value: {{ .Values.authSourceAllowlist | toJson | quote }}
- name: REUSE_SURFACE_LISTEN_HOST
value: "0.0.0.0"
- name: REUSE_SURFACE_LISTEN_PORT

View file

@ -0,0 +1,30 @@
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"image": {
"type": "object",
"properties": {
"digest": {
"type": "string",
"pattern": "^(|sha256:[a-f0-9]{64})$"
}
}
},
"authSourceAllowlist": {
"type": "object",
"propertyNames": {
"pattern": "^[A-Z][A-Z0-9_]*$"
},
"additionalProperties": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string",
"pattern": "^https://[^\\s]+$"
},
"minItems": 1
}
}
}
}

View file

@ -1,6 +1,7 @@
image:
repository: forgejo.coulomb.social/coulomb/reuse-surface
tag: ""
digest: ""
pullPolicy: IfNotPresent
replicaCount: 1
@ -26,6 +27,10 @@ resources:
envSecretName: reuse-surface-env
# Non-secret exact URL bindings for authenticated remote metadata fetches.
# Nonempty bindings require an immutable digest; use only a reviewed hardened image.
authSourceAllowlist: {}
landing:
enabled: false
image:

View file

@ -0,0 +1,119 @@
# Railiance apps preparation review — CUST81 private metadata reader R2
Reviewer: delegated railiance-apps preparation worker, supervised local preparation
assignment. No promotion evidence or existing own-scope supervision record was
found; the descriptive preparation record grants no runtime authority. This is
an S5 release-contract review grounded in INTENT principles 1–5 (workloads,
release contracts, repeatable operations, explicit S3 handoff, verified health).
It is not a founder decision, independent platform credential review or reuse
application source review. No live changes, commits, pushes, hub writes, image
publishes, login or credential retrieval occurred.
Disposition: **approved for integration as local preparation only; live promotion blocked**.
Canonical review disposition: `approved`. This accepts the bounded S5 proposal
and its explicit runtime gates, not live execution or another owner’s review.
## Proposed changes and owner boundaries
The chart accepts an optional immutable image digest, adds a non-secret exact
`REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST` environment binding, and fails rendering
when a nonempty allowlist lacks an immutable digest. Schema checks enforce
HTTPS allowlist entries and valid digest syntax. Production values continue
using their existing `main-6cbc862` tag; production ExternalSecret is unchanged.
The preparation override contains exactly 14 reviewed pinned metadata URLs and
an empty digest deliberately preventing deployment. A synthetic all-zero digest
in local tests is not an image and must never be promoted.
The proposed phase-B ExternalSecret preserves existing two keys, target metadata
and existing `openbao-reuse` ClusterSecretStore, adding only
`REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN` from
`workloads/reuse/reuse-surface/forgejo-source-read:FORGEJO_SOURCE_TOKEN`.
Platform owns the dedicated KV path/policy/store read scope, CCR-2026-0046 and
credential issuance; apps neither provisions nor consumes an admin credential.
Digest presence cannot prove the hardened application is included. The reuse
owner must provide published build digest, source revision, tests and review
binding *both* authenticated redirect rejection and exact environment-name/URL
credential routing. A reader must not reach the existing vulnerable runtime.
## Ordered promotion gates — not executed
1. Confirm own-scope supervision and founder change approval, reviewed CCR,
exact seven-source owner consent packet and scoped Forgejo read-only issuer
receipt. Integrate provisional RAPPS-WP-0017 through root owner coordination.
2. Run metadata inventory helper with an explicitly verified railiance01
kubeconfig; compare existing authenticated registrations with newly
fail-closed image behavior. The helper reads only SQLite registration
metadata, never env/Secrets, captures command errors and refuses unsafe
URLs. If it refuses, resolve via the source owner without emitting raw
objects. Any existing authenticated source requires separately reviewed
exact URL bindings including capability entry URLs before promotion; do not
silently orphan sources or broaden the 14-URL map. Missing inventory blocks
phase A. Store only safe names, counts and validated metadata URLs.
3. Read live release image/revision, replica state, PVC storage/access modes and
readiness. Confirm node external IP `92.205.62.239`, not retired coulombcore.
Record requested CPU/memory headroom and pending pods before rollout. Existing
API requests 100m CPU/256Mi, surge1 requires that much additional allocatable
capacity; landing unchanged. Confirm the existing PVC supports simultaneous
pod scheduling/mount on this single node; stop if RWO/RWOP or mount conflicts
prevent it. No rollout strategy/resource/PVC changes are proposed. Do not
change other workloads merely to obtain capacity.
4. Once a real reviewed digest exists, fill the preparation values; render
exact chart with production values plus proposal overrides. Server dry-run
and client diff must cover every rendered chart object and the phase-B ESO
manifest. Preserve stderr in memory and emit sanitized status only; never
print live Secrets, Helm secret values, annotations or raw API failures.
Existing release owner and any Argo adoption must be verified before choosing
owner Helm upgrade versus GitOps sync; neither is executed here.
5. Phase A: approved release of hardened digest plus approved allowlist, with
existing ESO fields only. Owner Helm path must use atomic upgrade, timeout
and wait; verify actual running imageID matches digest, API health/probes,
public federation baseline63 and credential-routing refusal/redirect tests.
Deployment failure blocks phase B. Database/PVC remains unchanged. Collect a
separately approved safe backup/recovery receipt before any risky live release.
6. Phase B: after verified phase A, execute reviewed platform credential action
and ESO reader mapping. Verify only ESO condition/status and key-presence
booleans via approved suppressing helpers, then restart/sync the hardened
workload so envFrom obtains the reader. Never dump Secret or process env.
7. Reuse owner runs native exact-byte authenticated proof for all14 URLs and
seven capability entries using pinned consent hashes. Only then register
seven sources through the scoped write route and verify hosted70/70,
no duplicates/conflicting IDs and public federation preserves all63.
## Rollback contract
Before execution capture previous approved release revision, digest/tag and
safe configuration, public discovery baseline and database recovery receipt.
If phase A fails before credential delivery, atomic restore of previous release
is safe because no reader has been supplied. After phase B, **never downgrade to
vulnerable runtime with reader still available**: revoke the dedicated reader
at Forgejo/OpenBao via credential owner, remove phase-B ESO mapping and materialized
reader key through reviewed silent maintenance, restart current hardened pods,
verify absence/revocation, then restore prior approved chart/image only if needed.
Metadata registrations may remain inaccessible until re-established; record the
regression explicitly. Do not roll back the PVC or use stale tokens as recovery.
## Local evidence and limitations
`helm lint charts/reuse-surface -f helm/reuse-surface-values.yaml` passed.
`python3 docs/assessments/cust81-private-reader/verify_preparation.py` passed ten
checks, including exact14 roundtrip, digest/schema refusal, retention of current
strategy/resources/PVC, correct isolated ESO mapping, metadata URL sanitization
and subprocess error suppression. `local-verification-r2.json` contains command
statuses without raw output. No cluster inventory, resource headroom,
server dry-run/diff, image publish, live approval or native fetch has been proven.
## Revision history — same proposal, no second trial
R1 root review found the inventory SQL incorrectly selected `$.index_url` rather
than the native HubStore registration field `$.url`. R1's local checks did not
exercise the pod SQL and therefore missed this defect. R1 must not be executed;
it remains preserved in the root assembly archive. R2 selects `$.url` and tests
the exact read-only pod SQL against a real SQLite registration payload containing
`repo`, `url`, `auth_env`, timestamps and an unrelated sentinel description, plus
an anonymous registration. Only expected names/URL emerge; rows remain unchanged.
R2 also accepts canonical Forgejo raw branch/commit/tag index routes while still
refusing userinfo, non-HTTPS, credentials in queries and fragments. Untrusted
successful subprocess output is refused without raw echo, as are failures.
No live inventory command has run. This corrective refinement is the same
CUST81-APPS-PRIVATE-READER-RELEASE proposal revision2, not an unchanged success.

View file

@ -0,0 +1,96 @@
{
"status": "passed",
"local_only": true,
"real_image_digest": null,
"synthetic_digest_used_only_to_check_rendering": true,
"checks": [
"production rendering unchanged except empty fail-closed allowlist",
"unknown/malformed digest fails",
"HTTP allowlist fails schema",
"exact14 URLs roundtrip",
"strategy resources PVC retained",
"dedicated ESO mapping preserves current fields/store",
"metadata sanitizer excludes userinfo/query secrets/fragments",
"kubectl failure output discarded",
"exact pod SQL real payload URL keys readonly fixture and anonymous filtering",
"legacy Forgejo branch URL accepted without weakening credential query refusal"
],
"helm_calls": [
{
"command": [
"helm",
"template",
"reuse",
"/tmp/cust81-apps-reader-owner/charts/reuse-surface",
"-f",
"/tmp/cust81-apps-reader-owner/helm/reuse-surface-values.yaml"
],
"exit_code": 0,
"expected_success": true
},
{
"command": [
"helm",
"template",
"reuse",
"/tmp/cust81-apps-reader-owner/charts/reuse-surface",
"-f",
"/tmp/cust81-apps-reader-owner/helm/reuse-surface-values.yaml",
"-f",
"/tmp/cust81-apps-reader-owner/docs/assessments/cust81-private-reader/private-reader-values.r1.yaml"
],
"exit_code": 1,
"expected_success": false
},
{
"command": [
"helm",
"template",
"reuse",
"/tmp/cust81-apps-reader-owner/charts/reuse-surface",
"-f",
"/tmp/cust81-apps-reader-owner/helm/reuse-surface-values.yaml",
"-f",
"/tmp/cust81-apps-reader-owner/docs/assessments/cust81-private-reader/private-reader-values.r1.yaml",
"--set",
"image.digest=sha256:bad"
],
"exit_code": 1,
"expected_success": false
},
{
"command": [
"helm",
"template",
"reuse",
"/tmp/cust81-apps-reader-owner/charts/reuse-surface",
"-f",
"/tmp/cust81-apps-reader-owner/helm/reuse-surface-values.yaml",
"-f",
"/tmp/cust81-apps-reader-owner/docs/assessments/cust81-private-reader/private-reader-values.r1.yaml",
"--set-json",
"authSourceAllowlist={\"BAD\":[\"http://attacker.invalid\"]}",
"--set",
"image.digest=sha256:0000000000000000000000000000000000000000000000000000000000000000"
],
"exit_code": 1,
"expected_success": false
},
{
"command": [
"helm",
"template",
"reuse",
"/tmp/cust81-apps-reader-owner/charts/reuse-surface",
"-f",
"/tmp/cust81-apps-reader-owner/helm/reuse-surface-values.yaml",
"-f",
"/tmp/cust81-apps-reader-owner/docs/assessments/cust81-private-reader/private-reader-values.r1.yaml",
"--set",
"image.digest=sha256:0000000000000000000000000000000000000000000000000000000000000000"
],
"exit_code": 0,
"expected_success": true
}
]
}

View file

@ -0,0 +1,30 @@
{
"reviewer_owner": "railiance-apps",
"reviewer_assignment": "delegated-railiance-apps-cust81-preparation",
"disposition": "approved",
"approved_scope": "isolated S5 chart/ESO preparation integration only",
"live_execution_approval": false,
"workitem": "RAPPS-WP-0017",
"intent_basis": [
"Release Contracts over Source Internals",
"Repeatable Operations",
"Clear Lower-Layer Handoffs",
"Evidence Before Confidence"
],
"review_artifact_sha256": "a3a2f2db6f0a8461a0d8299825c842c8ce427f59c86238884609d463837b3b75",
"reviewed_manifest_sha256": "45d467c2bb48462a388f5df4ba5188492d406bdddbddfbf3487bd2077486dec8",
"reviewed_patch_sha256": "39ebaa7f4050f9204fe8ee38364fbbce874903447ac45ccd408cf434aa6e4a73",
"gates": [
"unknown reviewed hardened image digest",
"metadata-only existing authenticated source inventory/migration",
"live node headroom/PVC/readiness survey",
"server dry-run and client diff",
"release-specific EUR estimates and founder live-change approval",
"phase A verified before phase B credential delivery",
"approved executed platform credential CCR",
"native14 URL/7 metadata hash proof then70/70 hosted"
],
"proposal_id": "CUST81-APPS-PRIVATE-READER-RELEASE-R1",
"revision": 2,
"refinement_or_rescue": true
}

View file

@ -0,0 +1,57 @@
# Apps concrete phase A proposal review
Disposition: `approved` for proposal preparation and local render only.
This supplement preserves the reviewed core R2 patch unchanged. It supplies
actual `reuse` Helm release / `reuse` namespace chart rendering with the locally
built hardened image digest. It does not authorize publication, execute a live
change or approve platform's CCR. INTENT basis: source-controlled release
contracts, explicit S3 handoff and evidence before confidence.
The proposed image is
`forgejo.coulomb.social/coulomb/reuse-surface@sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0`.
The local build receipt confirms no-network/read-only health and native source
hash smoke. Registry publication is false. Before apply the exact reviewed
artifact must be published and independently verified by registry manifest
digest. If publication changes manifest representation/digest, revise and review
the bound proposal rather than silently replacing the digest.
Current observations are node `92.205.62.239`, CPU requests3560m of4000m (440m
free), API100m/256Mi, replicas1 with surge1/unavailable0, PVC
`reuse-surface-data` Bound RWO1Gi, and Helm ownership without Argo tracking.
The proposed chart retains resources, strategy and PVC. One100m/256Mi surge fits
observed CPU headroom; recheck memory, pending pods and node headroom immediately
before rollout. RWO single-node does not prohibit two pods on that same node,
but driver mount behavior and SQLite concurrent-access readiness remain
verification gates. Do not change deployment strategy or PVC to bypass a failure.
Exact readonly authenticated-source inventory is0 at its receipt timestamp.
This clears the observed migration gate, but recheck before apply; no credential
or Secret/env was read. Existing Kubernetes-auth `openbao-reuse` store is Ready
with namespace/ServiceAccount/role matching the consumer; its current
ExternalSecret contains only the two old fields and remains unchanged in phase A.
Local full-chart render and assertions passed: exact proposed image and14 URL
allowlist; same100m/256Mi requests; same1surge/0unavailable/replicas1; no Secret,
ExternalSecret or store objects added. Full chart includes existing landing,
ingress, services and PVC and must receive normal full-chart server dry-run and
client diff, not a Deployment-only narrow review.
Incremental infrastructure cost is EUR0 because node, replica steady state,
requests, services and PVC capacity remain unchanged. Build/registry execution
cost is not independently accounted. Credible operational loss is qualitative
and not priced in EUR: rollout failure or concurrent SQLite/PVC access may cause
service interruption or recovery work. No autopilot grant is inferred. Exact
human review must accept these estimates and remaining readiness gates.
Before founder-authorized deploy, capture current Helm revision and safe rollback
reference (old running digest
`sha256:2c1514cb3f5e1297ffeeac912ba36a70f8a2591588a5a4643bc58293e97132de`),
known recovery receipt and63 public capability baseline. Use actual Helm release
`reuse`, namespace`reuse`, owner atomic/wait/timeout path after safe dry-run/diff.
No exact deploy command is executed by this proposal. Phase A retains the current
runtime Secret fields and supplies no reader. Verify running imageID, readiness,
public federation and credential refusal/redirect behavior before phase B.
If phase A fails with no reader delivered, restore the approved previous release.
After phase B, revoke/remove reader and verify its absence before any vulnerable
image restoration. Phase B is independently gated by approved/executed CCR and
native14 URL/7 entry-hash proof before70/70 hosted discovery.

View file

@ -0,0 +1,12 @@
{
"proposal_id": "CUST81-APPS-PHASE-A-LOCAL-IMAGE-R1",
"reviewer_owner": "railiance-apps",
"disposition": "approved",
"approved_scope": "preparation only, local full-chart render, supervised founder review required",
"files": {
"docs/assessments/cust81-private-reader/phase-a-local-image-r1/apps-owner-release-review.md": "a74e96986798a727fc87c0d3c578601579778dfd8521796d0bb81df8451c751b",
"docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-full-chart.proposed.yaml": "36c20c3e16757d3e888a3db02853032b33e791aa04a6055fe001121254345b81",
"docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-preparation-receipt.json": "3282a17ae3724619e40dd1f34846d83b2297d9ae00030618dbd269e8e2fd7d39",
"docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml": "35284857ec987fc7a929f5c2eecdb44c7d3367f7835904692947de09918ab8f1"
}
}

View file

@ -0,0 +1,478 @@
# PREPARATION RENDER ONLY; no registry publication or server validation proved.
---
# Source: reuse-surface/templates/landing-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: reuse-surface-landing
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
app.kubernetes.io/component: landing
data:
index.html: |
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<title>REUSE federation endpoint</title>
<style>
:root {
color-scheme: light;
--ink: #1d2733;
--muted: #536271;
--line: #d9e0e7;
--paper: #f8fafc;
--accent: #2066a8;
--accent-dark: #164b7e;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
color: var(--ink);
background: var(--paper);
display: grid;
place-items: center;
padding: 32px 18px;
}
main {
width: min(100%, 720px);
border: 1px solid var(--line);
border-radius: 8px;
background: #ffffff;
padding: clamp(28px, 5vw, 48px);
box-shadow: 0 18px 48px rgba(29, 39, 51, 0.08);
}
.eyebrow {
margin: 0 0 12px;
color: var(--accent-dark);
font-size: 0.86rem;
font-weight: 700;
text-transform: uppercase;
}
h1 {
margin: 0;
font-size: clamp(2rem, 7vw, 3rem);
line-height: 1.05;
}
p {
max-width: 62ch;
margin: 18px 0 0;
color: var(--muted);
font-size: 1rem;
line-height: 1.65;
}
.actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 28px;
}
a {
color: var(--accent);
}
.button {
display: inline-flex;
min-height: 44px;
align-items: center;
justify-content: center;
border-radius: 6px;
background: var(--accent);
color: #ffffff;
padding: 0 18px;
font-weight: 700;
text-decoration: none;
}
.button:focus,
.button:hover {
background: var(--accent-dark);
}
.links {
margin-top: 26px;
padding-top: 22px;
border-top: 1px solid var(--line);
display: grid;
gap: 10px;
}
</style>
</head>
<body>
<main>
<p class="eyebrow">reuse.coulomb.social</p>
<h1>REUSE federation endpoint</h1>
<p>This is the Railiance REUSE capability federation service. It is an API endpoint for automated clients and operators; there is no browser login for this service.</p>
<div class="actions">
<a class="button" href="/v1/federated">Open federated index</a>
</div>
<nav class="links" aria-label="Service links">
<a href="/health">Health check</a>
<a href="/v1/federated">Federated capability index</a>
<a href="https://forgejo.coulomb.social/coulomb/railiance-apps/src/branch/main/docs/reuse-surface-on-railiance01.md">Operator runbook</a>
</nav>
</main>
</body>
</html>
---
# Source: reuse-surface/templates/pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: reuse-surface-data
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
# Source: reuse-surface/templates/landing-service.yaml
apiVersion: v1
kind: Service
metadata:
name: reuse-surface-landing
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
app.kubernetes.io/component: landing
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/component: landing
ports:
- name: http
port: 8080
targetPort: http
protocol: TCP
---
# Source: reuse-surface/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: reuse-surface
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/component: api
ports:
- name: http
port: 8000
targetPort: http
protocol: TCP
---
# Source: reuse-surface/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: reuse-surface
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
app.kubernetes.io/component: api
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/component: api
spec:
enableServiceLinks: false
securityContext:
{}
containers:
- name: reuse-surface
image: "forgejo.coulomb.social/coulomb/reuse-surface@sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0"
imagePullPolicy: IfNotPresent
command: ["reuse-surface", "serve"]
securityContext:
{}
ports:
- name: http
containerPort: 8000
protocol: TCP
envFrom:
- secretRef:
name: "reuse-surface-env"
env:
- name: REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST
value: "{\"REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN\":[\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738\"]}"
- name: REUSE_SURFACE_LISTEN_HOST
value: "0.0.0.0"
- name: REUSE_SURFACE_LISTEN_PORT
value: "8000"
- name: REUSE_SURFACE_DB
value: "/data/reuse.db"
- name: REUSE_SURFACE_CACHE_DIR
value: "/data/cache"
volumeMounts:
- name: data
mountPath: /data
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 15
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
volumes:
- name: data
persistentVolumeClaim:
claimName: reuse-surface-data
---
# Source: reuse-surface/templates/landing-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: reuse-surface-landing
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
app.kubernetes.io/component: landing
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/component: landing
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/component: landing
spec:
enableServiceLinks: false
containers:
- name: landing
image: "nginxinc/nginx-unprivileged:1.27-alpine"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 3
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 10
periodSeconds: 30
timeoutSeconds: 3
failureThreshold: 3
resources:
limits:
cpu: 50m
memory: 64Mi
requests:
cpu: 10m
memory: 32Mi
volumeMounts:
- name: landing-page
mountPath: /usr/share/nginx/html/index.html
subPath: index.html
readOnly: true
volumes:
- name: landing-page
configMap:
name: reuse-surface-landing
---
# Source: reuse-surface/templates/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: reuse-surface
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
tls:
- hosts:
- reuse.coulomb.social
secretName: reuse-surface-tls
rules:
- host: reuse.coulomb.social
http:
paths:
- path: /health
pathType: Exact
backend:
service:
name: reuse-surface
port:
number: 8000
- path: /v1
pathType: Prefix
backend:
service:
name: reuse-surface
port:
number: 8000
---
# Source: reuse-surface/templates/landing-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: reuse-surface-landing
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.priority: "1"
spec:
ingressClassName: traefik
tls:
- hosts:
- reuse.coulomb.social
secretName: reuse-surface-tls
rules:
- host: reuse.coulomb.social
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: reuse-surface-landing
port:
number: 8080
---
# Source: reuse-surface/templates/redirect-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: reuse-surface-http-redirect
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
traefik.ingress.kubernetes.io/router.middlewares: "reuse-reuse-surface-redirect-https@kubernetescrd"
spec:
ingressClassName: traefik
rules:
- host: reuse.coulomb.social
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: reuse-surface
port:
number: 8000
---
# Source: reuse-surface/templates/redirect-middleware.yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: reuse-surface-redirect-https
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/instance: reuse
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: "0.1.0"
app.kubernetes.io/part-of: railiance-apps
helm.sh/chart: reuse-surface-0.1.0
spec:
redirectScheme:
scheme: https
permanent: true

View file

@ -0,0 +1,67 @@
{
"proposal_id": "CUST81-APPS-PHASE-A-LOCAL-IMAGE-R1",
"disposition": "approved",
"approved_scope": "concrete proposal preparation and local render only; not publish or production deploy",
"workitem": "RAPPS-WP-0017-T02",
"release": "reuse",
"namespace": "reuse",
"deployment": "reuse-surface",
"image_reference": "forgejo.coulomb.social/coulomb/reuse-surface@sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0",
"registry_publication_verified": false,
"phase_b_credential_delivery_included": false,
"incremental_infrastructure_cost_eur": 0,
"cost_basis": "existing node, same requests and replicas, same PVC, no new service or purchased capacity; build/registry execution cost not independently accounted",
"credible_loss_bound_eur": null,
"risk_basis": "qualitative supervised change: transient rollout or SQLite concurrent-access outage; RWO PVC single-node mounts need preflight; no customer production admitted; data recovery and exact atomic rollback required before execution",
"autopilot_authority": false,
"local_render_checks": "passed",
"evidence": {
"hardened-reader-local-image-r1.json": {
"path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/hardened-reader-local-image-r1.json",
"sha256": "ed7c2516925d7f16b573a70b5e48d5656a4875e9eb94bcc8760a8bdcbe07f59c"
},
"live-authenticated-source-inventory-r1.json": {
"path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/live-authenticated-source-inventory-r1.json",
"sha256": "ba669d6231c8c611191c7ad28f5914d6c47332032b23b0ea40a13f753e883073"
},
"reuse-release-runtime-metadata-r1.json": {
"path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/reuse-release-runtime-metadata-r1.json",
"sha256": "5ec901cf41b9f52628ff636c23b5bbc4789df6a9118f5cff0ff8518b287357e9"
},
"reuse-release-owner-eso-metadata-r1.json": {
"path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/reuse-release-owner-eso-metadata-r1.json",
"sha256": "ff9aa207ae081d27d86820747a993d4bbc290ba2c354eef72388233d6733adb3"
}
},
"observed_runtime": {
"node_ip": "92.205.62.239",
"cpu_free_m": 440,
"api_surge_cpu_m": 100,
"api_surge_memory_mi": 256,
"pvc": "reuse-surface-data",
"pvc_access": "ReadWriteOnce",
"pvc_capacity": "1Gi",
"previous_image_digest": "forgejo.coulomb.social/coulomb/reuse-surface@sha256:2c1514cb3f5e1297ffeeac912ba36a70f8a2591588a5a4643bc58293e97132de",
"authenticated_sources": 0
},
"gates": [
"publish exact reviewed image and verify registry digest; local digest may require reviewed update if registry transforms manifest",
"founder approval for exact phase A and later credential CCR/phase B",
"recheck target headroom memory node/PVC mount scheduling and authenticated inventory immediately before apply",
"bounded safe server dry-run/client diff and current release revision/rollback capture",
"no ESO reader field during phase A; verify actual imageID health and63public baseline before phase B",
"revoke/remove delivered reader before any downgrade to old vulnerable image"
],
"render_command": [
"helm",
"template",
"reuse",
"charts/reuse-surface",
"--namespace",
"reuse",
"-f",
"helm/reuse-surface-values.yaml",
"-f",
"docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml"
]
}

View file

@ -0,0 +1,665 @@
diff --git a/docs/assessments/cust81-private-reader/phase-a-local-image-r1/apps-owner-release-review.md b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/apps-owner-release-review.md
new file mode 100644
index 0000000..0079fe5
--- /dev/null
+++ b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/apps-owner-release-review.md
@@ -0,0 +1,57 @@
+# Apps concrete phase A proposal review
+
+Disposition: `approved` for proposal preparation and local render only.
+This supplement preserves the reviewed core R2 patch unchanged. It supplies
+actual `reuse` Helm release / `reuse` namespace chart rendering with the locally
+built hardened image digest. It does not authorize publication, execute a live
+change or approve platform's CCR. INTENT basis: source-controlled release
+contracts, explicit S3 handoff and evidence before confidence.
+
+The proposed image is
+`forgejo.coulomb.social/coulomb/reuse-surface@sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0`.
+The local build receipt confirms no-network/read-only health and native source
+hash smoke. Registry publication is false. Before apply the exact reviewed
+artifact must be published and independently verified by registry manifest
+digest. If publication changes manifest representation/digest, revise and review
+the bound proposal rather than silently replacing the digest.
+
+Current observations are node `92.205.62.239`, CPU requests3560m of4000m (440m
+free), API100m/256Mi, replicas1 with surge1/unavailable0, PVC
+`reuse-surface-data` Bound RWO1Gi, and Helm ownership without Argo tracking.
+The proposed chart retains resources, strategy and PVC. One100m/256Mi surge fits
+observed CPU headroom; recheck memory, pending pods and node headroom immediately
+before rollout. RWO single-node does not prohibit two pods on that same node,
+but driver mount behavior and SQLite concurrent-access readiness remain
+verification gates. Do not change deployment strategy or PVC to bypass a failure.
+
+Exact readonly authenticated-source inventory is0 at its receipt timestamp.
+This clears the observed migration gate, but recheck before apply; no credential
+or Secret/env was read. Existing Kubernetes-auth `openbao-reuse` store is Ready
+with namespace/ServiceAccount/role matching the consumer; its current
+ExternalSecret contains only the two old fields and remains unchanged in phase A.
+
+Local full-chart render and assertions passed: exact proposed image and14 URL
+allowlist; same100m/256Mi requests; same1surge/0unavailable/replicas1; no Secret,
+ExternalSecret or store objects added. Full chart includes existing landing,
+ingress, services and PVC and must receive normal full-chart server dry-run and
+client diff, not a Deployment-only narrow review.
+
+Incremental infrastructure cost is EUR0 because node, replica steady state,
+requests, services and PVC capacity remain unchanged. Build/registry execution
+cost is not independently accounted. Credible operational loss is qualitative
+and not priced in EUR: rollout failure or concurrent SQLite/PVC access may cause
+service interruption or recovery work. No autopilot grant is inferred. Exact
+human review must accept these estimates and remaining readiness gates.
+
+Before founder-authorized deploy, capture current Helm revision and safe rollback
+reference (old running digest
+`sha256:2c1514cb3f5e1297ffeeac912ba36a70f8a2591588a5a4643bc58293e97132de`),
+known recovery receipt and63 public capability baseline. Use actual Helm release
+`reuse`, namespace`reuse`, owner atomic/wait/timeout path after safe dry-run/diff.
+No exact deploy command is executed by this proposal. Phase A retains the current
+runtime Secret fields and supplies no reader. Verify running imageID, readiness,
+public federation and credential refusal/redirect behavior before phase B.
+If phase A fails with no reader delivered, restore the approved previous release.
+After phase B, revoke/remove reader and verify its absence before any vulnerable
+image restoration. Phase B is independently gated by approved/executed CCR and
+native14 URL/7 entry-hash proof before70/70 hosted discovery.
diff --git a/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-full-chart.proposed.yaml b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-full-chart.proposed.yaml
new file mode 100644
index 0000000..4059c3a
--- /dev/null
+++ b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-full-chart.proposed.yaml
@@ -0,0 +1,478 @@
+# PREPARATION RENDER ONLY; no registry publication or server validation proved.
+---
+# Source: reuse-surface/templates/landing-configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: reuse-surface-landing
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ app.kubernetes.io/component: landing
+data:
+ index.html: |
+
+ <!doctype html>
+ <html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="robots" content="noindex,nofollow">
+ <title>REUSE federation endpoint</title>
+ <style>
+ :root {
+ color-scheme: light;
+ --ink: #1d2733;
+ --muted: #536271;
+ --line: #d9e0e7;
+ --paper: #f8fafc;
+ --accent: #2066a8;
+ --accent-dark: #164b7e;
+ }
+ * {
+ box-sizing: border-box;
+ }
+ body {
+ margin: 0;
+ min-height: 100vh;
+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
+ color: var(--ink);
+ background: var(--paper);
+ display: grid;
+ place-items: center;
+ padding: 32px 18px;
+ }
+ main {
+ width: min(100%, 720px);
+ border: 1px solid var(--line);
+ border-radius: 8px;
+ background: #ffffff;
+ padding: clamp(28px, 5vw, 48px);
+ box-shadow: 0 18px 48px rgba(29, 39, 51, 0.08);
+ }
+ .eyebrow {
+ margin: 0 0 12px;
+ color: var(--accent-dark);
+ font-size: 0.86rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ }
+ h1 {
+ margin: 0;
+ font-size: clamp(2rem, 7vw, 3rem);
+ line-height: 1.05;
+ }
+ p {
+ max-width: 62ch;
+ margin: 18px 0 0;
+ color: var(--muted);
+ font-size: 1rem;
+ line-height: 1.65;
+ }
+ .actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ margin-top: 28px;
+ }
+ a {
+ color: var(--accent);
+ }
+ .button {
+ display: inline-flex;
+ min-height: 44px;
+ align-items: center;
+ justify-content: center;
+ border-radius: 6px;
+ background: var(--accent);
+ color: #ffffff;
+ padding: 0 18px;
+ font-weight: 700;
+ text-decoration: none;
+ }
+ .button:focus,
+ .button:hover {
+ background: var(--accent-dark);
+ }
+ .links {
+ margin-top: 26px;
+ padding-top: 22px;
+ border-top: 1px solid var(--line);
+ display: grid;
+ gap: 10px;
+ }
+ </style>
+ </head>
+ <body>
+ <main>
+ <p class="eyebrow">reuse.coulomb.social</p>
+ <h1>REUSE federation endpoint</h1>
+ <p>This is the Railiance REUSE capability federation service. It is an API endpoint for automated clients and operators; there is no browser login for this service.</p>
+ <div class="actions">
+ <a class="button" href="/v1/federated">Open federated index</a>
+ </div>
+ <nav class="links" aria-label="Service links">
+ <a href="/health">Health check</a>
+ <a href="/v1/federated">Federated capability index</a>
+ <a href="https://forgejo.coulomb.social/coulomb/railiance-apps/src/branch/main/docs/reuse-surface-on-railiance01.md">Operator runbook</a>
+ </nav>
+ </main>
+ </body>
+ </html>
+---
+# Source: reuse-surface/templates/pvc.yaml
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: reuse-surface-data
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+spec:
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 1Gi
+---
+# Source: reuse-surface/templates/landing-service.yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: reuse-surface-landing
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ app.kubernetes.io/component: landing
+spec:
+ type: ClusterIP
+ selector:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/component: landing
+ ports:
+ - name: http
+ port: 8080
+ targetPort: http
+ protocol: TCP
+---
+# Source: reuse-surface/templates/service.yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: reuse-surface
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+spec:
+ type: ClusterIP
+ selector:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/component: api
+ ports:
+ - name: http
+ port: 8000
+ targetPort: http
+ protocol: TCP
+---
+# Source: reuse-surface/templates/deployment.yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: reuse-surface
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ app.kubernetes.io/component: api
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/component: api
+ spec:
+ enableServiceLinks: false
+ securityContext:
+ {}
+ containers:
+ - name: reuse-surface
+ image: "forgejo.coulomb.social/coulomb/reuse-surface@sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0"
+ imagePullPolicy: IfNotPresent
+ command: ["reuse-surface", "serve"]
+ securityContext:
+ {}
+ ports:
+ - name: http
+ containerPort: 8000
+ protocol: TCP
+ envFrom:
+ - secretRef:
+ name: "reuse-surface-env"
+ env:
+ - name: REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST
+ value: "{\"REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN\":[\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738\",\"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738\"]}"
+ - name: REUSE_SURFACE_LISTEN_HOST
+ value: "0.0.0.0"
+ - name: REUSE_SURFACE_LISTEN_PORT
+ value: "8000"
+ - name: REUSE_SURFACE_DB
+ value: "/data/reuse.db"
+ - name: REUSE_SURFACE_CACHE_DIR
+ value: "/data/cache"
+ volumeMounts:
+ - name: data
+ mountPath: /data
+ readinessProbe:
+ httpGet:
+ path: /health
+ port: 8000
+ initialDelaySeconds: 10
+ periodSeconds: 10
+ timeoutSeconds: 5
+ failureThreshold: 3
+ livenessProbe:
+ httpGet:
+ path: /health
+ port: 8000
+ initialDelaySeconds: 15
+ periodSeconds: 30
+ timeoutSeconds: 5
+ failureThreshold: 3
+ resources:
+ limits:
+ cpu: 500m
+ memory: 512Mi
+ requests:
+ cpu: 100m
+ memory: 256Mi
+ volumes:
+ - name: data
+ persistentVolumeClaim:
+ claimName: reuse-surface-data
+---
+# Source: reuse-surface/templates/landing-deployment.yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: reuse-surface-landing
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ app.kubernetes.io/component: landing
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/component: landing
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
+ template:
+ metadata:
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/component: landing
+ spec:
+ enableServiceLinks: false
+ containers:
+ - name: landing
+ image: "nginxinc/nginx-unprivileged:1.27-alpine"
+ imagePullPolicy: IfNotPresent
+ ports:
+ - name: http
+ containerPort: 8080
+ protocol: TCP
+ readinessProbe:
+ httpGet:
+ path: /
+ port: http
+ initialDelaySeconds: 3
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
+ livenessProbe:
+ httpGet:
+ path: /
+ port: http
+ initialDelaySeconds: 10
+ periodSeconds: 30
+ timeoutSeconds: 3
+ failureThreshold: 3
+ resources:
+ limits:
+ cpu: 50m
+ memory: 64Mi
+ requests:
+ cpu: 10m
+ memory: 32Mi
+ volumeMounts:
+ - name: landing-page
+ mountPath: /usr/share/nginx/html/index.html
+ subPath: index.html
+ readOnly: true
+ volumes:
+ - name: landing-page
+ configMap:
+ name: reuse-surface-landing
+---
+# Source: reuse-surface/templates/ingress.yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: reuse-surface
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ traefik.ingress.kubernetes.io/router.entrypoints: websecure
+ traefik.ingress.kubernetes.io/router.tls: "true"
+spec:
+ ingressClassName: traefik
+ tls:
+ - hosts:
+ - reuse.coulomb.social
+ secretName: reuse-surface-tls
+ rules:
+ - host: reuse.coulomb.social
+ http:
+ paths:
+ - path: /health
+ pathType: Exact
+ backend:
+ service:
+ name: reuse-surface
+ port:
+ number: 8000
+ - path: /v1
+ pathType: Prefix
+ backend:
+ service:
+ name: reuse-surface
+ port:
+ number: 8000
+---
+# Source: reuse-surface/templates/landing-ingress.yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: reuse-surface-landing
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ annotations:
+ traefik.ingress.kubernetes.io/router.entrypoints: websecure
+ traefik.ingress.kubernetes.io/router.tls: "true"
+ traefik.ingress.kubernetes.io/router.priority: "1"
+spec:
+ ingressClassName: traefik
+ tls:
+ - hosts:
+ - reuse.coulomb.social
+ secretName: reuse-surface-tls
+ rules:
+ - host: reuse.coulomb.social
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: reuse-surface-landing
+ port:
+ number: 8080
+---
+# Source: reuse-surface/templates/redirect-ingress.yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: reuse-surface-http-redirect
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+ annotations:
+ traefik.ingress.kubernetes.io/router.entrypoints: web
+ traefik.ingress.kubernetes.io/router.middlewares: "reuse-reuse-surface-redirect-https@kubernetescrd"
+spec:
+ ingressClassName: traefik
+ rules:
+ - host: reuse.coulomb.social
+ http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: reuse-surface
+ port:
+ number: 8000
+---
+# Source: reuse-surface/templates/redirect-middleware.yaml
+apiVersion: traefik.io/v1alpha1
+kind: Middleware
+metadata:
+ name: reuse-surface-redirect-https
+ labels:
+ app.kubernetes.io/name: reuse-surface
+ app.kubernetes.io/instance: reuse
+ app.kubernetes.io/managed-by: Helm
+ app.kubernetes.io/version: "0.1.0"
+ app.kubernetes.io/part-of: railiance-apps
+ helm.sh/chart: reuse-surface-0.1.0
+spec:
+ redirectScheme:
+ scheme: https
+ permanent: true
diff --git a/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-preparation-receipt.json b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-preparation-receipt.json
new file mode 100644
index 0000000..c58f4b4
--- /dev/null
+++ b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-preparation-receipt.json
@@ -0,0 +1,67 @@
+{
+ "proposal_id": "CUST81-APPS-PHASE-A-LOCAL-IMAGE-R1",
+ "disposition": "approved",
+ "approved_scope": "concrete proposal preparation and local render only; not publish or production deploy",
+ "workitem": "RAPPS-WP-0017-T02",
+ "release": "reuse",
+ "namespace": "reuse",
+ "deployment": "reuse-surface",
+ "image_reference": "forgejo.coulomb.social/coulomb/reuse-surface@sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0",
+ "registry_publication_verified": false,
+ "phase_b_credential_delivery_included": false,
+ "incremental_infrastructure_cost_eur": 0,
+ "cost_basis": "existing node, same requests and replicas, same PVC, no new service or purchased capacity; build/registry execution cost not independently accounted",
+ "credible_loss_bound_eur": null,
+ "risk_basis": "qualitative supervised change: transient rollout or SQLite concurrent-access outage; RWO PVC single-node mounts need preflight; no customer production admitted; data recovery and exact atomic rollback required before execution",
+ "autopilot_authority": false,
+ "local_render_checks": "passed",
+ "evidence": {
+ "hardened-reader-local-image-r1.json": {
+ "path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/hardened-reader-local-image-r1.json",
+ "sha256": "ed7c2516925d7f16b573a70b5e48d5656a4875e9eb94bcc8760a8bdcbe07f59c"
+ },
+ "live-authenticated-source-inventory-r1.json": {
+ "path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/live-authenticated-source-inventory-r1.json",
+ "sha256": "ba669d6231c8c611191c7ad28f5914d6c47332032b23b0ea40a13f753e883073"
+ },
+ "reuse-release-runtime-metadata-r1.json": {
+ "path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/reuse-release-runtime-metadata-r1.json",
+ "sha256": "5ec901cf41b9f52628ff636c23b5bbc4789df6a9118f5cff0ff8518b287357e9"
+ },
+ "reuse-release-owner-eso-metadata-r1.json": {
+ "path": "/home/worsch/the-custodian/docs/assessments/netkingdom-2026-10-14/reuse-release-owner-eso-metadata-r1.json",
+ "sha256": "ff9aa207ae081d27d86820747a993d4bbc290ba2c354eef72388233d6733adb3"
+ }
+ },
+ "observed_runtime": {
+ "node_ip": "92.205.62.239",
+ "cpu_free_m": 440,
+ "api_surge_cpu_m": 100,
+ "api_surge_memory_mi": 256,
+ "pvc": "reuse-surface-data",
+ "pvc_access": "ReadWriteOnce",
+ "pvc_capacity": "1Gi",
+ "previous_image_digest": "forgejo.coulomb.social/coulomb/reuse-surface@sha256:2c1514cb3f5e1297ffeeac912ba36a70f8a2591588a5a4643bc58293e97132de",
+ "authenticated_sources": 0
+ },
+ "gates": [
+ "publish exact reviewed image and verify registry digest; local digest may require reviewed update if registry transforms manifest",
+ "founder approval for exact phase A and later credential CCR/phase B",
+ "recheck target headroom memory node/PVC mount scheduling and authenticated inventory immediately before apply",
+ "bounded safe server dry-run/client diff and current release revision/rollback capture",
+ "no ESO reader field during phase A; verify actual imageID health and63public baseline before phase B",
+ "revoke/remove delivered reader before any downgrade to old vulnerable image"
+ ],
+ "render_command": [
+ "helm",
+ "template",
+ "reuse",
+ "charts/reuse-surface",
+ "--namespace",
+ "reuse",
+ "-f",
+ "helm/reuse-surface-values.yaml",
+ "-f",
+ "docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml"
+ ]
+}
diff --git a/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml
new file mode 100644
index 0000000..6e6f81e
--- /dev/null
+++ b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml
@@ -0,0 +1,21 @@
+# PROPOSAL ONLY; digest is locally built, NOT published.
+# Publish exact reviewed artifact and verify registry digest before any apply.
+image:
+ repository: forgejo.coulomb.social/coulomb/reuse-surface
+ digest: sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0
+authSourceAllowlist:
+ REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN:
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738
+ - https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738
diff --git a/docs/assessments/cust81-private-reader/phase-a-local-image-r1/manifest.json b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/manifest.json
new file mode 100644
index 0000000..15cc477
--- /dev/null
+++ b/docs/assessments/cust81-private-reader/phase-a-local-image-r1/manifest.json
@@ -0,0 +1,12 @@
+{
+ "proposal_id": "CUST81-APPS-PHASE-A-LOCAL-IMAGE-R1",
+ "reviewer_owner": "railiance-apps",
+ "disposition": "approved",
+ "approved_scope": "preparation only, local full-chart render, supervised founder review required",
+ "files": {
+ "docs/assessments/cust81-private-reader/phase-a-local-image-r1/apps-owner-release-review.md": "a74e96986798a727fc87c0d3c578601579778dfd8521796d0bb81df8451c751b",
+ "docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-full-chart.proposed.yaml": "36c20c3e16757d3e888a3db02853032b33e791aa04a6055fe001121254345b81",
+ "docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-preparation-receipt.json": "3282a17ae3724619e40dd1f34846d83b2297d9ae00030618dbd269e8e2fd7d39",
+ "docs/assessments/cust81-private-reader/phase-a-local-image-r1/phase-a-values.proposed.yaml": "35284857ec987fc7a929f5c2eecdb44c7d3367f7835904692947de09918ab8f1"
+ }
+}

View file

@ -0,0 +1,21 @@
# PROPOSAL ONLY; digest is locally built, NOT published.
# Publish exact reviewed artifact and verify registry digest before any apply.
image:
repository: forgejo.coulomb.social/coulomb/reuse-surface
digest: sha256:2364b7e7859daccf9340a063654e2b09eed1bc27e0adf7b23cbb4b30135a7db0
authSourceAllowlist:
REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN:
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738
- https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738

View file

@ -0,0 +1,29 @@
{
"proposal_id": "CUST81-APPS-PRIVATE-READER-RELEASE-R1",
"status": "local_verified_live_blocked",
"real_image_digest": null,
"live_execution": false,
"cost_estimate_eur": null,
"risk_estimate_eur": null,
"estimate_status": "live cost/loss bounds require release-specific runtime headroom, recovery and image evidence; not executable before supervisor-approved estimates",
"paths": {
"charts/reuse-surface/templates/_helpers.tpl": "sha256:789606a31ac8da6dfb7a5f6ace6a77269e3be3867d2e9a11e52b19aadf6977df",
"charts/reuse-surface/templates/deployment.yaml": "sha256:2ec0be6d9aa24ed026b0c6629ab8ba003669eb0460d722fe413cd4934111540c",
"charts/reuse-surface/values.schema.json": "sha256:ea73e027e4dcd832cc0bd48fc7ccfa29158153033ca02a8dc7b25b7df0d6c2b5",
"charts/reuse-surface/values.yaml": "sha256:d1aeff71df0c53e4ecb3f4ebaac50ced7691b52c673fe9b49fbaeee6ca02c226",
"docs/assessments/cust81-private-reader/apps-owner-review-r2.md": "sha256:a3a2f2db6f0a8461a0d8299825c842c8ce427f59c86238884609d463837b3b75",
"docs/assessments/cust81-private-reader/local-verification-r2.json": "sha256:d723561845a05a76be9554596011c267fc67dd24953160f3bd7bd26a85c4812c",
"docs/assessments/cust81-private-reader/private-reader-values.r1.yaml": "sha256:e02a319aca9c4860cdb8338009e60af6723bdb1fc17a591db0824273206eff83",
"docs/assessments/cust81-private-reader/reuse-surface-runtime-externalsecret.r1.yaml": "sha256:adfb34c0ee4d01bc602f57cd2320f1658465fb8f8660978828fffa05a5b604b5",
"docs/assessments/cust81-private-reader/runtime-auth-source-allowlist-r1.json": "sha256:e1948c537e206b30fc72b9e4732a3f600d92e131813e6f7ecfd4bfbb18c27286",
"docs/assessments/cust81-private-reader/supervision-preparation-r1.json": "sha256:232f195026d704164b5973b5098002205445ff3ed6b0d2dd0c4a3c92c6ad9ca5",
"docs/assessments/cust81-private-reader/verify_preparation.py": "sha256:c07921ea3fcd7c646aa6f28f34f7cdcb552e893341fe53dc7102ee376541d04d",
"scripts/reuse_authenticated_source_inventory.py": "sha256:42eed5513db090d338daec39258b89a4ce2e9369d175c3c8312904ed68867ee1",
"workplans/RAPPS-WP-0017-reuse-private-reader-release.md": "sha256:3a114a461647b46f3cc8e0ff9aa16b69aed0429cbc1578edf9b0fed5e220cc55"
},
"chart_patch_sha256": "39ebaa7f4050f9204fe8ee38364fbbce874903447ac45ccd408cf434aa6e4a73",
"revision": 2,
"refinement_or_rescue": true,
"original_revision_preserved": "root owner-assembly/apps-r1 archive",
"correction": "pod SQL native registration url projection plus exact SQLite readonly fixture, safe legacy routes and untrusted successful output refusal"
}

View file

@ -0,0 +1,5 @@
# PREPARATION ONLY: empty digest deliberately prevents rendering/deployment.
# Fill only after reuse-surface publishes and reviews the fully hardened image.
image:
digest: ""
authSourceAllowlist: {"REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN": ["https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738", "https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738"]}

View file

@ -0,0 +1,46 @@
# PROPOSAL ONLY: phase B, after hardened runtime verified and CCR approved.
# reuse-surface hub runtime secrets from OpenBao (RAILIANCE-WP-0011 / CCR-2026-0005).
#
# OpenBao path (platform KV v2): workloads/reuse/reuse-surface/runtime-secrets
# Fields: REUSE_SURFACE_TOKEN, REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET
#
# Prereqs on railiance01:
# - External Secrets Operator (make eso-deploy)
# - ClusterSecretStore openbao-reuse (railiance-platform openbao-secretstore)
# - OpenBao policy workload-kv-read-reuse-surface-runtime + ESO token
# (make reuse-openbao-eso-token-apply)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: reuse-surface-runtime
namespace: reuse
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/part-of: railiance-apps
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: openbao-reuse
target:
# Explicit target metadata prevents ESO copying source last-applied annotations.
template:
metadata:
labels:
app.kubernetes.io/name: reuse-surface
app.kubernetes.io/part-of: railiance-apps
name: reuse-surface-env
creationPolicy: Owner
data:
- secretKey: REUSE_SURFACE_TOKEN
remoteRef:
key: workloads/reuse/reuse-surface/runtime-secrets
property: REUSE_SURFACE_TOKEN
- secretKey: REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET
remoteRef:
key: workloads/reuse/reuse-surface/runtime-secrets
property: REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET
- secretKey: REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN
remoteRef:
key: workloads/reuse/reuse-surface/forgejo-source-read
property: FORGEJO_SOURCE_TOKEN

View file

@ -0,0 +1,18 @@
{
"REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN": [
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/capabilities/capability.railiance.openbao-package.md?ref=35672be138036c8433a5ac5de91e068c03c2b124",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-openbao/raw/registry/indexes/capabilities.yaml?ref=35672be138036c8433a5ac5de91e068c03c2b124",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/capabilities/capability.railiance.policy-publication-package.md?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-policy-nexus/raw/registry/indexes/capabilities.yaml?ref=088b78ac03b0cebeec34a69aae3569eb7ec2f9c3",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/capabilities/capability.railiance.postgres-isolation-recovery.md?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-postgres/raw/registry/indexes/capabilities.yaml?ref=a9f569c96d74aa384ac8d3ac4aa960e4061550b5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/capabilities/capability.railiance.sbom-runtime-package.md?ref=adbedd349e8df97be43a1f57db7095af45ff29d1",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-sbom-nexus/raw/registry/indexes/capabilities.yaml?ref=adbedd349e8df97be43a1f57db7095af45ff29d1",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/capabilities/capability.railiance.telemetry-package.md?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-telemetry/raw/registry/indexes/capabilities.yaml?ref=f158307e24b86bab88a1af4830ff6b4f85afdeb5",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/capabilities/capability.railiance.tenant-engine-package.md?ref=9bdc86572728783a5ed94266f04f7b12d414c557",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-tenant-engine/raw/registry/indexes/capabilities.yaml?ref=9bdc86572728783a5ed94266f04f7b12d414c557",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/capabilities/capability.railiance.user-engine-package.md?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738",
"https://forgejo.coulomb.social/api/v1/repos/coulomb/rapp-user-engine/raw/registry/indexes/capabilities.yaml?ref=f35108f9e1b8702fb6c526fe42b2fec5ca032738"
]
}

View file

@ -0,0 +1,24 @@
{
"proposal_id": "CUST81-APPS-PRIVATE-READER-RELEASE-R1",
"owner": "railiance-apps",
"review_revision": 3,
"disposition": "approved",
"approved_scope": "ordinary source-only standard digest representation correction; no live runtime change",
"refinement_or_rescue": true,
"original_manifest_sha256": "45d467c2bb48462a388f5df4ba5188492d406bdddbddfbf3487bd2077486dec8",
"qualified_manifest_sha256": "324757f27a36090e34101adf9a68feb8f19530463303e53fec46abe2092943b8",
"source_file_digests_unchanged": true,
"scanner_rule": "generic-api-key",
"affected_field": "paths[docs/assessments/cust81-private-reader/reuse-surface-runtime-externalsecret.r1.yaml]",
"scanner_version": "8.30.1",
"pinned_scanner_sha256": "88f91962aa2f93ac6ab281d553b9e125f5197bbbce38f9f2437f7299c32e5509",
"original_scanner_exit": 20,
"candidate_scanner_exit": 0,
"mechanism": "standard sha256-qualified metadata identifier; unchanged scanner/config, no ignore/exception/bypass",
"backup_ref": "custody/cust81-apps-unpublished-r2",
"original_commits": [
"4e8e0f5",
"6a8a54d"
],
"live_execution_approved": false
}

View file

@ -0,0 +1,10 @@
{
"agent": "delegated-railiance-apps-cust81-preparation",
"mode": "supervised",
"scope": "isolated local chart/config/ESO proposal preparation, local verification only",
"supervisor": "root custodian coordinating founder-authorized work",
"promotion_evidence": null,
"runtime_enforcement_verified": false,
"authority_granted": false,
"live_execution_authorized": false
}

View file

@ -0,0 +1,94 @@
"""Local chart and non-disclosure checks only; never contacts a cluster."""
import hashlib
import importlib.util
import json
from pathlib import Path
import subprocess
import yaml
ROOT = Path(__file__).resolve().parents[3]
ARTIFACT = Path(__file__).resolve().parent
calls = []
def render(extra, success=True):
command = ['helm', 'template', 'reuse', str(ROOT / 'charts/reuse-surface'), '-f', str(ROOT / 'helm/reuse-surface-values.yaml'), *extra]
proc = subprocess.run(command, capture_output=True, text=True)
calls.append({'command': command, 'exit_code': proc.returncode, 'expected_success': success})
assert (proc.returncode == 0) == success
return list(yaml.safe_load_all(proc.stdout)) if success else []
def api(docs):
return next(d for d in docs if d and d.get('kind') == 'Deployment' and d['metadata']['name'] == 'reuse-surface')
current = api(render([]))
assert current['spec']['template']['spec']['containers'][0]['image'].endswith(':main-6cbc862')
assert next(e['value'] for e in current['spec']['template']['spec']['containers'][0]['env'] if e['name']=='REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST') == '{}'
proposal = ['-f', str(ARTIFACT / 'private-reader-values.r1.yaml')]
render(proposal, False) # unknown real digest is a hard gate
# Synthetic digest is render-only, and expressly not promotion/build evidence.
render(proposal+['--set', 'image.digest=sha256:bad'], False)
render(proposal+['--set-json', 'authSourceAllowlist={"BAD":["http://attacker.invalid"]}', '--set', 'image.digest=sha256:'+'0'*64], False)
docs = render(proposal+['--set', 'image.digest=sha256:'+'0'*64])
deployment = api(docs)
container = deployment['spec']['template']['spec']['containers'][0]
assert container['image'].endswith('@sha256:'+'0'*64)
allowlist=json.loads(next(e['value'] for e in container['env'] if e['name']=='REUSE_SURFACE_AUTH_SOURCE_ALLOWLIST'))
expected = json.loads((ARTIFACT/'runtime-auth-source-allowlist-r1.json').read_text())
assert allowlist==expected and len(next(iter(allowlist.values())))==14
assert deployment['spec']['strategy'] == current['spec']['strategy']
assert container['resources']==current['spec']['template']['spec']['containers'][0]['resources']
assert deployment['spec']['template']['spec']['volumes']==current['spec']['template']['spec']['volumes']
assert container['volumeMounts']==current['spec']['template']['spec']['containers'][0]['volumeMounts']
secret=yaml.safe_load((ARTIFACT/'reuse-surface-runtime-externalsecret.r1.yaml').read_text())
baseline=yaml.safe_load((ROOT/'manifests/reuse-surface-runtime-externalsecret.yaml').read_text())
assert secret['spec']['data'][:-1]==baseline['spec']['data']
assert secret['spec']['secretStoreRef']==baseline['spec']['secretStoreRef']
assert secret['spec']['data'][-1]=={'secretKey':'REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN','remoteRef':{'key':'workloads/reuse/reuse-surface/forgejo-source-read','property':'FORGEJO_SOURCE_TOKEN'}}
spec=importlib.util.spec_from_file_location('inventory',ROOT/'scripts/reuse_authenticated_source_inventory.py')
mod=importlib.util.module_from_spec(spec);spec.loader.exec_module(mod)
url=expected['REUSE_SURFACE_FORGEJO_SOURCE_READ_TOKEN'][1]
assert len(mod.sanitize([['rapp-openbao','FIXTURE_READ_TOKEN',url]]))==1
legacy='https://forgejo.coulomb.social/coulomb/rapp-openbao/raw/branch/main/registry/indexes/capabilities.yaml'
assert len(mod.sanitize([['rapp-openbao','FIXTURE_READ_TOKEN',legacy]]))==1
# Exercise the EXACT pod code against actual native registration keys in SQLite.
# Replacing only the fixture DB path leaves the metadata SELECT/read-only mode intact.
import sqlite3,tempfile
with tempfile.TemporaryDirectory(prefix='apps-reader-fixture-') as temp:
fixture=Path(temp)/'reuse.db'
with sqlite3.connect(fixture) as db:
db.execute('CREATE TABLE registrations(repo TEXT PRIMARY KEY, payload TEXT NOT NULL, registered_at TEXT, updated_at TEXT)')
db.execute('INSERT INTO registrations VALUES(?,?,?,?)', ('rapp-openbao',json.dumps({'repo':'rapp-openbao','url':url,'auth_env':'FIXTURE_READ_TOKEN','description':'fixture-secret-never-emit'}),'fixture','fixture'))
db.execute('INSERT INTO registrations VALUES(?,?,?,?)', ('anonymous',json.dumps({'repo':'anonymous','url':legacy}),'fixture','fixture'))
pod_code=mod.POD_CODE.replace('/data/reuse.db',str(fixture))
proc=subprocess.run(['python3','-c',pod_code],capture_output=True,text=True,check=True)
assert json.loads(proc.stdout)==[['rapp-openbao','FIXTURE_READ_TOKEN',url]]
assert 'fixture-secret' not in proc.stdout
assert len(mod.sanitize(json.loads(proc.stdout)))==1
with sqlite3.connect(fixture) as db: assert db.execute('SELECT count(*) FROM registrations').fetchone()==(2,)
assert 'mode=ro' in pod_code and '$.index_url' not in pod_code
assert 'os.environ' not in pod_code and 'getenv' not in pod_code and 'kubectl' not in pod_code
for bad in ['https://token@forgejo.coulomb.social/x', url+'&token=fixture-secret','http://attacker.invalid',url+'#fixture-secret',legacy+'?token=fixture-secret',legacy+'/../credentials',legacy+'%3Ftoken=fixture-secret']:
try: mod.sanitize([['rapp-openbao','FIXTURE_READ_TOKEN',bad]])
except ValueError: pass
else: raise AssertionError('unsafe URL accepted')
# Errors from kubectl are discarded before output; no subprocess invoked in test.
original=mod.subprocess.run
class Failure:
returncode=1;stdout=b'fixture-secret';stderr=b'fixture-secret'
mod.subprocess.run=lambda *args,**kwargs: Failure()
import sys,io,contextlib
argv=sys.argv;sys.argv=['inventory','--kubeconfig','fixture-path']
buf=io.StringIO()
with contextlib.redirect_stdout(buf): assert mod.main()==1
assert 'fixture-secret' not in buf.getvalue()
class UnsafeSuccess:
returncode=0;stdout=json.dumps([['rapp-openbao','FIXTURE_READ_TOKEN',url+'&token=fixture-secret']]).encode();stderr=b''
mod.subprocess.run=lambda *args,**kwargs: UnsafeSuccess()
buf=io.StringIO()
with contextlib.redirect_stdout(buf): assert mod.main()==1
assert 'fixture-secret' not in buf.getvalue()
sys.argv=argv;mod.subprocess.run=original
result={'status':'passed','local_only':True,'real_image_digest':None,'synthetic_digest_used_only_to_check_rendering':True,'checks':['production rendering unchanged except empty fail-closed allowlist','unknown/malformed digest fails','HTTP allowlist fails schema','exact14 URLs roundtrip','strategy resources PVC retained','dedicated ESO mapping preserves current fields/store','metadata sanitizer excludes userinfo/query secrets/fragments','kubectl failure output discarded','exact pod SQL real payload URL keys readonly fixture and anonymous filtering','legacy Forgejo branch URL accepted without weakening credential query refusal'],'helm_calls':calls}
(ARTIFACT/'local-verification-r2.json').write_text(json.dumps(result,indent=2)+'\n')
print(json.dumps({'status':'passed','checks':len(result['checks'])}))

View file

@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Read-only authenticated source metadata; never read env or Kubernetes Secrets.
Caller must first confirm the kubeconfig targets railiance01. Raw command
stdout/stderr and exception text are never emitted. No credentials are needed
beyond the caller's separately approved Kubernetes observation/exec lane.
"""
import argparse
import json
import re
import subprocess
from urllib.parse import urlsplit, parse_qs
# SQL projects metadata only; the registration payload itself is never printed.
POD_CODE = '''import json, sqlite3
with sqlite3.connect("file:/data/reuse.db?mode=ro", uri=True) as db:
rows=db.execute("SELECT repo, json_extract(payload, '$.auth_env'), json_extract(payload, '$.url') FROM registrations WHERE json_extract(payload, '$.auth_env') IS NOT NULL AND json_extract(payload, '$.auth_env') != ''").fetchall()
print(json.dumps(rows))
'''
def sanitize(rows):
result = []
for repo, name, url in rows:
if not isinstance(repo, str) or not re.fullmatch(r'[a-zA-Z0-9_.-]{1,128}', repo):
raise ValueError('invalid metadata')
if not isinstance(name, str) or not re.fullmatch(r'[A-Z][A-Z0-9_]{0,127}', name):
raise ValueError('invalid metadata')
parts = urlsplit(url)
# URLs are untrusted stored data; refuse userinfo/fragments and arbitrary
# query fields (which could contain credentials). Never echo invalid rows.
query = parse_qs(parts.query, keep_blank_values=True)
if (parts.scheme != 'https' or parts.username or parts.password or parts.fragment
or parts.hostname != 'forgejo.coulomb.social' or parts.port not in (None, 443)
or not (re.fullmatch(r'/api/v1/repos/coulomb/[a-zA-Z0-9_.-]+/raw/registry/indexes/[a-zA-Z0-9_.-]+', parts.path)
or re.fullmatch(r'/coulomb/[a-zA-Z0-9_.-]+/raw/(?:branch|commit|tag)/[a-zA-Z0-9_.-]+/registry/indexes/[a-zA-Z0-9_.-]+', parts.path))
or any(k != 'ref' for k in query)
or ('ref' in query and (len(query['ref']) != 1 or not re.fullmatch(r'[a-zA-Z0-9_.-]{1,128}', query['ref'][0])))):
raise ValueError('unsafe metadata')
result.append({'repo': repo, 'auth_env': name, 'index_url': url})
return sorted(result, key=lambda row: row['repo'])
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--kubeconfig', required=True)
args = parser.parse_args()
try:
proc = subprocess.run(['kubectl', '--kubeconfig', args.kubeconfig, '-n', 'reuse',
'exec', 'deployment/reuse-surface', '-c', 'reuse-surface', '--', 'python3', '-c', POD_CODE],
capture_output=True, timeout=30)
if proc.returncode:
raise RuntimeError('inventory unavailable')
rows = sanitize(json.loads(proc.stdout))
except Exception:
print(json.dumps({'status': 'refused_or_unavailable', 'raw_output_discarded': True}))
return 1
print(json.dumps({'status': 'verified', 'authenticated_source_count': len(rows), 'sources': rows}, indent=2))
return 0
if __name__ == '__main__':
raise SystemExit(main())

View file

@ -0,0 +1,57 @@
---
id: RAPPS-WP-0017
type: workplan
title: "Release hardened reuse federation with seven-source metadata reader"
domain: financials
repo: railiance-apps
status: proposed
owner: codex
created: "2026-10-15"
updated: "2026-10-15"
flavor: implementation
depends_on: [RPF-WP-0058, REUSE-WP-0025]
---
Provisional id in isolated preparation checkout; root integration must confirm
availability. No hub registration, fix-consistency or push until integration.
Source owners approved metadata disclosure under CUST81 R1; that is not approval
for live credential issuance or workload rollout. Apps owns only S5 release.
## Prepare bounded release contract
```task
id: RAPPS-WP-0017-T01
status: done
priority: high
```
Prepare chart allowlist/digest support, exact14 URL override and separate phase-B
ESO manifest, own preparation review and meaningful local validation.
Evidence: docs/assessments/cust81-private-reader/apps-owner-review-r1.md.
## Verify and promote hardened runtime before reader delivery
```task
id: RAPPS-WP-0017-T02
status: wait
priority: high
```
Wait for published fully hardened image digest/source/tests plus owner reviews
and change authorization. Obtain metadata-only existing auth-source migration
inventory, live headroom/PVC evidence, exact server dry-run/diff, baseline health
and rollback receipt. Phase A deploy excludes reader ESO mapping.
## Deliver reviewed reader and prove complete hosted discovery
```task
id: RAPPS-WP-0017-T03
status: wait
priority: high
```
After verified phase A and approved/executed platform CCR, apply phase-B ESO
mapping and restart hardened runtime through reviewed owner lane. Require
sanitized ESO/key-presence proof and reuse native14 fetch/7 entry hashes before
registration. Final CUST81 owner verifies70/70 hosted; rollback revokes/removes
reader before any vulnerable image restoration.