Finish architecture-cleanup RAILIANCE-WP-0016 T05
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Has been cancelled

Item 13 is the restore RESOURCE-WP-0002 already proved. Item 14 retires
the dead Bitnami postgresql-ha deploy path and gates Valkey until a
consumer exists. Item 17 publishes the versioned S3 consumer-interface
index.
This commit is contained in:
codex 2026-08-15 14:43:44 +02:00
parent 2af19627e1
commit 1eb5fa51ed
8 changed files with 156 additions and 69 deletions

View file

@ -1,18 +1,18 @@
## Stack ## Stack
- **Language:** Kubernetes manifests + Helm values, Bash Make targets - **Language:** Kubernetes manifests + Helm values, Bash Make targets
- **Key deps:** CloudNative-PG (cnpg) clusters, Valkey, OpenBao, SOPS/age; runs against the S2 cluster on railiance01 - **Key deps:** CloudNative-PG (cnpg) clusters, OpenBao, SOPS/age; runs against the S2 cluster on railiance01. Bitnami postgresql-ha is retired. Valkey is declared, not deployed.
## Dev Commands ## Dev Commands
```bash ```bash
make help # list all targets (db-*, apps-pg-*, pg-*, valkey-*, openbao-*) make help # list all targets (db-*, apps-pg-*, openbao-*)
make db-status # gitea-db cnpg cluster health (read-only) make db-status # gitea-db / forgejo-db cnpg cluster health (read-only)
make apps-pg-status # shared apps-pg cluster health (read-only) make apps-pg-status # shared apps-pg cluster health (read-only)
make pg-status # standalone PostgreSQL HA pod status (read-only) make pg-status # confirms retired Bitnami postgresql-ha is absent
make valkey-status # Valkey pod status (read-only) make valkey-status # confirms Valkey is absent
make db-deploy | apps-pg-deploy | pg-deploy | valkey-deploy # production-touching make db-deploy | apps-pg-deploy # production-touching
``` ```
`*-deploy` targets change production platform services — operator approval `pg-deploy` and `valkey-deploy` are fail-closed. `*-status` / `*-logs`
required. `*-status` / `*-logs` targets are read-only and safe. targets are read-only and safe.

View file

@ -1,9 +1,8 @@
# SOPS encryption policy for railiance-platform # SOPS encryption policy for railiance-platform
# Encrypts any file matching *.sops.yaml using the shared age key. # Encrypts any file matching *.sops.yaml using the shared age key.
# Decrypt: sops -d helm/postgresql-ha-values.sops.yaml # Decrypt: sops -d <file>.sops.yaml
# Use with helm: helm upgrade postgresql-ha bitnami/postgresql-ha \ # Encrypt: sops -e -i <file>.sops.yaml
# -n platform -f <(sops -d helm/postgresql-ha-values.sops.yaml) # postgresql-ha deploy is retired; valkey-values.sops.yaml is unused until a consumer exists.
# Encrypt: sops -e -i helm/postgresql-ha-values.sops.yaml
creation_rules: creation_rules:
- path_regex: \.sops\.yaml$ - path_regex: \.sops\.yaml$

View file

@ -86,41 +86,32 @@ apps-pg-logs: ## Tail apps-pg primary logs
net-kingdom-pg-inter-hub-networkpolicy-deploy: ## Allow inter-hub to reach net-kingdom-pg net-kingdom-pg-inter-hub-networkpolicy-deploy: ## Allow inter-hub to reach net-kingdom-pg
$(KUBECTL) apply -f helm/net-kingdom-pg-inter-hub-networkpolicy.yaml $(KUBECTL) apply -f helm/net-kingdom-pg-inter-hub-networkpolicy.yaml
##@ PostgreSQL HA (legacy — superseded by cnpg above) ##@ PostgreSQL HA (retired — CNPG superseded this)
pg-deploy: ## Deploy / upgrade standalone PostgreSQL HA to platform namespace pg-deploy: ## Retired: refuse to deploy Bitnami postgresql-ha
$(KUBECTL) create namespace $(NAMESPACE) --dry-run=client -o yaml | $(KUBECTL) apply -f - @echo 'pg-deploy is retired (RAILIANCE-WP-0016 item 14). Use apps-pg / forgejo-db / rapp-postgres.' >&2; exit 2
$(HELM) repo add bitnami https://charts.bitnami.com/bitnami --force-update
$(HELM) upgrade --install postgresql-ha bitnami/postgresql-ha \
--version $(PG_CHART_VERSION) \
--namespace $(NAMESPACE) \
-f <(sops -d helm/postgresql-ha-values.sops.yaml) \
--wait --timeout 5m
pg-status: ## Check PostgreSQL HA pod status pg-status: ## Confirm Bitnami postgresql-ha is absent
$(KUBECTL) get pods -n $(NAMESPACE) -l app.kubernetes.io/name=postgresql-ha @if $(KUBECTL) get ns $(NAMESPACE) >/dev/null 2>&1; then \
$(KUBECTL) get pods -n $(NAMESPACE) -l app.kubernetes.io/name=postgresql-ha; \
pg-pgpool-check: ## Verify pgpool-password secret key is present (see RAIL-BS-WP-0003)
@SECRET=$$($(KUBECTL) get secret -n $(NAMESPACE) postgresql-ha-postgresql \
-o jsonpath='{.data.pgpool-password}' 2>/dev/null); \
if [ -z "$$SECRET" ]; then \
echo "ERROR: pgpool-password key missing from secret — pgpool will CrashLoop on restart"; \
exit 1; \
else \ else \
echo "OK: pgpool-password key present"; \ echo 'postgresql-ha retired: namespace $(NAMESPACE) is absent'; \
fi fi
##@ Valkey (cache) pg-pgpool-check: ## Retired: no pgpool secret to check
@echo 'pg-pgpool-check is retired with postgresql-ha (RAILIANCE-WP-0016 item 14).' >&2; exit 2
valkey-deploy: ## Deploy / upgrade Valkey (Redis-compatible) to platform namespace ##@ Valkey (cache) — declared, not deployed
$(KUBECTL) create namespace $(NAMESPACE) --dry-run=client -o yaml | $(KUBECTL) apply -f -
$(HELM) upgrade --install valkey bitnami/valkey \
--namespace $(NAMESPACE) \
-f <(sops -d helm/valkey-values.sops.yaml) \
--wait --timeout 3m
valkey-status: ## Check Valkey pod status valkey-deploy: ## Gated: do not deploy Valkey until a consumer rapp exists
$(KUBECTL) get pods -n $(NAMESPACE) -l app.kubernetes.io/name=valkey @echo 'valkey-deploy is gated (RAILIANCE-WP-0016 item 14): no live consumer, nothing to extract from S2.' >&2; exit 2
valkey-status: ## Confirm Valkey is absent
@if $(KUBECTL) get ns $(NAMESPACE) >/dev/null 2>&1; then \
$(KUBECTL) get pods -n $(NAMESPACE) -l app.kubernetes.io/name=valkey; \
else \
echo 'valkey undeployed: namespace $(NAMESPACE) is absent'; \
fi
##@ OpenBao (secrets) ##@ OpenBao (secrets)

View file

