--- id: RPF-WP-0047 type: workplan title: "bao.coulomb.social: static not-publicly-available page with a trusted certificate" domain: financials repo: railiance-platform status: finished owner: railiance-platform topic_slug: railiance created: "2026-09-24" updated: "2026-09-24" related: [RPF-WP-0025, RMASTER-WP-0020] state_hub_workstream_id: "6ab44339-66d3-522b-9d34-fc9ff6f20d1b" --- ## Why The founder decided on 2026-09-23 (relayed by user-engine, hub message `7d8982c2`) that OpenBao stays non-public. The RMASTER-WP-0020-T09 / RPF-WP-0025-T03 retraction stands. But the published name must not present a self-signed Traefik certificate and a bare 404. **Requested end state:** a static page saying the resource is not publicly available, over a trusted certificate. It names no internal host, port, tunnel or version, offers no login form or redirect, and proxies nothing to OpenBao. This reverses the DNS withdrawal handed to railiance-infra on 2026-09-22; a hold was sent (`a4bca724`). A static notice is not an exposure grant under ADR-0008. ## T01 Build the page and manifests ```task id: RPF-WP-0047-T01 status: done priority: high state_hub_task_id: "caa019c6-dfdb-5f17-b860-67e1feaebd51" ``` `argocd/platform-addons/bao-notice/` holds: - A namespace `bao-notice` with a NetworkPolicy: ingress only from Traefik (kube-system) on 8080, no egress at all, so there is no path to OpenBao. - Nginx `nginxinc/nginx-unprivileged` pinned by digest (already running in the cluster), running non-root with a read-only root filesystem and all capabilities dropped. - `/` returns 200 with the notice. Every other path returns 404 with the same notice, so a probe of `/v1/sys/health` is never a false 200. - `server_tokens off`, CSP `default-src 'none'`, `noindex`, `no-store`. - An Ingress on `websecure` with `letsencrypt-prod`, and an HTTP→HTTPS redirect at priority 1, so ACME HTTP-01 still wins. Verified on 2026-09-24: - Local container probe: `/` 200, `/v1/sys/health` and `/ui/` 404 with the notice, `Server: nginx` with no version. - Server-side dry run on railiance01: all eight objects valid. - No existing Ingress claims the host. - The `railiance-tenants` AppProject already whitelists every kind. ## T02 Adopt through ArgoCD (live, founder go-ahead) ```task id: RPF-WP-0047-T02 status: done priority: high state_hub_task_id: "3af7f95f-4689-547e-90dc-529e65c7b9e2" ``` The Application is `argocd/railiance01/applications/bao-notice.application.yaml`, pinned to `960ed09`. Sync the root by hand to create it, then sync `bao-notice` by hand. cert-manager issues `bao-notice-tls` over HTTP-01. ## T03 Verify from outside and close the loop ```task id: RPF-WP-0047-T03 status: done priority: high state_hub_task_id: "26bf3291-e74e-51dd-89e5-c38169d471b0" ``` From the workstation: `curl -sv https://bao.coulomb.social/` must show a trusted chain with no `-k`, HTTP 200 and the notice. `https://bao.coulomb.social/v1/sys/health` must return 404, and `http://bao.coulomb.social/` must redirect to https. Record the evidence, then tell user-engine, railiance-infra (keep the A record) and railiance-master (T09 posture unchanged). ## Rollback Delete the `bao-notice` Application with prune. That restores today's state: the Traefik default certificate and a 404. ## Execution record — 2026-09-23/24 (founder go-ahead) - **T02 done.** The root and `bao-notice` were hand-synced; the app is Synced/Healthy. - **First issuance returned 502 on the HTTP-01 challenge.** The isolation NetworkPolicy also covered cert-manager's solver pod (port 8089). Fixed by a narrow `bao-notice-acme-solver` policy, Traefik to solver pods on 8089 only, and `bao-notice-tls` was issued. - **HSTS added** (`max-age=31536000`, this host only). The single-replica pod swap caused a few seconds of 502 through Traefik. - **T03 done.** Checked from the workstation with no `-k`: - Certificate `CN=bao.coulomb.social` from Let's Encrypt, verify ok, expires 2026-12-22 (cert-manager renews). - `/` returns 200 with the notice; `/v1/sys/health` and `/ui/` return 404; `http://` returns a 301 to https. - HSTS and CSP `default-src 'none'` are set, and the `Server` header carries no version. - No internal identifiers, form or redirect in the body. - Evidence: `docs/evidence/2026-09-24-bao-coulomb-social-notice.json`.