117 lines
6.6 KiB
Markdown
117 lines
6.6 KiB
Markdown
# 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 `vN` document may add optional fields. Removing or renaming a
|
|
required field is `vN+1`.
|
|
- Values never appear in an interface document. Paths, grant ids, CCR
|
|
ids, and role names are the contract.
|
|
- `make pg-deploy` / Bitnami DSN
|
|
`postgresql-ha-pgpool.platform.svc.cluster.local` is **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. |
|
|
| Database boundary | own database only | `CONNECT` and `TEMPORARY` are revoked from `PUBLIC`; each consumer role receives them only on its own database. |
|
|
| 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/platform-pg/apps-pg/`; backup and restore proof captured 2026-08-20. |
|
|
| 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 configuration and evidence gaps closed on 2026-08-20:
|
|
`LastBackupSucceeded=True`, a 56-second scratch restore, and a 14/14 live
|
|
boundary/noisy-neighbour run. Source configuration is not substituted for
|
|
those artifacts; see `docs/evidence/RPF-WP-0019-*.md`.
|
|
|
|
## `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.
|