Compare commits
No commits in common. "b15215d1911d6e2ff3f06d4b8f9ede666c640334" and "868313f3358b2e18c76aaceb0a6813db5476868f" have entirely different histories.
b15215d191
...
868313f335
4 changed files with 34 additions and 261 deletions
|
|
@ -20,7 +20,7 @@
|
||||||
| workplan | RAILIANCE-WP-0016 | finished | — | workplans/RAILIANCE-WP-0016-apps-pg-resource-evidence.md |
|
| workplan | RAILIANCE-WP-0016 | finished | — | workplans/RAILIANCE-WP-0016-apps-pg-resource-evidence.md |
|
||||||
| workplan | RAILIANCE-WP-0016 | finished | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md |
|
| workplan | RAILIANCE-WP-0016 | finished | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md |
|
||||||
| workplan | RAILIANCE-WP-0017 | finished | — | workplans/RAILIANCE-WP-0017-consumption-mode-enforcement.md |
|
| workplan | RAILIANCE-WP-0017 | finished | — | workplans/RAILIANCE-WP-0017-consumption-mode-enforcement.md |
|
||||||
| workplan | RPF-WP-0018 | active | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| workplan | RPF-WP-0018 | proposed | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RAILIANCE-WP-0005-T01 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.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-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 |
|
| task | RAILIANCE-WP-0005-T03 | done | — | workplans/RAILIANCE-WP-0005-credential-request-and-lease-broker.md |
|
||||||
|
|
@ -81,10 +81,10 @@
|
||||||
| task | RAILIANCE-WP-0016-T04 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md |
|
| task | RAILIANCE-WP-0016-T04 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md |
|
||||||
| task | RAILIANCE-WP-0016-T05 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md |
|
| task | RAILIANCE-WP-0016-T05 | done | — | workplans/RAILIANCE-WP-0016-architecture-cleanup-backlog.md |
|
||||||
| task | RAILIANCE-WP-0017-T01 | done | — | workplans/RAILIANCE-WP-0017-consumption-mode-enforcement.md |
|
| task | RAILIANCE-WP-0017-T01 | done | — | workplans/RAILIANCE-WP-0017-consumption-mode-enforcement.md |
|
||||||
| task | RPF-WP-0018-T01 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T01 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RPF-WP-0018-T02 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T02 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RPF-WP-0018-T03 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T03 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RPF-WP-0018-T04 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T04 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RPF-WP-0018-T05 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T05 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RPF-WP-0018-T06 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T06 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
| task | RPF-WP-0018-T07 | done | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
| task | RPF-WP-0018-T07 | todo | — | workplans/RPF-WP-0018-policy-surface-alignment.md |
|
||||||
|
|
|
||||||
|
|
@ -70,50 +70,15 @@ has an answer that is not archaeology. The **placement owner** decides
|
||||||
placement changes for that workload and is accountable for watching its
|
placement changes for that workload and is accountable for watching its
|
||||||
triggers. It is not the same role as the operator of the cluster.
|
triggers. It is not the same role as the operator of the cluster.
|
||||||
|
|
||||||
| Workload | Substrate | Provided level | Placement owner | Co-signer | §13 evidence |
|
| Workload | Substrate | Provided level | Placement owner | Co-signer |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| `audit-core` | `platform-pg` | P1 | `audit-core` | this repo | probes exist |
|
| `audit-core` | `platform-pg` | P1 | `audit-core` | this repo |
|
||||||
| `tenant-engine` | `platform-pg` | P1 | `tenant-engine` | this repo | probes exist |
|
| `tenant-engine` | `platform-pg` | P1 | `tenant-engine` | this repo |
|
||||||
| `user-engine` | `user-engine-pg` | P2 | `net-kingdom` | this repo | not assessed here |
|
| `user-engine` | `user-engine-pg` | P2 | `net-kingdom` | this repo |
|
||||||
| `target-revenue` | `target-revenue-pg` | P2 | `target-revenue` | this repo | not assessed here |
|
| `target-revenue` | `target-revenue-pg` | P2 | `target-revenue` | this repo |
|
||||||
| `forgejo` | `forgejo-db` | P2 | this repo | — | single consumer |
|
| `forgejo` | `forgejo-db` | P2 | this repo | — |
|
||||||
| `vergabe` | `apps-pg` | P1 | `vergabe-teilnahme` | this repo | **absent** |
|
| `vergabe` | `apps-pg` | P1 | `vergabe-teilnahme` | this repo |
|
||||||
| `coulomb_social` | `apps-pg` | P1 | `coulomb-social` | this repo | **absent** |
|
| `coulomb_social` | `apps-pg` | P1 | `coulomb-social` | this repo |
|
||||||
|
|
||||||
### 3.1 Two of these P1 levels are asserted without evidence
|
|
||||||
|
|
||||||
§13.1 claims a level only with its artifact present. The P1–P4 artifact is
|
|
||||||
*"provisioning declaration plus the platform's isolation probes"*.
|
|
||||||
|
|
||||||
`platform-pg` has them — `rapp-postgres` runs 15 adversarial probes against the
|
|
||||||
consumer boundary. **`apps-pg` has none.** `scripts/capture-apps-pg-evidence.py`
|
|
||||||
captures *capacity* evidence for `resource-control`; it makes no isolation
|
|
||||||
assertion. So the P1 levels recorded above for `vergabe` and `coulomb_social`
|
|
||||||
are, as of 2026-08-17, **provisioning declarations without probes** — stated
|
|
||||||
here rather than quietly carried, because a table of levels that mixes
|
|
||||||
evidenced and unevidenced entries without saying which is which is the failure
|
|
||||||
§13.1 exists to prevent.
|
|
||||||
|
|
||||||
Recorded as owed by this repo. Until the probes exist, those two rows should be
|
|
||||||
read as *intended* placement, not *verified* placement.
|
|
||||||
|
|
||||||
### 3.2 `apps-pg` cannot produce the noisy-neighbour artifact at all
|
|
||||||
|
|
||||||
Worth separating from the gap above, because it is not a matter of writing a
|
|
||||||
missing test. §13's P1–P2 noisy-neighbour artifact requires a per-consumer
|
|
||||||
usage baseline, a saturation run, and **evidence that the governance controls
|
|
||||||
bind — that the greedy consumer is held at its limits.**
|
|
||||||
|
|
||||||
`apps-pg` has no per-consumer governance controls. Its connection pool is not
|
|
||||||
partitioned, there is no per-consumer connection allowance, no statement
|
|
||||||
timeout and no resource limit on the pod. There is nothing that could be shown
|
|
||||||
to bind, so a run against it could only demonstrate that a saturating consumer
|
|
||||||
degrades its co-residents — which §13.4 explicitly rejects as an artifact that
|
|
||||||
"can only fail, or that passes by being run gently enough".
|
|
||||||
|
|
||||||
The honest sequence is therefore: **controls first, artifact second.** Writing
|
|
||||||
the probe before the limits exist would produce an overclaim wearing the
|
|
||||||
costume of evidence. Tracked as `RPF-WP-0019`.
|
|
||||||
|
|
||||||
**The consuming repo is the placement owner; this repo co-signs.** The
|
**The consuming repo is the placement owner; this repo co-signs.** The
|
||||||
consumer knows its latency requirement, its erasure horizon and its compliance
|
consumer knows its latency requirement, its erasure horizon and its compliance
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,6 @@ levels below are `0`. None of them is an admission of weakness, and §6 is
|
||||||
explicit that a declared low level is conformant while an unevidenced high
|
explicit that a declared low level is conformant while an unevidenced high
|
||||||
level is not.
|
level is not.
|
||||||
|
|
||||||
**Every level below carries what §13 requires of it.** §13.1: a level is
|
|
||||||
claimed only with its evidence artifact present. §13.1a: at or below the
|
|
||||||
"no control" rung, a declaration requires a **stated reason** instead, because
|
|
||||||
there is nothing to overclaim at the bottom of a ladder. Floor claims here
|
|
||||||
carry `reason:`; claims above the floor carry `evidence:`. A claim with
|
|
||||||
neither would be the overclaim §6 prohibits.
|
|
||||||
|
|
||||||
Where `target` equals `current`, that is a **settled position, not a stalled
|
|
||||||
trajectory** — §6 permits a low level to be permanent by design, on the
|
|
||||||
`flex-auth` precedent (`I1` forever, because verifying its own inputs would
|
|
||||||
make it the identity provider its scope refuses to be). Those lines carry
|
|
||||||
`permanent: true` so §12's guard does not nag them.
|
|
||||||
|
|
||||||
## Why this is a vector *set* and not a vector
|
## Why this is a vector *set* and not a vector
|
||||||
|
|
||||||
§5 asks a **service** for one level per axis. `railiance-platform` is an OAS
|
§5 asks a **service** for one level per axis. `railiance-platform` is an OAS
|
||||||
|
|
@ -97,65 +84,28 @@ tenancy:
|
||||||
tenancy:
|
tenancy:
|
||||||
service: openbao
|
service: openbao
|
||||||
role: credential-provider
|
role: credential-provider
|
||||||
current: { I: 0, A: 0, E: 0, P: 0, R: 0 }
|
current: { I: 0, A: 2, E: 0, P: 0, R: 0 }
|
||||||
target: { I: 0, A: 0, E: 0, P: 0, R: 1 }
|
target: { I: 0, A: 2, E: 0, P: 0, R: 1 }
|
||||||
permanent: [I, A, E]
|
|
||||||
service_class: latency-critical
|
service_class: latency-critical
|
||||||
reviewed: "2026-08-17"
|
reviewed: "2026-08-17"
|
||||||
reason:
|
|
||||||
I: "No tenant concept. OpenBao authenticates workloads via Kubernetes
|
|
||||||
auth; it never receives, parses or validates a NetKingdom tenant
|
|
||||||
identifier. Permanent by design — a secrets engine that resolved
|
|
||||||
tenant identity would be duplicating tenant-engine."
|
|
||||||
A: "No tenant context is carried, so there is nothing to bind. Permanent
|
|
||||||
by design, on the §6 flex-auth precedent."
|
|
||||||
E: "No tenant-keyed data. OpenBao holds workload secrets, not tenant
|
|
||||||
records."
|
|
||||||
P: "One instance, every consumer shares it. Single-node rail; §17
|
|
||||||
scaling demands apply."
|
|
||||||
R: "No retention position on audit device output or on KV version
|
|
||||||
history."
|
|
||||||
gap:
|
gap:
|
||||||
R: "R1 (platform default) is reachable cheaply and is not yet declared.
|
R: "No retention position on audit device output or on KV version history.
|
||||||
The only line here with a real trajectory."
|
R1 (platform default) is reachable cheaply and is not yet declared."
|
||||||
|
notes:
|
||||||
|
- "A2 is claimed on the consumer boundary, not a tenant boundary: policy
|
||||||
|
per workload path, bound once, centrally, in OpenBao's own policy
|
||||||
|
engine. It is NOT delegated to flex-auth, so A3 is not claimed and is
|
||||||
|
not currently a target — a PDP in the credential path would put
|
||||||
|
flex-auth on OpenBao's availability path and OpenBao on flex-auth's."
|
||||||
|
- "E is 0 on the TENANT axis and that number is misleading without this
|
||||||
|
sentence: consumer separation in OpenBao is structural — a workload
|
||||||
|
token's policy cannot address another workload's path at all, which is
|
||||||
|
E4-shaped machinery. It scores 0 because the axis measures the tenant
|
||||||
|
boundary and OpenBao has no tenant dimension. See the provider note."
|
||||||
|
- "P0 is accurate and deliberate: one instance, every consumer shares it.
|
||||||
|
Single-node rail; §17 scaling demands apply."
|
||||||
```
|
```
|
||||||
|
|
||||||
**Correction, 2026-08-17.** This vector first declared `A: 2`. That was
|
|
||||||
wrong twice over and both errors are worth recording rather than quietly
|
|
||||||
editing.
|
|
||||||
|
|
||||||
*It was internally incoherent.* `E: 0` was justified on the ground that
|
|
||||||
OpenBao has no tenant dimension. §4.2's `A2` reads "a single local
|
|
||||||
authorization boundary; **tenant context** bound once, centrally" — the same
|
|
||||||
dimension. A declaration cannot invoke the absence of tenant context to claim
|
|
||||||
the floor on one axis and ignore it to claim a rung on the next.
|
|
||||||
|
|
||||||
*It was unevidenced at the moment of claiming.* §13.1 requires the artifact to
|
|
||||||
be present when the level is claimed, and none was cited. §13.1a would not
|
|
||||||
have rescued it: the table defines an artifact from `A2` upward, so `A2` is
|
|
||||||
precisely the first rung where the exemption stops applying.
|
|
||||||
|
|
||||||
The irony is the point. This repo routed a finding about unevidenced claims
|
|
||||||
in the same week it made one.
|
|
||||||
|
|
||||||
**What the corrected zeros conceal, and why the provider note below exists.**
|
|
||||||
`A: 0` now reads as though OpenBao performs no authorization. It performs a
|
|
||||||
great deal, it is central, and it is mechanically evidenced —
|
|
||||||
`scripts/openbao-verify-token-grants.py` mints a scoped child token, asserts
|
|
||||||
it *can* sign with `ssh/sign/agt-role`, and asserts it *cannot* read policy
|
|
||||||
metadata, then revokes by accessor. That is exactly the shape §13 asks for at
|
|
||||||
`A2`: choke point identified, unbound request refused. It is pointed at the
|
|
||||||
**consumer** boundary, and none of the five axes has anywhere to put it.
|
|
||||||
|
|
||||||
That evidence is therefore cited under the provider statement rather than
|
|
||||||
against a consumer axis. Consumer separation in OpenBao is structural — a
|
|
||||||
workload token's policy cannot address another workload's path at all, which
|
|
||||||
is `E4`-shaped machinery — and the framework's honest application scores it
|
|
||||||
`0`.
|
|
||||||
|
|
||||||
`A3` is not a target: a PDP in the credential path would put `flex-auth` on
|
|
||||||
OpenBao's availability path and OpenBao on `flex-auth`'s.
|
|
||||||
|
|
||||||
### `platform-pg` — policy relationship only
|
### `platform-pg` — policy relationship only
|
||||||
|
|
||||||
Declared by `rapp-postgres`. This repo does not restate it. What this repo
|
Declared by `rapp-postgres`. This repo does not restate it. What this repo
|
||||||
|
|
@ -181,18 +131,6 @@ plus the provider statement is the accurate form. This is routed as a finding.
|
||||||
**The five ladders describe a consumer of storage. They do not describe a
|
**The five ladders describe a consumer of storage. They do not describe a
|
||||||
provider of it.**
|
provider of it.**
|
||||||
|
|
||||||
**Narrowed on re-reading, 2026-08-17.** An earlier version of this finding
|
|
||||||
claimed the framework had no way to say "this zero is structural, not weak".
|
|
||||||
That was wrong: §6 says exactly that, and §13.1a supplies the mechanism —
|
|
||||||
`target` equal to `current` with a stated reason is a settled position, on the
|
|
||||||
`flex-auth` `I1`-forever precedent. This declaration now uses it. Half of the
|
|
||||||
finding is withdrawn.
|
|
||||||
|
|
||||||
What survives is the other half, and it is not expressible: a provider cannot
|
|
||||||
state **what level it makes reachable for the workloads it holds**, nor record
|
|
||||||
a control that is real, mechanically evidenced, and simply not on any of the
|
|
||||||
five consumer axes.
|
|
||||||
|
|
||||||
Every service above scores at or near zero on I, A and E, and in each case for
|
Every service above scores at or near zero on I, A and E, and in each case for
|
||||||
the same structural reason rather than for a weakness: a storage or credential
|
the same structural reason rather than for a weakness: a storage or credential
|
||||||
platform has no tenant dimension of its own. It is exactly as strong or weak as
|
platform has no tenant dimension of its own. It is exactly as strong or weak as
|
||||||
|
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
---
|
|
||||||
id: RPF-WP-0019
|
|
||||||
type: workplan
|
|
||||||
title: "apps-pg: backup, per-consumer controls, and the isolation probes they make possible"
|
|
||||||
domain: financials
|
|
||||||
repo: railiance-platform
|
|
||||||
status: proposed
|
|
||||||
owner: codex
|
|
||||||
topic_slug: railiance
|
|
||||||
created: "2026-08-17"
|
|
||||||
updated: "2026-08-17"
|
|
||||||
related:
|
|
||||||
- RPF-WP-0018
|
|
||||||
origin: residual
|
|
||||||
origin_ref: RPF-WP-0018
|
|
||||||
---
|
|
||||||
|
|
||||||
# RPF-WP-0019 — apps-pg recoverability and per-consumer controls
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
|
|
||||||
Close the three defects `RPF-WP-0018` surfaced in `apps-pg` by writing its
|
|
||||||
quota disclosure. Documentation found them; only this workplan fixes them.
|
|
||||||
|
|
||||||
## Why this is separate from RPF-WP-0018
|
|
||||||
|
|
||||||
That workplan declared posture and policy. This one changes a live cluster.
|
|
||||||
Keeping them apart matters: a declaration workplan that quietly starts editing
|
|
||||||
production is how "we wrote it down" becomes indistinguishable from "we fixed
|
|
||||||
it". The declaration is published as-is, with the defects visible, and this is
|
|
||||||
the record of closing them.
|
|
||||||
|
|
||||||
## The three defects
|
|
||||||
|
|
||||||
**D1 — `apps-pg` has no backup.** No `barmanObjectStore`, no `retentionPolicy`,
|
|
||||||
nothing. This is not a short retention window; it is no recovery path at all,
|
|
||||||
on a cluster holding two S5 application databases. Its R level is `R0` and
|
|
||||||
`R0` here means unrecoverable, not merely un-erasable.
|
|
||||||
|
|
||||||
**D2 — no per-consumer controls.** The connection pool is unpartitioned, so
|
|
||||||
one consumer can exhaust the cluster while staying politely inside its own
|
|
||||||
expectations. No `statement_timeout`, no `idle_in_transaction_session_timeout`,
|
|
||||||
no CPU or memory limits — the pod is BestEffort QoS and is the first thing
|
|
||||||
evicted under node pressure.
|
|
||||||
|
|
||||||
**D3 — no isolation probes**, so the `P1` levels recorded for `vergabe` and
|
|
||||||
`coulomb_social` in `docs/placement-policy.md` §3.1 are provisioning
|
|
||||||
declarations without the §13 artifact.
|
|
||||||
|
|
||||||
## Sequencing, and why it is not the obvious one
|
|
||||||
|
|
||||||
**D1 first.** It is the only one whose failure is unrecoverable. A cluster
|
|
||||||
with no backup is one bad afternoon from data loss that no amount of isolation
|
|
||||||
evidence compensates for.
|
|
||||||
|
|
||||||
**D2 before D3, necessarily.** Tenancy Posture §13.4: an artifact must assert
|
|
||||||
something achievable. The noisy-neighbour artifact requires showing the
|
|
||||||
governance controls *bind*. With no controls there is nothing to bind, so a
|
|
||||||
probe written now could only demonstrate degradation — an artifact that "can
|
|
||||||
only fail, or that passes by being run gently enough". Writing the probe first
|
|
||||||
would produce an overclaim wearing the costume of evidence.
|
|
||||||
|
|
||||||
D1 also depends on a backup target, which is `resource-control`'s bucket and
|
|
||||||
the `platform-pg-backup-s3` credential lane — the same handoff
|
|
||||||
`make postgres-backup-deploy` waits on. Check whether that is now live before
|
|
||||||
assuming this is blocked.
|
|
||||||
|
|
||||||
## Tasks
|
|
||||||
|
|
||||||
```task
|
|
||||||
id: RPF-WP-0019-T01
|
|
||||||
status: todo
|
|
||||||
priority: high
|
|
||||||
```
|
|
||||||
**Establish a backup target for `apps-pg`.** Confirm the state of the
|
|
||||||
`resource-control` bucket and the `platform-pg-backup-s3` OpenBao Secret; if
|
|
||||||
live, configure `barmanObjectStore` and a `retentionPolicy` on the cluster. If
|
|
||||||
not live, record the dependency and say so — do not leave the absence
|
|
||||||
undocumented a second time.
|
|
||||||
|
|
||||||
```task
|
|
||||||
id: RPF-WP-0019-T02
|
|
||||||
status: todo
|
|
||||||
priority: high
|
|
||||||
```
|
|
||||||
**Declare and enforce per-consumer controls.** Per-consumer connection
|
|
||||||
allowance, `statement_timeout`, `idle_in_transaction_session_timeout`, and
|
|
||||||
pod resource requests/limits to lift `apps-pg` off BestEffort QoS. Publish
|
|
||||||
every value in `docs/s3-consumer-interfaces.md` before it takes effect —
|
|
||||||
§10.2 is a disclosure rule, and applying a timeout consumers learn about by
|
|
||||||
hitting it would breach the rule while implementing it.
|
|
||||||
|
|
||||||
```task
|
|
||||||
id: RPF-WP-0019-T03
|
|
||||||
status: todo
|
|
||||||
priority: medium
|
|
||||||
```
|
|
||||||
**Declare the ceiling and overflow target.** Owed under this repo's own
|
|
||||||
Rule P-4.1 before `apps-pg`'s third consumer; it is at two. Name the binding
|
|
||||||
resource per Rule P-4.2 — memory or connections — and a named overflow
|
|
||||||
substrate per P-4.3.
|
|
||||||
|
|
||||||
```task
|
|
||||||
id: RPF-WP-0019-T04
|
|
||||||
status: todo
|
|
||||||
priority: medium
|
|
||||||
```
|
|
||||||
**Isolation probes, after T02.** Consumer-boundary probes on the
|
|
||||||
`rapp-postgres` model, then the §13 noisy-neighbour artifact: per-consumer
|
|
||||||
baseline, saturation run, evidence the controls bind, degradation measured and
|
|
||||||
judged against each consumer's declared service class. Update
|
|
||||||
`docs/placement-policy.md` §3.1 and `docs/tenancy-posture.md` when the P1
|
|
||||||
claims become evidenced.
|
|
||||||
|
|
||||||
## Boundaries
|
|
||||||
|
|
||||||
- `apps-pg` only. `platform-pg`'s equivalents are `rapp-postgres`'s.
|
|
||||||
- No consumer is migrated. This changes the cluster, not who is on it.
|
|
||||||
- Values are published before they are enforced, never after.
|
|
||||||
|
|
||||||
## Risks
|
|
||||||
|
|
||||||
**Applying limits to a live cluster breaks a consumer that was relying on
|
|
||||||
their absence.** Most likely with `statement_timeout`. Mitigation is the
|
|
||||||
disclosure-first ordering in T02, which gives consumers a window to object.
|
|
||||||
|
|
||||||
**T01 stays blocked on a handoff outside this repo and the cluster keeps no
|
|
||||||
backup meanwhile.** Mitigation is that T01 requires the dependency be recorded
|
|
||||||
explicitly rather than left as a silent absence — which is exactly how D1
|
|
||||||
survived this long.
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue