RPF-WP-0018 closed: all seven tasks done. The provider-declaration finding was adopted upstream and its canonical form is the provider: block in tenancy.yaml; adaptive-pricing declined the standing co-signature and supplied typed tier minima instead, recorded in ADR-0002. Three corrections against our own output are recorded in the documents rather than edited away. RPF-WP-0019 T03 done (ceiling of three, memory binding, apps-pg-2 named as overflow, enforced by make apps-pg-verify-capacity). T01/T02 are repository-complete: backup target, retention, per-consumer connection limits, role timeouts and Burstable resources are declared in source and published in s3-consumer-interfaces 1.1.0 before rollout. They stay in progress because no live application, backup success or restore proof exists, and declared configuration is not a section 13 artifact. T04 waits on that window. apps-pg R reason corrected to say the target is declared-not-applied rather than absent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6.6 KiB
S3 consumer service interfaces
Work record: RAILIANCE-WP-0016 item 17; RPF-WP-0018 T04
Date: 2026-08-15, revised 2026-08-17
Contract version of this index: 1.1.0
Consumers bind to these contracts, not to Helm chart names or pod topology. Changing an engine behind a versioned interface does not bump the interface unless the consumer-visible fields change.
| Interface | Version | Who it is for | Authority |
|---|---|---|---|
| Shared application database | apps-pg.v1 |
S5 apps that need an isolated database on apps-pg |
docs/apps-pg.md |
| Isolated platform database | rapp-postgres.v1 |
Platform services that need a CNPG consumer on platform-pg |
rapp-postgres/declarations/rapp.yaml consumer_contract |
| Standing runtime secret | ccr-workload-kv.v1 |
Workloads that need a KV path via External Secrets | schemas/credential-change-request.schema.yaml |
| Short-lived lease | credential-grant.v1 |
Operators/agents and dynamic DB roles | credential-grants/catalog.yaml |
| Rapp credential bind | rapp-lane.v1 |
How a rapp names the two lanes above | docs/rapp-credential-lane-binding.md |
| Consumption-mode gate | consumption-mode.v1 |
New orders for a restricted financial entity | docs/consumption-mode-enforcement.md |
Compatibility rules
- A
vNdocument may add optional fields. Removing or renaming a required field isvN+1. - Values never appear in an interface document. Paths, grant ids, CCR ids, and role names are the contract.
make pg-deploy/ Bitnami DSNpostgresql-ha-pgpool.platform.svc.cluster.localis not an interface. That stack is retired.
Quota disclosure
Added in 1.1.0 — additive, so no consumer contract breaks.
Tenancy Posture §10.2: quotas are disclosed, not discovered. Every consumer is told at provisioning what the platform will refuse to do for it, and told again when that changes. A consumer learning its statement timeout by hitting it in production is a disclosure failure, not a consumer bug.
The obligation this places on S3 is a standing one: a change to any value in the tables below is announced to bound consumers before it takes effect. The values themselves are read from the cluster CR and are the package owner's to set — this index publishes them, it does not choose them.
Retention disclosure carries the additional §7 rule from
docs/placement-policy.md: on a shared cluster the effective erasure
horizon is the maximum declared across co-residents, not the value the
consumer requested. That number is disclosed, and it moves when a co-resident
changes.
apps-pg.v1
Consumer supplies: app name, namespace, database name, role name. Platform
provisions the role and CNPG Database, labels the namespace
railiance.io/postgres-client=apps-pg, and publishes a runtime Secret.
RW endpoint: apps-pg-rw.databases.svc.cluster.local:5432. Bootstrap
role apps_admin is not a consumer credential.
Quotas and limits — declared in helm/apps-pg-cluster.yaml and
helm/apps-pg-consumer-controls.sql, 2026-08-18. These values are published
before the corresponding live rollout:
| Property | Value | Note |
|---|---|---|
max_connections |
100 | Explicit aggregate cap. Forty connections remain outside the declared three-consumer ceiling for operator/CNPG overhead. |
| Per-consumer connections | 20 | CNPG managed.roles[].connectionLimit, for both current roles. |
statement_timeout |
15s | Per role; idempotent operator SQL because CNPG 1.28 has no managed-role settings field. |
idle_in_transaction_session_timeout |
15s | Per role, same enforcement path. |
| CPU / memory | 100m / 256Mi requests; 1 CPU / 1Gi limits | Burstable QoS; memory is expected to bind before connections if workload size grows. |
| Instances | 1 | No HA. Restart recovery only, per the single-node rail. |
| Storage | 10Gi | |
| Backup | 30d; daily 02:15 UTC + continuous WAL | S3 prefix s3://railiance-platform-pg-backup/apps-pg/; rollout is not evidence of recoverability until first backup and restore proof exist. |
| Effective erasure horizon | 30d, or the max across co-residents | Shared-cluster rule from placement policy §7. |
| Declared ceiling / overflow | 3 consumers / apps-pg-2 |
Memory is the binding safety constraint; provision the named overflow substrate before admitting a fourth. |
The manifests close the configuration gap, not the evidence gap. Until the
cluster change is applied and LastBackupSucceeded=True plus a scratch restore
are captured, recovery remains operationally unproven. Likewise the P1 noisy-
neighbour claim waits for the controlled probe window; source configuration is
not substituted for either artifact.
rapp-postgres.v1
Consumer is a consumers[].declaration. Boundary unit is
database-per-consumer. Credential type is
openbao-dynamic-database-credential via grant
rapp-postgres/<consumer>-<role>. Tenant identifiers are opaque.
Quotas and limits — authority is rapp-postgres's
helm/platform-pg-cluster.yaml; reproduced here for disclosure, 2026-08-17:
| Property | Value | Note |
|---|---|---|
max_connections |
100 | Aggregate, not per consumer. ~14 per consumer (12 runtime + 2 migration) puts the practical ceiling near 6. |
| Memory limit | 1Gi | Expected to bind before connections do — ~10MB per backend. Memory pressure OOM-kills; connection exhaustion errors cleanly. |
| CPU | 100m request / 1 limit | |
| Instances | 1 | No HA. |
| Storage | 20Gi | |
| Backup retention | 30d | Instance-wide, per rapp-postgres ADR-0002. |
| Effective erasure horizon | 30d, or the max across co-residents | A consumer needing shorter cannot have it at P1. See docs/placement-policy.md §7. |
| Statement timeout | consumer-set | tenant-engine sets 5s for its own path; not a platform default. |
| Declared ceiling / overflow target | 4 declarations / platform-pg-2 |
The isolation probe counts. rapp-postgres rejects a fifth declaration on one cell; ADR-0004 owns the number. |
Service classes currently co-resident on platform-pg: latency-critical
(tenant-engine) and batch (audit-core). Nothing prioritises between them
— community PostgreSQL has no resource governor. Reported per Tenancy Posture
§8.3.3.
ccr-workload-kv.v1 and credential-grant.v1
Unchanged semantics from docs/credential-change-approval.md and
docs/credential-broker.md. The version name exists so a rapp can cite
the lane without restating TTL, delivery, or revocation rules.
Not yet an interface
Valkey and in-cluster MinIO have capability blocks in SCOPE.md and no
live service. They do not receive a v1 until a consumer exists.