Advance RPF-WP-0021 platform onboarding
This commit is contained in:
parent
8caba51801
commit
07ed6217b7
8 changed files with 284 additions and 5 deletions
|
|
@ -101,7 +101,7 @@
|
|||
| task | RPF-WP-0020-T03 | todo | — | workplans/RPF-WP-0020-ccr-schema-drift.md |
|
||||
| task | RPF-WP-0020-T04 | todo | — | workplans/RPF-WP-0020-ccr-schema-drift.md |
|
||||
| task | RPF-WP-0021-T01 | done | — | workplans/RPF-WP-0021-core-hub-platform-onboarding.md |
|
||||
| task | RPF-WP-0021-T02 | progress | — | workplans/RPF-WP-0021-core-hub-platform-onboarding.md |
|
||||
| task | RPF-WP-0021-T02 | done | — | workplans/RPF-WP-0021-core-hub-platform-onboarding.md |
|
||||
| task | RPF-WP-0021-T03 | progress | — | workplans/RPF-WP-0021-core-hub-platform-onboarding.md |
|
||||
| task | RPF-WP-0021-T04 | progress | — | workplans/RPF-WP-0021-core-hub-platform-onboarding.md |
|
||||
| task | RPF-WP-0021-T05 | wait | — | workplans/RPF-WP-0021-core-hub-platform-onboarding.md |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# RPF-WP-0021: three disjoint materialized Secrets for the Core Hub package.
|
||||
# Apply only after the static CCR is approved/seeded and the database roles
|
||||
# plus exact-scope renewable ESO token exist.
|
||||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: core-hub-api-token
|
||||
namespace: core-hub
|
||||
spec:
|
||||
refreshInterval: 5m
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: openbao-core-hub-runtime
|
||||
target:
|
||||
name: core-hub-api-token
|
||||
creationPolicy: Owner
|
||||
deletionPolicy: Retain
|
||||
data:
|
||||
- secretKey: CORE_HUB_API_TOKEN
|
||||
remoteRef:
|
||||
key: workloads/core-hub/runtime
|
||||
property: CORE_HUB_API_TOKEN
|
||||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: core-hub-runtime-database
|
||||
namespace: core-hub
|
||||
spec:
|
||||
refreshInterval: 5m
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: openbao-core-hub-database
|
||||
target:
|
||||
name: core-hub-runtime-database
|
||||
creationPolicy: Owner
|
||||
deletionPolicy: Retain
|
||||
# A single extract mints one lease and keeps its username/password paired.
|
||||
dataFrom:
|
||||
- extract:
|
||||
key: creds/core-hub-runtime
|
||||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: core-hub-migration-database
|
||||
namespace: core-hub
|
||||
spec:
|
||||
refreshInterval: 5m
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: openbao-core-hub-database
|
||||
target:
|
||||
name: core-hub-migration-database
|
||||
creationPolicy: Owner
|
||||
deletionPolicy: Retain
|
||||
dataFrom:
|
||||
- extract:
|
||||
key: creds/core-hub-migration
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# Railiance01-local database-engine store for RPF-WP-0021. The renewable
|
||||
# orphan parent token is streamed into the referenced Secret by an attended
|
||||
# platform operation; its value never enters this repository.
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ClusterSecretStore
|
||||
metadata:
|
||||
name: openbao-core-hub-database
|
||||
labels:
|
||||
app.kubernetes.io/part-of: railiance-gitops
|
||||
railiance-platform/component: external-secrets
|
||||
app.kubernetes.io/name: core-hub
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: http://openbao.openbao.svc:8200
|
||||
path: database
|
||||
version: v1
|
||||
auth:
|
||||
tokenSecretRef:
|
||||
name: openbao-core-hub-eso-token
|
||||
namespace: external-secrets
|
||||
key: token
|
||||
conditions:
|
||||
- namespaces:
|
||||
- core-hub
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# Core Hub PostgreSQL capacity admission — 2026-08-20
|
||||
|
||||
Workplan: `RPF-WP-0021-T02`
|
||||
|
||||
Target: railiance01 `databases/platform-pg`
|
||||
|
||||
Mode: bounded live occupancy probe; no application data or credential value
|
||||
was read or recorded.
|
||||
|
||||
## Question
|
||||
|
||||
Can Core Hub occupy the fourth and final declaration slot on `platform-pg`
|
||||
without raising the current 1Gi pod limit or exceeding the explicit
|
||||
100-connection aggregate?
|
||||
|
||||
The four declarations are `audit-core`, `tenant-engine`, `core-hub`, and the
|
||||
counted isolation probe. Each workload declaration reserves 12 runtime plus
|
||||
two migration connections; the probe's smaller allowance is deliberately
|
||||
overstated here, making 56 a conservative declared-pool occupancy.
|
||||
|
||||
## Method
|
||||
|
||||
A temporary namespace labeled as a `platform-pg` client received the existing
|
||||
bootstrap Secret by namespace-to-namespace projection without printing its
|
||||
values. A separate client pod opened 56 sessions in four named groups of 14.
|
||||
This kept client-process memory outside the database pod. The run then repeated
|
||||
the same 56-session occupancy with 13 idle and one bounded active sort query
|
||||
per group. The namespace and copied Secret were deleted after the run.
|
||||
|
||||
The active query materialized and sorted 100,000 generated integers, then held
|
||||
the backend briefly for observation. It did not access an application table.
|
||||
|
||||
## Observations
|
||||
|
||||
| Signal | Before | Declared occupancy / observed peak |
|
||||
| --- | ---: | ---: |
|
||||
| Probe sessions | 0 | 56 (14 in each named group) |
|
||||
| All PostgreSQL sessions | 9 | 65 |
|
||||
| Active / idle sessions | 1 / 2 | 5 / 54 in the mixed run |
|
||||
| PostgreSQL pod memory | 89Mi | **174Mi maximum observed** |
|
||||
| PostgreSQL pod CPU | 7m | 82m during connection startup |
|
||||
| Node memory | 6,210Mi / 16Gi | 6,342Mi / 16Gi (39%) |
|
||||
| Node CPU | 470m | 2,002m transient startup peak |
|
||||
|
||||
The 85Mi database-pod increase across 56 opened backends is approximately
|
||||
1.52Mi per connection at declared pool occupancy. That replaces ADR-0004's
|
||||
unmeasured 10Mi literature estimate for idle/backend occupancy on this live
|
||||
instance; it does not claim every query operator is limited to that figure.
|
||||
|
||||
The earlier quiet preflight observed 362Mi. Conservatively adding the entire
|
||||
measured connection delta to that higher historical sample gives 447Mi, under
|
||||
44% of the 1Gi limit. The four bounded active queries did not exceed the
|
||||
174Mi maximum already observed during connection startup.
|
||||
|
||||
## Decision
|
||||
|
||||
Core Hub is accepted as the fourth declaration on `platform-pg` without a
|
||||
memory-limit increase. It reaches the declared ceiling and does not authorize
|
||||
a fifth declaration. The renderer must continue to reject any additional
|
||||
consumer on this cell; the named overflow remains `platform-pg-2`.
|
||||
|
||||
This is capacity admission evidence, not a latency or workload-peak guarantee.
|
||||
Core Hub is latency-critical beside batch `audit-core`, and community
|
||||
PostgreSQL provides no service-class priority. The private shadow run must
|
||||
therefore capture application health, query latency, pod memory, and backend
|
||||
counts; material regression is a placement trigger, not a reason to reinterpret
|
||||
this probe as stronger evidence.
|
||||
42
docs/evidence/core-hub-shadow-preflight-2026-08-20.md
Normal file
42
docs/evidence/core-hub-shadow-preflight-2026-08-20.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Core Hub private-shadow preflight — 2026-08-20
|
||||
|
||||
This records non-secret source/target metadata gathered for
|
||||
`RPF-WP-0021-T05`. It is preparation only: no source data was dumped or
|
||||
restored because the governed credential projections under T04 are not yet
|
||||
live.
|
||||
|
||||
## Target admission
|
||||
|
||||
At `2026-08-20T21:31:13Z` on railiance01:
|
||||
|
||||
- namespace `core-hub` was Active and carried
|
||||
`railiance.io/postgres-client=platform-pg` plus the package identity labels;
|
||||
- CNPG `Database/core-hub` reported `status.applied=true` against
|
||||
`platform-pg`, with reclaim policy `retain` and owner `core_hub_owner`;
|
||||
- the `core_hub` database existed but intentionally contained no application
|
||||
tables before the rehearsal restore; and
|
||||
- the KV store, database store and three ExternalSecret manifests all passed
|
||||
Kubernetes server-side dry-run after namespace creation.
|
||||
|
||||
## Source snapshot inventory
|
||||
|
||||
A read-only query ran through the existing `coulombcore` SSH route against
|
||||
`apps-pg/core_hub`. No Secret or connection value was read. The live source
|
||||
writer remained enabled, so these counts are a rehearsal baseline and must be
|
||||
captured again with the eventual consistent dump.
|
||||
|
||||
| Object | Rows |
|
||||
| --- | ---: |
|
||||
| `public.alembic_version` | 1 |
|
||||
| `public.api_consumers` | 3 |
|
||||
| `public.api_keys` | 10 |
|
||||
| `public.hub_capability_manifests` | 2 |
|
||||
| `public.hubs` | 2 |
|
||||
| `public.interaction_events` | 3 |
|
||||
| `public.migration_runs` | 2 |
|
||||
| `public.widgets` | 16 |
|
||||
|
||||
The source Alembic revision was `20260627_0002`. No user-defined sequence was
|
||||
reported. The table set and counts are small enough for a bounded logical-copy
|
||||
rehearsal, but the restore remains gated on T04 so that migration and runtime
|
||||
checks use the intended distinct dynamic leases rather than a bootstrap login.
|
||||
11
openbao/policies/external-secrets-core-hub-database.hcl
Normal file
11
openbao/policies/external-secrets-core-hub-database.hcl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Exact-scope parent policy for the renewable ESO token that projects Core Hub
|
||||
# PostgreSQL leases. Static API-token custody uses the separate
|
||||
# workload-kv-read-core-hub-runtime policy and Kubernetes-auth store.
|
||||
|
||||
path "database/creds/core-hub-runtime" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
path "database/creds/core-hub-migration" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
|
@ -104,6 +104,48 @@ class CredentialChangeTests(unittest.TestCase):
|
|||
self.assertEqual(store["spec"]["provider"]["vault"]["path"], "platform")
|
||||
self.assertEqual(store["spec"]["conditions"][0]["namespaces"], ["core-hub"])
|
||||
|
||||
database_policy = (
|
||||
REPO_DIR / "openbao/policies/external-secrets-core-hub-database.hcl"
|
||||
).read_text()
|
||||
self.assertIn('path "database/creds/core-hub-runtime"', database_policy)
|
||||
self.assertIn('path "database/creds/core-hub-migration"', database_policy)
|
||||
self.assertNotIn("platform/data/", database_policy)
|
||||
|
||||
database_store = credential_change.load_yaml(
|
||||
REPO_DIR
|
||||
/ "argocd/platform-addons/openbao-secretstore/openbao-core-hub-database.clustersecretstore.yaml"
|
||||
)
|
||||
self.assertEqual(database_store["spec"]["provider"]["vault"]["path"], "database")
|
||||
self.assertEqual(database_store["spec"]["provider"]["vault"]["version"], "v1")
|
||||
self.assertEqual(database_store["spec"]["conditions"][0]["namespaces"], ["core-hub"])
|
||||
|
||||
with (
|
||||
REPO_DIR
|
||||
/ "argocd/platform-addons/openbao-secretstore/core-hub.externalsecrets.yaml"
|
||||
).open() as stream:
|
||||
external_secrets = list(credential_change.yaml.safe_load_all(stream))
|
||||
self.assertEqual(
|
||||
{item["metadata"]["name"] for item in external_secrets},
|
||||
{
|
||||
"core-hub-api-token",
|
||||
"core-hub-runtime-database",
|
||||
"core-hub-migration-database",
|
||||
},
|
||||
)
|
||||
for item in external_secrets:
|
||||
self.assertEqual(item["metadata"]["namespace"], "core-hub")
|
||||
self.assertEqual(item["spec"]["refreshInterval"], "5m")
|
||||
runtime = next(
|
||||
item for item in external_secrets
|
||||
if item["metadata"]["name"] == "core-hub-runtime-database"
|
||||
)
|
||||
migration = next(
|
||||
item for item in external_secrets
|
||||
if item["metadata"]["name"] == "core-hub-migration-database"
|
||||
)
|
||||
self.assertEqual(runtime["spec"]["dataFrom"][0]["extract"]["key"], "creds/core-hub-runtime")
|
||||
self.assertEqual(migration["spec"]["dataFrom"][0]["extract"]["key"], "creds/core-hub-migration")
|
||||
|
||||
def test_target_rapp_rejects_non_slug(self) -> None:
|
||||
path = self.unapproved_ccr()
|
||||
data = credential_change.load_yaml(path)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ State Hub; workplan UUID assignment remains with the production registrar.
|
|||
|
||||
```task
|
||||
id: RPF-WP-0021-T02
|
||||
status: progress
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
|
|
@ -125,8 +125,7 @@ baseline. The untracked `consumers/issue-core.yaml` is not a real consumer —
|
|||
`ISSUE-WP-0007` explicitly removed Postgres from that package — and must not
|
||||
silently consume a slot.
|
||||
|
||||
Live apply, database role creation, namespace labeling, and OpenBao database
|
||||
role configuration remain attended operations after declaration review.
|
||||
OpenBao database role configuration remains an attended operation under T04.
|
||||
|
||||
Read-only preflight 2026-08-20: `platform-pg-1` used 9m CPU and 362Mi memory
|
||||
against a 1Gi limit, with only `audit_core` and operator sessions present;
|
||||
|
|
@ -134,6 +133,23 @@ against a 1Gi limit, with only `audit_core` and operator sessions present;
|
|||
does not satisfy ADR-0004's representative multi-consumer peak measurement.
|
||||
Evidence: `docs/evidence/core-hub-postgres-capacity-preflight-2026-08-20.md`.
|
||||
|
||||
Capacity admission completed 2026-08-20. A bounded live probe opened 56
|
||||
sessions in four declaration groups and repeated the occupancy with one active
|
||||
bounded sort per group. `platform-pg` peaked at 174Mi/1Gi; the 85Mi increase is
|
||||
about 1.52Mi per opened backend. Even adding that delta to the earlier 362Mi
|
||||
sample yields 447Mi, under 44% of the limit. Core Hub is accepted as the fourth
|
||||
and final declaration without raising the pod limit. Evidence:
|
||||
`docs/evidence/core-hub-postgres-capacity-admission-2026-08-20.md`.
|
||||
|
||||
Completed 2026-08-20. `rapp-postgres` commit `4f316cc` accepts and publishes
|
||||
the Core Hub declaration as the fourth `platform-pg` consumer. All 31 package
|
||||
tests and consumer rendering passed; the railiance01 server-side dry-run
|
||||
accepted the generated resource. The idempotent package provisioner then
|
||||
created `core_hub`, its `core_hub` schema, distinct NOLOGIN owner/migration/
|
||||
runtime roles and bounded role settings. CNPG `Database/core-hub` reports
|
||||
`status.applied=true`, targets `platform-pg`, retains the database on resource
|
||||
deletion, and names `core_hub_owner` as owner.
|
||||
|
||||
## T03 — Correct the runtime credential delivery contract
|
||||
|
||||
```task
|
||||
|
|
@ -207,6 +223,16 @@ high-risk boundary to deny direct data reads on the new path. Database-engine
|
|||
policy/store manifests wait for the accepted Postgres declaration and the T03
|
||||
consumer correction.
|
||||
|
||||
Progress 2026-08-20 after T02 admission: added an exact two-path database ESO
|
||||
policy, a namespace-limited `openbao-core-hub-database` store, and three
|
||||
disjoint ExternalSecrets. Runtime and migration each use one `dataFrom.extract`
|
||||
so a username/password pair comes from one lease; both refresh every five
|
||||
minutes. The database store and all projections passed railiance01 server-side
|
||||
dry-run. The package namespace is live with the reviewed `platform-pg` client
|
||||
label. Live role/store activation correctly stopped because the current
|
||||
OpenBao session receives 403 and CCR-2026-0013 is still proposed; no authority
|
||||
or placeholder Secret was improvised.
|
||||
|
||||
## T05 — Support the private shadow restore and verification
|
||||
|
||||
```task
|
||||
|
|
@ -224,11 +250,17 @@ the private endpoint.
|
|||
This task ends with repeatable shadow evidence. It does not flip
|
||||
`hub.coulomb.social`, freeze production writes, or remove CoulombCore.
|
||||
|
||||
Preflight 2026-08-20: the source has Alembic revision `20260627_0002`, eight
|
||||
public tables and 39 total rows. The admitted target intentionally has no
|
||||
application tables before restore. No dump or restore was attempted ahead of
|
||||
the T04 credential gate. Evidence:
|
||||
`docs/evidence/core-hub-shadow-preflight-2026-08-20.md`.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [x] Private Forgejo repo exists, validated commit `4403c9b` is preserved,
|
||||
and the registered workplan prefix is consistent.
|
||||
- [ ] Core Hub is an accepted, capacity-reviewed `rapp-postgres` consumer.
|
||||
- [x] Core Hub is an accepted, capacity-reviewed `rapp-postgres` consumer.
|
||||
- [ ] Static API-token and dynamic database credentials have distinct,
|
||||
least-privilege delivery paths.
|
||||
- [ ] Database credential rotation cannot leave a running pod using an expired
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue