From ee87fa28ea84c56b7a9f6f825ffd4ae90eaaf075 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 30 Jul 2026 16:37:59 +0200 Subject: [PATCH] Add TREV-WP-0011: Railiance reef deployment workplan Deploys the Trust Service and Control Plane UI to Railiance infrastructure-as-code behind revenue.coulomb.social. T01 is a human decision gate on deployment pattern (own-repo k8s/railiance vs. railiance-apps chart, one process vs. two, CNPG database, OpenBao secrets, subdomain/TLS, credential bootstrap) before any manifest work starts. Deployment is explicitly scoped as infrastructure delivery, not a Phase go-live decision (that remains WP-0008-T05). Co-Authored-By: Claude Sonnet 5 --- README.md | 1 + .../TREV-WP-0011-railiance-reef-deployment.md | 163 ++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 workplans/TREV-WP-0011-railiance-reef-deployment.md diff --git a/README.md b/README.md index c1668ab..e99c5e5 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ The concept's §13 now defines a **Global Contingency Share Determination Rule** | [TREV-WP-0008](workplans/TREV-WP-0008-governance-and-pilot-rollout.md) | Governance formalization + pilot rollout — active; T01–T04 done. `info-tech-canon` dry-run onboarding routine exercised end-to-end 2026-07-29. **Org-wide TRSL license adoption executed 2026-07-30** across ~90 `coulomb`-org repos (`history/260730-TRSL-OrgWideLicenseRollout.md`) — a license-text adoption, not a Phase declaration. T05 (real Phase go-live gate) remains `todo` by design; no Phase exists yet for any repo | | [TREV-WP-0009](workplans/TREV-WP-0009-target-revenue-control-plane.md) | Target Revenue Control Plane — interactive UI for the `binky` tenant, incl. interactive Development Credit entry creation (`specs/TargetRevenueControlPlaneConcept.md`) — **finished**, all 4 tasks done. **T04 (interactive UI, `src/target_revenue/service/control_plane_app.py`) built on vendored `whynot-design` web components** rather than from scratch, per an explicit feasibility check | | [TREV-WP-0010](workplans/TREV-WP-0010-development-effort-calculator.md) | Development Effort Calculator — **finished**, all 3 tasks done. Applied to the three real pilot candidates (`history/260730-EffortCalculator-CandidateApplication.md`) — every calculator-derived Initial Target came out materially lower than the earlier hand-picked placeholders, two of three carrying explicit warnings recommending manual review | +| [TREV-WP-0011](workplans/TREV-WP-0011-railiance-reef-deployment.md) | Deploy Trust Service + Control Plane to the Railiance reef, fronted by `revenue.coulomb.social` — active; T01 (deployment-pattern decision, human gate) next. Deployment alone does not authorize a real Phase go-live — that remains WP-0008-T05 | Hub index: [`WORK-RECORDS.md`](WORK-RECORDS.md) · brief: [`.custodian-brief.md`](.custodian-brief.md) diff --git a/workplans/TREV-WP-0011-railiance-reef-deployment.md b/workplans/TREV-WP-0011-railiance-reef-deployment.md new file mode 100644 index 0000000..ad56782 --- /dev/null +++ b/workplans/TREV-WP-0011-railiance-reef-deployment.md @@ -0,0 +1,163 @@ +--- +id: TREV-WP-0011 +type: workplan +title: "Deploy Trust Service and Control Plane to the Railiance reef" +domain: infotech +repo: target-revenue +status: active +owner: claude +topic_slug: infotech +created: "2026-07-30" +updated: "2026-07-30" +--- + +# Deploy Trust Service and Control Plane to the Railiance reef + +Deploy the hosted Trust Service (`service/app.py`, WP-0006) and the +Control Plane interactive UI (`service/control_plane_app.py`, WP-0009-T04) +to Railiance infrastructure-as-code, on a rail hosted in `reef-railiance`'s +grouped home substrate, fronted by the subdomain `revenue.coulomb.social`. + +This is an infrastructure delivery workplan, not a governance one: it does +not authorize a real Phase to go live for any repo. That gate remains +`workplans/TREV-WP-0008-governance-and-pilot-rollout.md` T05, independent +of whether the software is reachable at a public URL. The Control Plane UI +itself already carries this disclaimer in its footer +(`service/control_plane_templates/base.html`) and will continue to once +deployed. + +**Reference deployment**: `railiance-vergabe-teilnahme` / +`railiance-apps/charts/vergabe-teilnahme` is the closest existing precedent +— a Django app, its own Postgres, a Helm chart living in `railiance-apps`, +an `Ingress` with `cert-manager.io/cluster-issuer: letsencrypt-prod`, and +runtime secrets via an `ExternalSecret` reading an OpenBao +`ClusterSecretStore`. `issue-core` is a second precedent using a different +pattern — its own repo carries `k8s/railiance` and an ArgoCD `Application` +points `repoURL` directly at that repo rather than at `railiance-apps`. T01 +below has to pick between these two patterns (or a third) rather than +assume one. + +```task +id: TREV-WP-0011-T01 +status: todo +priority: high +human_accept_required: true +``` + +**Decide the deployment pattern (human gate).** Concretely: + +- **Manifest home**: does `target-revenue` carry its own `k8s/railiance` + path (like `issue-core`) with an ArgoCD `Application` pointing straight + at this repo, or does the Helm chart/Ingress/manifests live in + `railiance-apps/charts/target-revenue` alongside `vergabe-teilnahme` + (this repo's TRSL licensing and its being a monetization-framework repo, + not an application repo, may argue for keeping deploy manifests + out-of-tree)? +- **Process topology**: `service/app.py` (Trust Service) and + `service/control_plane_app.py` (Control Plane UI) are two separate + FastAPI `app` objects today, sharing the same Postgres and the same + Ed25519 signing key. Deploy as two Deployments/Services behind one + Ingress with path-based routing, or mount one inside the other + (`app.mount("/control-plane", control_plane_app)`) into a single + process/image? The latter needs a small code change (WP-0009-T04's + Optional-Next-Step note flagged this as undecided); the former needs no + code change but two sets of secrets/probes. +- **Database**: a dedicated CNPG (`CloudNativePG`) `Cluster` for this + workload's Postgres (matching the `cnpg-option-a-*` manifests already + in `railiance-apps`), sized appropriately for a pilot-scale Trust + Service instance — not the shared state-hub Postgres, per this + project's own standing rule about never reusing that instance for + hosted-service data. +- **Secrets**: which values go through OpenBao + `ExternalSecret` + (`TRF_SIGNING_KEY_HEX`, `TRF_CONTROL_PLANE_SECRET_KEY`, + `TRF_DATABASE_URL`/the `trf_app` role password) versus which, if any, + are fine as plain Helm `values.yaml` — following the + `reuse-surface-runtime-externalsecret.yaml` pattern, one + `ClusterSecretStore` per workload namespace. +- **Subdomain and TLS**: confirm `revenue.coulomb.social` DNS is (or will + be) pointed at the Railiance ingress, and that `letsencrypt-prod` issuing + for a `coulomb.social` subdomain has no unresolved prerequisite (SAN + limits, existing wildcard, etc.) — check `railiance-infra`/ + `railiance-platform` docs rather than assuming parity with + `whywhynot.de`. +- **Founding credential bootstrap**: how the first `binky` admin + credential is seeded into the deployed database — an idempotent + migration-adjacent script, or a documented one-time manual `kubectl + exec`/`psql` step, consistent with how `railiance-apps`/`railiance-platform` + already handle comparable one-time bootstrap actions. + +Record the decision here (Result) before any manifest is written — this +gate exists because every later task in this workplan assumes a specific +answer to each bullet above. + +```task +id: TREV-WP-0011-T02 +status: todo +priority: high +``` + +**Containerize.** Add a `Dockerfile` (and, if T01 decided on two +processes, two images or one image with two entrypoints/commands) building +the `service` extras (`fastapi`, `uvicorn`, `jinja2`, `itsdangerous`, +`python-multipart`, `psycopg[binary]`, `psycopg-pool`) plus +`static/whynot-design` and `control_plane_templates/` as part of the image +— nothing in T04's implementation currently assumes local filesystem paths +outside the package, but this should be verified for a container context +(non-root user, read-only root filesystem where the app's own static/ +template files don't need write access). Push to +`forgejo.coulomb.social/coulomb/target-revenue` per the existing image +registry convention (`vergabe-teilnahme`'s `values.yaml` `image.repository` +pattern). + +```task +id: TREV-WP-0011-T03 +status: todo +priority: high +``` + +**Provision the database and secrets** per T01's decision: a CNPG +`Cluster`, the `0001`–`0006` migrations applied against it (as a Job, an +init step, or a documented manual run — decide which, consistent with +however `railiance-apps`'s other CNPG-backed workloads handle first-boot +migration), the `trf_app` role and its grants (already defined in the +migration files themselves), an `OpenBao` `ClusterSecretStore` + +`ExternalSecret` surfacing `TRF_SIGNING_KEY_HEX`, +`TRF_CONTROL_PLANE_SECRET_KEY`, and the `trf_app` password/DSN into the +workload's namespace. + +```task +id: TREV-WP-0011-T04 +status: todo +priority: high +``` + +**Helm chart, Ingress, and ArgoCD wiring.** Following T01's chosen home +(own-repo `k8s/railiance` vs. `railiance-apps/charts/target-revenue`): +Deployment(s)/Service(s)/Ingress for `revenue.coulomb.social` with +`cert-manager.io/cluster-issuer: letsencrypt-prod` and TLS, readiness/ +liveness probes against a real health path (neither `service/app.py` nor +`control_plane_app.py` currently exposes one — add a trivial `/healthz` to +each rather than probing an authenticated or Postgres-dependent route), +and an ArgoCD `Application` (`railiance-tenants` project, matching +`issue-core.application.yaml`'s shape) with automated sync. + +```task +id: TREV-WP-0011-T05 +status: todo +priority: medium +``` + +**Bootstrap and smoke-test the live deployment.** Seed the founding +`binky` admin credential per T01's decision, confirm +`https://revenue.coulomb.social/login` is reachable and TLS-valid, sign in, +register a throwaway test Phase (id clearly marked as a smoke test, not a +real candidate), append a Development Credit entry, confirm the audit log +and metrics reflect it, then decide whether to leave that smoke-test Phase +in place (clearly labeled) or remove it — Phase Manifests are append-only +by design (no delete path), so if a smoke test is unacceptable to leave +behind, use a disposable local/staging instance for this step, not the +production deployment, and only do a read-only login check against the +real one. Update `README.md`'s WP-0011 summary row and this workplan's +Result sections; add a short deployment note (URL, how to sign in, that no +Phase go-live is authorized by deployment alone) to `docs/` or `SCOPE.md` +as appropriate.