diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index a8b3f68..b2ac774 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -16,6 +16,7 @@ | workplan | RAILIANCE-WP-0012 | finished | — | workplans/RAILIANCE-WP-0012-rapp-openbao-extraction-boundary.md | | workplan | RAILIANCE-WP-0013 | finished | — | workplans/RAILIANCE-WP-0013-forgejo-admin-pat-openbao-cutover.md | | workplan | RAILIANCE-WP-0014 | finished | — | workplans/RAILIANCE-WP-0014-credential-change-suite-stabilization.md | +| workplan | RAILIANCE-WP-0015 | active | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | | task | RAILIANCE-WP-0005-T01 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md | | task | RAILIANCE-WP-0005-T02 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md | | task | RAILIANCE-WP-0005-T03 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md | @@ -61,3 +62,9 @@ | task | RAILIANCE-WP-0014-T02 | done | — | workplans/RAILIANCE-WP-0014-credential-change-suite-stabilization.md | | task | RAILIANCE-WP-0014-T03 | done | — | workplans/RAILIANCE-WP-0014-credential-change-suite-stabilization.md | | task | RAILIANCE-WP-0014-T04 | done | — | workplans/RAILIANCE-WP-0014-credential-change-suite-stabilization.md | +| task | RAILIANCE-WP-0015-T01 | todo | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | +| task | RAILIANCE-WP-0015-T02 | todo | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | +| task | RAILIANCE-WP-0015-T03 | todo | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | +| task | RAILIANCE-WP-0015-T04 | todo | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | +| task | RAILIANCE-WP-0015-T05 | todo | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | +| task | RAILIANCE-WP-0015-T06 | todo | — | workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md | diff --git a/docs/rapp-platform-service-pattern.md b/docs/rapp-platform-service-pattern.md new file mode 100644 index 0000000..bce0138 --- /dev/null +++ b/docs/rapp-platform-service-pattern.md @@ -0,0 +1,149 @@ +# The S3 Platform-Service Rapp Pattern + +Date: 2026-08-11 +Owner: `railiance-platform` (S3) +Work record: `RAILIANCE-WP-0015-T01` + +## Purpose + +This is the reference shape for packaging a **platform service** as a `rapp-*` +managed workload package. It generalizes the two boundaries S3 has already +drawn — `docs/rapp-openbao-boundary.md` and `docs/rapp-postgres-boundary.md` — +so the third and fourth platform rapps do not each re-derive the split from +scratch. + +It is deliberately *not* a general rapp standard. The four-axis repo family +model belongs to `railiance-master/docs/repository-axes.md`, and the +`rapp.yaml` schema and canon promotion are in flight there and in +`the-custodian`. This document covers only the half S3 owns: what a +platform-service rapp looks like, and where the line falls between the package +and the platform. + +## The rule + +> A rapp owns how its workload is **packaged, deployed, verified, rolled back +> and recovered**. S3 retains everything that is **true across workloads**: +> policy, credential custody, lane approval, and the shared substrate the +> package assumes. + +Both existing platform rapps already state this in their own words. From +`rapp-openbao-boundary.md`: the package may own how OpenBao is packaged, +deployed, verified and skinned, and must not become the home for platform-admin +policy, workload KV lane policy, delegated metadata authority, or credential +grants. From `rapp-postgres-boundary.md`: the package owns manifests, consumer +declarations, provisioning surface, isolation tests and recovery, while S3 +retains the operator, storage policy, backup target and the credential-broker +grant catalog. + +## The ownership test + +When an asset's home is unclear, ask in this order. The first answer that +applies decides it. + +1. **Would this asset survive replacing the workload with a different product?** + If yes, it is S3's. Credential lane approval survives swapping OpenBao for + another secrets engine; an OpenBao Helm values file does not. +2. **Does any other workload depend on this asset?** If yes, it is S3's. A + `workload-kv-read-*` policy is consumed by the workload it names but governed + by a lane model shared by all of them. +3. **Does it encode who may approve, not how to apply?** Approval authority is + S3's; application mechanics are the package's. This is the line that keeps a + rapp from becoming a shadow S3 repo — the failure mode named explicitly in + `railiance-master/docs/rapp-first-wave-candidates.md`. +4. **Otherwise it is the package's.** Charts, values, overlays, deploy and + verify scripts, workload-specific smoke and recovery procedure, and the + Makefile targets that drive them. + +### Applied + +| Asset class | Home | Test | +| --- | --- | --- | +| Helm values, chart pins, overlays, ingress/middleware manifests | rapp | 4 | +| Deploy / dry-run / status / verify / rollback commands | rapp | 4 | +| Workload-specific smoke and recovery procedure | rapp | 4 | +| Consumer declarations and provisioning surface | rapp | 4 | +| Operator and read-only policy surface | S3 | 1 | +| Credential lane approval, CCRs, grant catalog | S3 | 3 | +| Cross-workload secret delivery (ESO, KV lanes) | S3 | 2 | +| Backup target procurement and its credentials | S3 | 1 | +| Storage class, monitoring substrate, cluster access | S3 | 1 | + +## Reference `rapp.yaml` for a platform service + +Pending the normative schema from `railiance-master`, a platform-service rapp +should carry at least the following. Fields marked † are the consistency fields +currently present in `rail.yaml` and `rapp-qonto` but missing from both platform +rapps; `RAILIANCE-WP-0015-T02` adds them once the schema settles. + +```yaml +kind: managed-workload-package +repo_family: rapp +rapp_id: rapp- +repo: rapp- +ownership_repo: railiance-platform # the S3 home retaining governance +contract_version: 1.0.0 # † +readiness_state: verified # † +data_classification: # † +criticality: # † +workload_identity: + name: # the workload, never the repo name + package_type: helm-managed-platform-service + chart: + chart_version: + app_version: +primary_rail: rail-kubernetes +supported_rails: [rail-kubernetes] +runtime_dependencies: [...] # what must exist for this to run +rollout_contract: {...} +smoke_contract: {...} +rollback_contract: {...} +source_documents: [...] +``` + +Two conventions worth stating because they have already drifted: + +- `workload_identity.name` is the **workload**, not the repo. `openbao`, not + `rapp-openbao`. +- `ownership_repo` is the repo that retains governance after extraction — for + platform services that is `railiance-platform`, and it is not the same thing + as the repo the package was carved out of. + +## Grouped rapps + +Operator decision of 2026-08-11: rapp granularity is **grouped by bounded +context** — one rapp per cohesive group of services that deploys, versions and +rolls back together, rather than one rapp per deployable. + +For a grouped rapp: + +- members **must** be declared explicitly; an undeclared bundle is not a rapp, + it is a drawer +- grouping is legitimate **only** where members share rollout and rollback fate. + If one member can be rolled back without the others, it is a separate rapp +- the group's smoke contract must cover the group, not just its largest member + +`rapp-postgres` is already a grouped package in this sense — it owns the CNPG +cluster manifests plus per-consumer declarations, and declares its consumers +explicitly in `consumers:`. That is the shape to copy. + +## Credential lanes + +A platform-service rapp never owns credential custody. It declares what it +needs; S3 vends it through the existing broker. The binding between a rapp's +`runtime_dependencies` / `secret_references` and the S3 grant catalog and CCR +lanes is specified in `RAILIANCE-WP-0015-T06` — until that lands, follow +`docs/credential-broker.md` and `docs/credential-change-approval.md` directly +and do not create a package-local lane. + +The existing rule holds without exception: the package never commits +credentials, and a workload receives a short-lived lease through the platform +broker rather than a package-managed secret. + +## When a platform service earns a rapp + +Not every S3 service needs one. A platform service is ready for extraction when +it has a stable workload identity, a package surface already visible in Git, an +explicit dependency and secret story, and described deploy/verify/recover +behavior — the criteria from `rapp-first-wave-candidates.md`. A service that +fails these is not blocked from being operated; it simply stays owned by S3 +until its packaging identity stops moving. diff --git a/workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md b/workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md index 3bf08fb..afa3d13 100644 --- a/workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md +++ b/workplans/RAILIANCE-WP-0015-platform-rapp-consistency.md @@ -15,6 +15,7 @@ related_repos: - reef-railiance - rapp-openbao - rapp-postgres +state_hub_workstream_id: "a14fd4d3-2e30-474f-aeea-af560c622394" --- # RAILIANCE-WP-0015 - Platform rapp consistency and deployment-management contract @@ -104,8 +105,9 @@ It must not: ```task id: RAILIANCE-WP-0015-T01 -status: todo +status: done priority: high +state_hub_task_id: "53f6a28f-ee10-4695-ab7f-6781b3d35c76" ``` Publish the S3 platform-service rapp pattern as `docs/rapp-platform-service-pattern.md`: @@ -119,6 +121,7 @@ inventing a third boundary vocabulary. id: RAILIANCE-WP-0015-T02 status: todo priority: high +state_hub_task_id: "eada3a6f-9f4e-47bc-bfe5-2ec585f5d312" ``` Bring `rapp-openbao/declarations/rapp.yaml` and @@ -132,8 +135,9 @@ not converge on different answers. ```task id: RAILIANCE-WP-0015-T03 -status: todo +status: done priority: medium +state_hub_task_id: "493d0ab0-595c-4a14-b3d6-8c396bd7747b" ``` Correct the reef binding registry: propose to `reef-railiance` that @@ -144,8 +148,9 @@ since a hand-listed registry is what went stale. ```task id: RAILIANCE-WP-0015-T04 -status: todo +status: done priority: high +state_hub_task_id: "30cb0cb2-2ce2-4d27-8d43-c29dc32904a8" ``` Route the schema and validator proposal to `railiance-master`: a @@ -156,8 +161,9 @@ was actually built and the grouped-context wave-2 inventory. ```task id: RAILIANCE-WP-0015-T05 -status: todo +status: done priority: medium +state_hub_task_id: "ca661530-5ebd-422b-854d-7b6986f0b3fe" ``` Route the canon promotion proposal to `the-custodian`: a @@ -170,6 +176,7 @@ the open C-31 failures on multi-segment `RAPP-*-WP-` ids. id: RAILIANCE-WP-0015-T06 status: todo priority: medium +state_hub_task_id: "9ea10522-47a9-4cce-b0d8-cb6f9c7813b8" ``` Define how a rapp binds to its credential lane: the relationship between @@ -181,4 +188,8 @@ the existing lane, it does not build a parallel one. ## Outcome -Pending. +Session of 2026-08-11: T01 published the S3 platform-service pattern; T03, T04 +and T05 routed their proposals to the owning repos (reef-railiance +f0f44ce0, railiance-master 04c776c4, the-custodian cc64764a). T02 is +deliberately held until railiance-master settles the schema, so the platform +rapps and the schema do not converge on different answers. T06 is open.