Close RPF-WP-0025, WP-0043 T01/T05, WP-0045 T05; retire bao.coulomb.social defaults
- WP-0025-T03 done: public listener retracted 2026-09-15; bao.coulomb.social is retired, tunnel is the operator path; DNS withdrawal handed to S1. - WP-0043-T01 done: ArgoCD Core reconciles railiance01 at main (evidence). - WP-0043-T05 done: direct-apply gap inventory and founder proposal. - WP-0045-T05 cancelled (no rollback needed); T06 preconditions recorded. - Operator scripts default BAO_ADDR to the openbao-ui-railiance01 tunnel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 150322@bnt-lap001 Assistant-Session: 16a7b788-374e-4915-a1df-fc87ffd9a5e4
This commit is contained in:
parent
8a7ebce5c6
commit
b666301487
11 changed files with 133 additions and 14 deletions
40
docs/direct-apply-gap-inventory.md
Normal file
40
docs/direct-apply-gap-inventory.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Direct-apply gap inventory (RPF-WP-0043-T05)
|
||||
|
||||
Inventory date: 2026-09-22. Source: `Makefile` on `main` at `8a7ebce`.
|
||||
Nothing here changes a target's behaviour.
|
||||
|
||||
## Declaration
|
||||
|
||||
Under the Kubernetes change gate (`the-custodian/docs/kubernetes-change-gate-decision.md`),
|
||||
a platform object without a readiness state defaults to the production tier,
|
||||
and the production row is `CONSTRUCT` through git and ArgoCD. The targets
|
||||
below change railiance01 directly (`kubectl apply`, `helm upgrade`, or the
|
||||
OpenBao API). Their evidence is `target-audited` only. **They do not conform
|
||||
to the production row.** Until the founder rules on each group, every run is
|
||||
`ADMINISTER @ realm:kubernetes/railiance01`, `activation=APPROVED`, and is
|
||||
recorded as a production-tier change.
|
||||
|
||||
ArgoCD Core has run on railiance01 since 2026-09-21. The evidence is
|
||||
`docs/evidence/2026-09-22-argocd-railiance01-status.json`. A reconciled lane
|
||||
therefore exists for Kubernetes objects. It does not exist for OpenBao API
|
||||
state.
|
||||
|
||||
## Inventory and proposal
|
||||
|
||||
| Group | Targets | What they change | Proposal |
|
||||
| --- | --- | --- | --- |
|
||||
| A. CNPG clusters, backups, NetworkPolicies | `db-deploy`, `forgejo-db-deploy`, `apps-pg-deploy`, `apps-pg-backup-deploy`, `apps-pg-overflow-deploy`, `net-kingdom-pg-inter-hub-networkpolicy-deploy` | `helm/*.yaml` via `kubectl apply` | **Move to a reconciled lane.** Adopt one Application per database cell, one at a time, as in RPF-WP-0044. The first sync is manual with prune off, and CNPG `Cluster` needs an AppProject whitelist entry. `db-deploy` (gitea-db) may be retirement, not adoption: check first whether gitea-db still exists. |
|
||||
| B. ClusterSecretStores | the `openbao-secretstore` Application (already adopted) plus stores patched by hand during recoveries (RPF-WP-0037, RPF-WP-0045) | `ClusterSecretStore` specs | **Move to reconciled.** Store auth blocks belong in `argocd/`-tracked manifests. A hand patch now counts as drift to reconcile back into git. |
|
||||
| C. OpenBao package | `openbao-deploy`, `openbao-overlay-apply`, `openbao-public-listener-retract`, `openbao-public-listener-rollback` | Helm release and gateway overlay in `openbao` | **Move to reconciled, with rapp-openbao.** The package belongs to `rapp-openbao`, so its Application should come from there. The listener retract and rollback stay direct as attended break-glass under `APPROVED`. |
|
||||
| D. OpenBao configuration | `openbao-configure-initial`, `-ssh`, `-external-secrets-*`, `-workload-kv-lanes`, `-credential-change-appliers`, `-token-grants`, `credential-change-applier-apply` | policies, roles and mounts over the OpenBao API | **Stay direct under `APPROVED`.** ArgoCD cannot reconcile API state. The controls are compare-before-write scripts, attended login and per-run evidence. A declarative reconciler is a separate decision. |
|
||||
| E. ArgoCD bootstrap | `argocd-bootstrap-deploy`, `argocd-repo-apply` | AppProjects, root Application, repository Secret | **`argocd-bootstrap-deploy`: never against railiance01.** It renders the old root with automated prune and self-heal. Use `argocd/railiance01/bootstrap/` (RPF-WP-0044). Retire or guard the target when coulombcore is retired (RPF-WP-0044-T08). `argocd-repo-apply` stays direct under `APPROVED` because it carries SOPS-encrypted credentials. |
|
||||
| F. Not Kubernetes | `forgejo-package-prune`, `backup`, `forgejo-backup` | Forgejo API, backup uploads | Outside the Kubernetes gate. Stays direct. |
|
||||
| Fail-closed | `pg-deploy`, `valkey-deploy` | nothing (refuse) | No action. |
|
||||
|
||||
Read-only targets (`*-status`, `*-logs`, `*-dry-run`, `*-verify*`,
|
||||
`assurance-*`) change nothing and are not in scope.
|
||||
|
||||
## Founder decision requested
|
||||
|
||||
Accept or amend the per-group proposal. Adopting groups A to C is later work.
|
||||
It is not started by this inventory.
|
||||
30
docs/evidence/2026-09-22-argocd-railiance01-status.json
Normal file
30
docs/evidence/2026-09-22-argocd-railiance01-status.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"schema": "railiance-platform.argocd-railiance01-status.v1",
|
||||
"task": "RPF-WP-0043-T01",
|
||||
"observed_at": "2026-09-22T20:40:00Z",
|
||||
"method": "read-only `ssh railiance01 'kubectl get ...'`; nothing applied, patched or synced",
|
||||
"node": {
|
||||
"name": "239.62.205.92.host.secureserver.net",
|
||||
"internal_ip": "92.205.62.239",
|
||||
"roles": "control-plane,etcd",
|
||||
"kubelet": "v1.35.1+k3s1",
|
||||
"ready": true
|
||||
},
|
||||
"argocd_namespace_workloads": {
|
||||
"deployment/argocd-applicationset-controller": "1/1",
|
||||
"deployment/argocd-redis": "1/1",
|
||||
"deployment/argocd-repo-server": "1/1",
|
||||
"statefulset/argocd-application-controller": "1/1",
|
||||
"age": "30h (Argo CD Core v3.5.3, phase A install 2026-09-21)"
|
||||
},
|
||||
"applications": {
|
||||
"railiance-apps-root": {"sync": "Synced", "health": "Healthy", "revision": "8a7ebce5c600026cb9eb818e27538e5e8990faa8"},
|
||||
"openbao-secretstore": {"sync": "Synced", "health": "Healthy", "revision": "d2dbc19c254247652c49fda8721c80d53bca206a"},
|
||||
"target-revenue": {"sync": "Synced", "health": "Healthy", "revision": "f1109d54eeda9f187daa215cf1c7163610d35d0a"}
|
||||
},
|
||||
"forgejo_main_revision": "8a7ebce5c600026cb9eb818e27538e5e8990faa8",
|
||||
"root_revision_matches_main": true,
|
||||
"supersedes": "the-custodian message cc3acf71 (2026-09-21, 'ArgoCD is not on railiance01'): that check predates the phase A install and ran before the workstation kubeconfig fix recorded in the-custodian/docs/agent-environment-orientation.md section 1",
|
||||
"conclusion": "ArgoCD is installed on railiance01 and reconciles the root application at Forgejo main. The production row of the change gate has a working path; RPF-WP-0043 continues.",
|
||||
"credential_values_emitted": false
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ def main():
|
|||
helper = Path.home()/'.vault-token'
|
||||
private(helper, 0o600)
|
||||
token = helper.read_text().strip()
|
||||
req = Request('https://bao.coulomb.social/v1/platform/data/workloads/secrets-engine/approval-client?version=1',headers={'X-Vault-Token':token})
|
||||
req = Request(os.environ.get('BAO_ADDR','http://127.0.0.1:18200')+'/v1/platform/data/workloads/secrets-engine/approval-client?version=1',headers={'X-Vault-Token':token})
|
||||
with transport(req,timeout=20) as response:
|
||||
data = response.read(65537)
|
||||
if len(data)>65536:
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class Operator:
|
|||
if not token:
|
||||
raise ProcedureError("OpenBao token file is empty")
|
||||
self.remote = remote
|
||||
self.bao_env = dict(os.environ, BAO_ADDR="https://bao.coulomb.social", BAO_TOKEN=token)
|
||||
self.bao_env = dict(os.environ, BAO_ADDR=os.environ.get("BAO_ADDR", "http://127.0.0.1:18200"), BAO_TOKEN=token)
|
||||
|
||||
def bao(self, args: list[str], *, label: str, input_text: str | None = None, allow_missing: bool = False) -> subprocess.CompletedProcess[str]:
|
||||
return safe_run(["bao", *args], label=label, env=self.bao_env, input_text=input_text, allow_missing=allow_missing)
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class Operator:
|
|||
if not token:
|
||||
raise ProcedureError("OpenBao token file is empty")
|
||||
self.remote = remote
|
||||
self.bao_env = dict(os.environ, BAO_ADDR="https://bao.coulomb.social", BAO_TOKEN=token)
|
||||
self.bao_env = dict(os.environ, BAO_ADDR=os.environ.get("BAO_ADDR", "http://127.0.0.1:18200"), BAO_TOKEN=token)
|
||||
|
||||
def bao(self, args: list[str], *, label: str, input_text: str | None = None, allow_missing: bool = False) -> subprocess.CompletedProcess[str]:
|
||||
return safe_run(["bao", *args], label=label, env=self.bao_env, input_text=input_text, allow_missing=allow_missing)
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class Operator:
|
|||
self.remote = contract["authority"]["remote"]
|
||||
self.bao_env = dict(
|
||||
os.environ,
|
||||
BAO_ADDR=os.environ.get("BAO_ADDR", "https://bao.coulomb.social"),
|
||||
BAO_ADDR=os.environ.get("BAO_ADDR", "http://127.0.0.1:18200"),
|
||||
BAO_TOKEN=token,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@ for mount in $MOUNTS; do
|
|||
done
|
||||
|
||||
printf '\nVerify unauthenticated UI mount listing:\n'
|
||||
curl -fsS "https://bao.coulomb.social/v1/sys/internal/ui/mounts" | python3 -m json.tool
|
||||
curl -fsS "${BAO_ADDR:-http://127.0.0.1:18200}/v1/sys/internal/ui/mounts" | python3 -m json.tool
|
||||
|
|
@ -13,7 +13,7 @@ import urllib.request
|
|||
from typing import Any
|
||||
|
||||
|
||||
DEFAULT_ADDR = "https://bao.coulomb.social"
|
||||
DEFAULT_ADDR = "http://127.0.0.1:18200" # openbao-ui-railiance01 tunnel
|
||||
DATA_PATH = "platform/data/workloads/issue-core/issue-core/issue-core-runtime"
|
||||
METADATA_PATH = (
|
||||
"platform/metadata/workloads/issue-core/issue-core/issue-core-runtime"
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ type: workplan
|
|||
title: "Retract public OpenBao listener behind operator-only access"
|
||||
domain: financials
|
||||
repo: railiance-platform
|
||||
status: active
|
||||
status: finished
|
||||
flavor: implementation
|
||||
owner: codex
|
||||
topic_slug: railiance
|
||||
created: "2026-08-23"
|
||||
updated: "2026-09-15"
|
||||
updated: "2026-09-22"
|
||||
related:
|
||||
- RMASTER-WP-0020-T09
|
||||
- RAPP-OPENBAO-WP-0002
|
||||
|
|
@ -55,7 +55,7 @@ It deletes only the Ingress and provides an exact rollback path.
|
|||
|
||||
```task
|
||||
id: RPF-WP-0025-T03
|
||||
status: progress
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "8850d742-7cd7-5a1b-ba52-4dbc4bdeba7e"
|
||||
```
|
||||
|
|
@ -152,3 +152,21 @@ HTTP 404. Evidence:
|
|||
Remaining T03: public DNS withdrawal with railiance-infra and non-secret
|
||||
acceptance to Railiance Master. Rollback phrase remains available during the
|
||||
observation window.
|
||||
|
||||
## Closure — 2026-09-22
|
||||
|
||||
T03 done. The operator-only cutover is complete on the platform side:
|
||||
loopback MFA login passed, and the public Ingress was retracted on 2026-09-15
|
||||
(`docs/evidence/2026-09-15-openbao-public-listener-retract.json`). **Intended
|
||||
end state: `bao.coulomb.social` is retired.** The named tunnel
|
||||
`openbao-ui-railiance01` (`http://127.0.0.1:18200`) is the only operator path,
|
||||
and workloads use `openbao.openbao.svc:8200`. No certificate or route will be
|
||||
restored for the public name. The dangling DNS record (it still resolves to
|
||||
92.205.62.239, where Traefik serves its default certificate and returns 404)
|
||||
was handed to its S1 publisher, railiance-infra, for withdrawal. Non-secret
|
||||
acceptance went to railiance-master for RMASTER-WP-0020-T09, and the end
|
||||
state was sent to user-engine (hub message `e8ccbc2f`). Operator scripts no
|
||||
longer default `BAO_ADDR` to the public name. The one exception is
|
||||
`scripts/audit-core-database-lease-recovery.py`: the WP-0024 owner-review
|
||||
contract pins its digest, so it keeps the old literal until the next owner
|
||||
review.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ flavor: planning
|
|||
owner: railiance-platform
|
||||
topic_slug: railiance
|
||||
created: "2026-09-21"
|
||||
updated: "2026-09-21"
|
||||
updated: "2026-09-22"
|
||||
due: "2026-12-21"
|
||||
related: [RPF-WP-0022]
|
||||
state_hub_workstream_id: "ec41a4bd-df18-5b07-9b63-ccb80d9f001c"
|
||||
|
|
@ -43,7 +43,7 @@ stays untouched and unwrapped while this lane moves.
|
|||
|
||||
```task
|
||||
id: RPF-WP-0043-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "d6a7a480-6251-504a-aa5f-ab9c04fe1e79"
|
||||
```
|
||||
|
|
@ -205,7 +205,7 @@ Rollback:
|
|||
|
||||
```task
|
||||
id: RPF-WP-0043-T05
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "91431560-79d4-5352-a6b5-f12850315dd2"
|
||||
```
|
||||
|
|
@ -218,3 +218,16 @@ evidence only. Inventory those targets, declare the gap as not conforming,
|
|||
and propose to the founder which ones move to a reconciled lane and which
|
||||
stay direct under `APPROVED`. Do not change a target's behaviour as part of
|
||||
the inventory.
|
||||
|
||||
## Execution record — 2026-09-22
|
||||
|
||||
- **T01 done.** Read-only check over `ssh railiance01`. Node 92.205.62.239 is
|
||||
Ready. Argo CD Core runs 1/1 in `argocd`. `railiance-apps-root` is
|
||||
Synced/Healthy at `8a7ebce`, which equals Forgejo `main`. `openbao-secretstore`
|
||||
and `target-revenue` are Synced/Healthy. Evidence:
|
||||
`docs/evidence/2026-09-22-argocd-railiance01-status.json`. This supersedes
|
||||
the custodian's 2026-09-21 "not installed" reading, which predates the phase A
|
||||
install and the kubeconfig fix. The plan continues.
|
||||
- **T05 done.** Gap declared and inventoried in
|
||||
`docs/direct-apply-gap-inventory.md`, with a per-group proposal for the
|
||||
founder. No target changed.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ flavor: implementation
|
|||
owner: railiance-platform
|
||||
topic_slug: railiance
|
||||
created: "2026-09-21"
|
||||
updated: "2026-09-21"
|
||||
updated: "2026-09-22"
|
||||
related: [RPF-WP-0037]
|
||||
state_hub_workstream_id: "0edc6426-9cc8-5bbe-88ea-c27d9862d96e"
|
||||
---
|
||||
|
|
@ -200,7 +200,7 @@ other than the header. The earlier 37-count had 5 failing; expect 0.
|
|||
|
||||
```task
|
||||
id: RPF-WP-0045-T05
|
||||
status: wait
|
||||
status: cancel
|
||||
priority: medium
|
||||
state_hub_task_id: "6bccc229-3428-588a-9488-3fd5d5a07e92"
|
||||
```
|
||||
|
|
@ -277,3 +277,21 @@ and `email-connect/deploy/k8s/railiance/openbao-eso-token-apply.sh`, and update
|
|||
- **T03 done.** SAs created; both stores switched to Kubernetes auth.
|
||||
- **T04 done.** Both stores `Ready=True` ("store validated"); forced refresh; all five ExternalSecrets `SecretSynced` at 17:39Z; **37/37 ExternalSecrets ready cluster-wide.**
|
||||
- **T06** (delete the two dead token Secrets) is due after 24 h of clean syncs, i.e. not before 2026-09-22T17:40Z.
|
||||
|
||||
## Execution record — 2026-09-22
|
||||
|
||||
- **T05 cancelled.** Rollback is not needed. At 20:40Z both stores are
|
||||
`Valid`/Ready on Kubernetes auth, and all five ExternalSecrets synced at
|
||||
20:39Z, more than 24 h after the T04 switch.
|
||||
- **T06 preconditions met, deletion not run.** The no-reference check returned
|
||||
no output: no store references either token Secret. The deletion was blocked
|
||||
by the session's permission guard, so it waits for the founder to run it:
|
||||
`ssh railiance01 'kubectl -n external-secrets delete secret openbao-activity-core-eso-token openbao-email-connect-eso-token'`.
|
||||
The bootstrap-target retirements in activity-core and email-connect were
|
||||
handed to their owners.
|
||||
- **New incident, outside this plan:** `openbao-core-hub-database` and
|
||||
`openbao-tenant-engine-database` (both static-token) have failed
|
||||
`lookup-self` with 403 since about 2026-09-21T22:00Z. Six ExternalSecrets are
|
||||
failing (four in core-hub, two in tenant-engine). This is the failure mode
|
||||
named in the Risks section above. It needs the same Kubernetes-auth
|
||||
migration, with an attended admin login.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue