target-revenue/workplans/TREV-WP-0011-railiance-reef-deployment.md
tegwick 87ccf37b59 chore(consistency): sync workstream/task IDs for TREV-WP-0011
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 16:38:41 +02:00

169 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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"
state_hub_workstream_id: "f40fa906-9fbc-4445-9ebc-62ec46ac17b5"
---
# 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
state_hub_task_id: "8dffe5e1-6f2b-4020-ac07-a108a8fc2edc"
```
**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
state_hub_task_id: "d4b3dae4-eb2a-4bed-bc10-5ce90d972cec"
```
**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
state_hub_task_id: "06567eb5-d924-4100-9cd5-19478121c3c7"
```
**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
state_hub_task_id: "e6ecf3e5-3a9d-4f00-92b1-a05817b19013"
```
**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
state_hub_task_id: "37847415-19c4-43b5-8b0d-de7a4211bfdd"
```
**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.