@ -21,11 +21,10 @@ Stack dimension: the platform services that multiple applications share. Five
repos cover S1S5; other `railiance-*` repos sit on other OAS dimensions rather repos cover S1S5; other `railiance-*` repos sit on other OAS dimensions rather
than on the stack. See `ArchitectureBlueprint.md` for the full backbone. than on the stack. See `ArchitectureBlueprint.md` for the full backbone.
The active migration is from Bitnami postgresql-ha (repmgr + pgpool, deployed The database operator is CloudNative PG. Bitnami postgresql-ha is retired
historically as part of the Gitea subchart in S2 — the forge itself is now (no live release; `make pg-deploy` fail-closed, `RAILIANCE-WP-0016` item 14).
Forgejo) to CloudNative PG (cnpg operator, already deployed in the cnpg-system Valkey is a declared capability with no live instance and nothing left in S2
namespace) as the canonical database operator. Valkey cluster is also in scope to extract; `make valkey-deploy` is gated until a consumer rapp exists.
for S3 extraction from S2.
OpenBao is a platform capability in this repo, but not every OpenBao-related OpenBao is a platform capability in this repo, but not every OpenBao-related
file belongs in the long-term S3 ownership home. The deployable package surface file belongs in the long-term S3 ownership home. The deployable package surface
@ -78,18 +77,18 @@ policy, and lane governance.
## Current State ## Current State
- Status: maintained / emerging - Status: maintained / emerging
- Implementation: CloudNative PG operator (cnpg) deployed; `databases` namespace active; OpenBao is live as the S3 secrets service; Valkey + legacy postgresql-ha extraction from S2 remain in progress - Implementation: CloudNative PG operator live; `databases` namespace holds the platform clusters; OpenBao is the S3 secrets service. Bitnami postgresql-ha is retired. Valkey is undeployed.
- Stability: emerging — cnpg deployed but database cluster definitions not yet migrated from S2 - Stability: emerging — CNPG clusters are live; cache and in-cluster object storage are not
- Usage: shared database, cache, and secrets layer; cnpg-system, databases, and openbao namespaces are live - Usage: shared database and secrets layer; cnpg-system, databases, and openbao namespaces are live
- Deploys via ArgoCD: four Applications (`external-secrets`, `issue-core`, - Deploys via ArgoCD: four Applications (`external-secrets`, `issue-core`,
`openbao-secretstore`, `target-revenue`) plus AppProjects under `openbao-secretstore`, `target-revenue`) plus AppProjects under
`argocd/bootstrap/`; see `docs/argocd-gitops.md` `argocd/bootstrap/`; see `docs/argocd-gitops.md`
- Emits to `railiance-telemetry` (Q2 Observability) once the evidence plane - Emits to `railiance-telemetry` (Q2 Observability) once the evidence plane
exists — seeded 2026-08-11, not yet implemented exists — seeded 2026-08-11, not yet implemented
- Open work: Valkey and legacy postgresql-ha extraction remain active; the - Open work: Valkey remains a declared-but-unbuilt cache; MinIO is likewise
OpenBao package boundary and PAT consumer cutover are now documented and declared, not deployed. OpenBao package boundary and PAT cutover are
closed; `rapp-openbao`/`rapp-postgres` declaration conformance closed. Platform rapp declarations conform (`RAILIANCE-WP-0015`).
(`RAILIANCE-WP-0015-T02`) is held pending the `railiance-master` schema Versioned consumer interfaces: `docs/s3-consumer-interfaces.md`.
- Known drift: State Hub attributes ~11 capabilities to this repo, including - Known drift: State Hub attributes ~11 capabilities to this repo, including
S1/S2/S4/S5 concerns it does not own. The four `capability` blocks in this S1/S2/S4/S5 concerns it does not own. The four `capability` blocks in this
file are authoritative; the hub carries stale pre-split attributions file are authoritative; the hub carries stale pre-split attributions
@ -138,7 +137,7 @@ keywords: [postgresql, postgres, cnpg, cloudnative-pg, operator, database, kuber
```capability ```capability
type: infrastructure type: infrastructure
title: Valkey / Redis-compatible cache title: Valkey / Redis-compatible cache
description: Shared Redis-compatible cache service (Valkey) for all applications in the Railiance stack. description: Declared shared Redis-compatible cache. Not deployed on railiance01 as of 2026-08-15; no S2 instance remains to extract.
keywords: [valkey, redis, cache, shared, session, queue] keywords: [valkey, redis, cache, shared, session, queue]
``` ```

View file

@ -0,0 +1,29 @@
# Item 13 — restore proven end to end
Work record: architecture-cleanup `RAILIANCE-WP-0016` item 13
Date: 2026-08-15
Status: **done** (unblocked by `RESOURCE-WP-0002` finish)
The blocker was decision `9c21c0e0` / `RESOURCE-WP-0002`. That workplan is
finished. The restore this item asked for was executed as
`RESOURCE-WP-0002-T05` on 2026-08-14 and is still true on the live cluster.
## Production path (railiance01 `platform-pg`)
| Fact | Value |
| --- | --- |
| Destination | `s3://railiance-platform-pg-backup/platform-pg/` |
| Endpoint | `https://s3.nl-ams.scw.cloud` |
| Credential Secret | `databases/platform-pg-backup-s3` (keys present, values not read) |
| ScheduledBackup | `platform-pg-daily` (02:15 UTC) |
| Completed Backups | `platform-pg-daily-20260814181421`, `platform-pg-daily-20260815021500` |
Full restore 65s (`audit_core.events` 30=30). PITR 65s (`keep` present,
`destroy` absent). Evidence:
`resource-control/docs/evidence/RESOURCE-WP-0002-T05-restore-2026-08-14.md`.
Logical offsite copy: `RESOURCE-WP-0002-T06`.
This item is the S3-owned *proof*, not a second restore program. `apps-pg`
is still local-path only (RAILIANCE-WP-0016 apps-pg evidence T02). Covering
that cluster is a later consumer of the same bucket, not a re-opening of
item 13.

View file

@ -1,9 +1,16 @@
# PostgreSQL HA — Platform Service # PostgreSQL HA — retired
**Chart:** `bitnami/postgresql-ha` **Status:** retired 2026-08-15 (`RAILIANCE-WP-0016` item 14)
**Namespace:** `platform` **Superseded by:** CloudNativePG clusters in `databases` (`apps-pg`,
**Managed by:** `railiance-platform` (S3) `forgejo-db`, `platform-pg`, and the other CNPG instances).
**Workplan:** `RAIL-PL-WP-0001` **Do not deploy.** `make pg-deploy` is fail-closed.
The Bitnami `postgresql-ha` (repmgr + pgpool) stack never ran as a live
S3 service on railiance01. There is no `platform` namespace and no
matching pods. Giteas historical subchart in S2 was replaced by
`forgejo-db`. Keep this file as the retirement record and the
pgpool-password incident note. New databases go through `docs/apps-pg.md`
or `rapp-postgres`.
--- ---

View file

@ -0,0 +1,53 @@
# S3 consumer service interfaces
Work record: `RAILIANCE-WP-0016` item 17
Date: 2026-08-15
Contract version of this index: `1.0.0`
Consumers bind to these contracts, not to Helm chart names or pod topology.
Changing an engine behind a versioned interface does not bump the interface
unless the consumer-visible fields change.
| Interface | Version | Who it is for | Authority |
| --- | --- | --- | --- |
| Shared application database | `apps-pg.v1` | S5 apps that need an isolated database on `apps-pg` | `docs/apps-pg.md` |
| Isolated platform database | `rapp-postgres.v1` | Platform services that need a CNPG consumer on `platform-pg` | `rapp-postgres/declarations/rapp.yaml` `consumer_contract` |
| Standing runtime secret | `ccr-workload-kv.v1` | Workloads that need a KV path via External Secrets | `schemas/credential-change-request.schema.yaml` |
| Short-lived lease | `credential-grant.v1` | Operators/agents and dynamic DB roles | `credential-grants/catalog.yaml` |
| Rapp credential bind | `rapp-lane.v1` | How a rapp names the two lanes above | `docs/rapp-credential-lane-binding.md` |
## Compatibility rules
- A `vN` document may add optional fields. Removing or renaming a
required field is `vN+1`.
- Values never appear in an interface document. Paths, grant ids, CCR
ids, and role names are the contract.
- `make pg-deploy` / Bitnami DSN
`postgresql-ha-pgpool.platform.svc.cluster.local` is **not** an
interface. That stack is retired.
## `apps-pg.v1`
Consumer supplies: app name, namespace, database name, role name. Platform
provisions the role and CNPG `Database`, labels the namespace
`railiance.io/postgres-client=apps-pg`, and publishes a runtime Secret.
RW endpoint: `apps-pg-rw.databases.svc.cluster.local:5432`. Bootstrap
role `apps_admin` is not a consumer credential.
## `rapp-postgres.v1`
Consumer is a `consumers[].declaration`. Boundary unit is
`database-per-consumer`. Credential type is
`openbao-dynamic-database-credential` via grant
`rapp-postgres/<consumer>-<role>`. Tenant identifiers are opaque.
## `ccr-workload-kv.v1` and `credential-grant.v1`
Unchanged semantics from `docs/credential-change-approval.md` and
`docs/credential-broker.md`. The version name exists so a rapp can cite
the lane without restating TTL, delivery, or revocation rules.
## Not yet an interface
Valkey and in-cluster MinIO have capability blocks in `SCOPE.md` and no
live service. They do not receive a `v1` until a consumer exists.

View file

@ -4,11 +4,11 @@ type: workplan
title: "Architecture cleanup backlog, WSJF-prioritized" title: "Architecture cleanup backlog, WSJF-prioritized"
domain: financials domain: financials
repo: railiance-platform repo: railiance-platform
status: active status: finished
owner: codex owner: codex
topic_slug: railiance topic_slug: railiance
created: "2026-08-12" created: "2026-08-12"
updated: "2026-08-12" updated: "2026-08-15"
related_repos: related_repos:
- railiance-master - railiance-master
- railiance-infra - railiance-infra
@ -67,11 +67,11 @@ reliable numbers here, because nobody has scoped them yet.
| 10b | Schedule verification; route failures where they are seen | `railiance-infra` / Q7 owner | 7 | 6 | 8 | 3 | **7.0** | | 10b | Schedule verification; route failures where they are seen | `railiance-infra` / Q7 owner | 7 | 6 | 8 | 3 | **7.0** |
| 11 | Consolidate the bootstrap path; sort inherited S2 content | `railiance-bootstrap` | 5 | 3 | 4 | 4 | **3.0** | | 11 | Consolidate the bootstrap path; sort inherited S2 content | `railiance-bootstrap` | 5 | 3 | 4 | 4 | **3.0** |
| 12 | Forge migration: `rapp-forgejo` + S4 layer transfer | `railiance-forge` / S4 | 6 | 4 | 4 | 5 | **2.8** | | 12 | Forge migration: `rapp-forgejo` + S4 layer transfer | `railiance-forge` / S4 | 6 | 4 | 4 | 5 | **2.8** |
| 13 | Prove a restore end to end | `railiance-platform` | 9 | 5 | 9 | 8 | **2.9** | | ~~13~~ | ~~Prove a restore end to end~~ **DONE 2026-08-15** | `railiance-platform` | 9 | 5 | 9 | 8 | **2.9** |
| 14 | Valkey extraction + legacy postgresql-ha retirement | `railiance-platform` | 5 | 4 | 4 | 5 | **2.6** | | ~~14~~ | ~~Valkey extraction + legacy postgresql-ha retirement~~ **DONE 2026-08-15** | `railiance-platform` | 5 | 4 | 4 | 5 | **2.6** |
| 15 | Sweep remaining Gitea prose (~31 files each) | `railiance-forge`, `railiance-apps` | 3 | 2 | 2 | 3 | **2.3** | | 15 | Sweep remaining Gitea prose (~31 files each) | `railiance-forge`, `railiance-apps` | 3 | 2 | 2 | 3 | **2.3** |
| 16 | Declare the Q6 cost boundary with `resource-control`/`fin-hub` | `railiance-master` | 4 | 3 | 3 | 4 | **2.5** | | 16 | Declare the Q6 cost boundary with `resource-control`/`fin-hub` | `railiance-master` | 4 | 3 | 3 | 4 | **2.5** |
| 17 | Version S3 consumer service interfaces | `railiance-platform` | 6 | 3 | 5 | 6 | **2.3** | | ~~17~~ | ~~Version S3 consumer service interfaces~~ **DONE 2026-08-15** | `railiance-platform` | 6 | 3 | 5 | 6 | **2.3** |
| 18 | Resolve the C4 ecosystem-modelling overlap | `railiance-master` / `railiance-fabric` | 4 | 3 | 4 | 5 | **2.2** | | 18 | Resolve the C4 ecosystem-modelling overlap | `railiance-master` / `railiance-fabric` | 4 | 3 | 4 | 5 | **2.2** |
| 19 | S4 build-out: pipeline templates, SDKs, portal | `railiance-enablement` | 7 | 3 | 4 | 9 | **1.6** | | 19 | S4 build-out: pipeline templates, SDKs, portal | `railiance-enablement` | 7 | 3 | 4 | 9 | **1.6** |
@ -94,9 +94,10 @@ conformance checker already exists in `railiance-infra` and has simply not run
since 2026-03-09. **Slice 10a is now the highest-value item after the since 2026-03-09. **Slice 10a is now the highest-value item after the
ratifications** at WSJF 12.0. ratifications** at WSJF 12.0.
**Item 13 is blocked, not deprioritized.** Proving a restore needs the object **Item 13 is done, not blocked.** `RESOURCE-WP-0002` finished 2026-08-15.
storage decision (`9c21c0e0`), which is escalated and awaiting human approval on Barman is live on `platform-pg`; T05 recorded full restore and PITR on
commercial terms. Its WSJF understates it; treat the blocker as the real item. 2026-08-14; daily backups have completed since. Pointer:
`docs/evidence/RAILIANCE-WP-0016-item13-restore-2026-08-15.md`.
**Item 19 is last and that is deliberate.** S4 build-out is the widest gap in **Item 19 is last and that is deliberate.** S4 build-out is the widest gap in
the family, but it is large, and item 12 gives S4 a smaller first the family, but it is large, and item 12 gives S4 a smaller first
@ -270,7 +271,7 @@ it.
```task ```task
id: RAILIANCE-WP-0016-T05 id: RAILIANCE-WP-0016-T05
status: todo status: done
priority: medium priority: medium
state_hub_task_id: "a40faaf1-77db-43f5-a774-6ab3866d8e1d" state_hub_task_id: "a40faaf1-77db-43f5-a774-6ab3866d8e1d"
``` ```
@ -278,7 +279,15 @@ state_hub_task_id: "a40faaf1-77db-43f5-a774-6ab3866d8e1d"
Execute the S3-owned items in WSJF order — 13 (blocked on `9c21c0e0`), 14, 17 — Execute the S3-owned items in WSJF order — 13 (blocked on `9c21c0e0`), 14, 17 —
and keep this table current as items complete or their sizes become known. and keep this table current as items complete or their sizes become known.
**Done 2026-08-15.** Item 13 unblocked by `RESOURCE-WP-0002` finish: restore
already proven as T05 there; live `platform-pg-daily` backups completing.
Item 14: Bitnami postgresql-ha deploy path fail-closed (never live on
railiance01); Valkey has no S2 instance to extract and no consumer, so
deploy is gated. Item 17: `docs/s3-consumer-interfaces.md` v1.0.0.
## Outcome ## Outcome
Pending. T01-T03 delivered; routed to `railiance-master` for adoption T01T05 done. Routed to `railiance-master` (message `ac73b172`); master
(message `ac73b172`). T04 rescoping and T05 S3-owned execution remain. took items 6 and 8 as WP-0021 and declined the rest. S3-owned items 13,
14 and 17 executed 2026-08-15 after the object-store purchase landed.
Workplan finished. Remaining backlog rows belong to other repos.