---
id: RPF-WP-0018
type: workplan
title: "Align S3 with the estate policy surface (Tenancy Posture + policy-nexus)"
domain: financials
repo: railiance-platform
status: finished
owner: codex
topic_slug: railiance
created: "2026-08-17"
updated: "2026-08-18"
related:
  - POLICY-NEXUS-WP-0001
  - TEN-WP-0009
  - RAPP-POSTGRES-WP-0002
origin: routed
origin_ref: "net-kingdom/canon/standards/tenancy-posture_v0.1.md §19.2, §20"
state_hub_workstream_id: "4fcb6026-2630-59a3-b5de-15f54efcf59d"
---

# RPF-WP-0018 — policy surface alignment

## Goal

Answer the two policy asks that landed on this repo, accept what fits,
push back on what does not, and leave behind artifacts that are checkable
rather than a promise to be good.

Done means: this repo has published a posture declaration, has accepted or
declined placement ownership in writing, has told its consumers their
quotas, and has answered `policy-nexus` on the one assignment in
`POLICY-NEXUS-WP-0001` that contradicts the OAS stack.

## Where the policy comes from

Two documents, from two owners, arriving in the same week.

1. **`net-kingdom/canon/standards/tenancy-posture_v0.1.md`** (draft-5,
   proposed, reviewed by nobody). Routed by `rapp-postgres` on 2026-08-17
   (message `d9da7d11`), foreshadowed by `tenant-engine` on 2026-08-16
   (message `31aed179`). It asks this repo, **co-signed with
   `adaptive-pricing`**, to own database placement policy — §8.2, §19.2 —
   and to publish its own posture vector as the ratification test (§20.2).
2. **`policy-nexus/workplans/POLICY-NEXUS-WP-0001`** (proposed). It
   assigns this repo the *substrate* for `policy.coulomb.social` — DNS,
   TLS, ingress, hosting — and includes this repo in the ~68-ADR corpus it
   intends to publish from `docs/adr/*.md`.

Both are drafts. Neither is ratified. Accepting them now is cheaper than
accepting them later, because both are still willing to change.

## What actually applies to us, and what does not

**Applies, and fits.** The placement ladder (P0–P4) describes our estate
accurately: `apps-pg` is a P1 shared cluster, `user-engine-pg` and
`target-revenue-pg` are P2. The §10.2 quota-disclosure obligation lands on
a document we already maintain, `docs/s3-consumer-interfaces.md`. The §9.1
ban on static long-lived database credentials is already how the credential
broker works. Nothing in the ladder requires us to move a single workload.

**Applies, but we cannot satisfy it yet.** §8.1 says placement triggers
MUST be *monitored*, not merely recorded. This repo has no monitoring
plane. `SCOPE.md` states we emit to `railiance-telemetry` "once the
evidence plane exists — seeded 2026-08-11, not yet implemented". Claiming
monitoring we do not have is the exact overclaim §6 prohibits, so T03
records each trigger with a named monitor or an explicit `unmonitored`
marker, and the marker is the honest answer until telemetry lands.

**Does not fit, and the policy should change.** Five findings, T07.

## Findings against the policy (routed 2026-08-17, T07)

**F1 — `POLICY-NEXUS-WP-0001` assigns S3 a concern S3 does not own.**
It states "`railiance-platform` owns the substrate — DNS, TLS, ingress,
hosting". Per `SCOPE.md`, DNS and OS-level concerns are S1
`railiance-infra`, and Kubernetes ingress is S2 `railiance-cluster`;
S3 owns shared *platform services*. Accepting the assignment as written
would re-import the boundary violation that `RAIL-PL-WP-0001` and ADR-003
exist to prevent.

*Recommend:* split T04 of that workplan. Ingress and TLS to S2, DNS to S1
or the reef boundary, and the genuinely S3 parts — an object-storage bucket
for the static output if it wants one, plus any credential lane — stay
here. This repo can co-sign the deployment without owning the substrate.
Adjacent and unresolved: `railiance-master` asked us on 2026-08-15
(`ba477968`) to confirm `bao.coulomb.social` does not publish on
reef-railiance. A second public name on the same rail should go through
whatever answers that question, not around it.

**F2 — this repo's decisions are structurally unpublishable.**
`policy-nexus` publishes canon and ADRs only, globbing `docs/adr/*.md`.
This repo has **no `docs/adr/` directory and no ADRs**. Its load-bearing
decisions live either in `docs/` as prose without frontmatter (24 files,
no status, revision, review date or owner — the fields T02/T05 of the
publication workplan require) or in the State Hub via `record_decision()`,
which is a read model and is not a publication source. The estate's
standing rule is that local files are the source of truth; for decisions,
this repo does not follow it.

*Recommend:* not a mass conversion. T05 here promotes the small set that
is genuinely decisional — the boundary rules, the credential-lane model,
the consumption-mode gate — into ADR form with the frontmatter
`policy-nexus` needs. The runbooks stay prose and stay unpublished, which
is what that workplan's scope rule already wants.

**F3 — §19.8 asks this repo for a number that lives in another repo.**
Cell sizing wants `platform-pg`'s declared maximum size. That spec —
`instances: 1`, `max_connections: 100`, `1Gi` — is `rapp-postgres`'s
cluster CR, not ours; `RAILIANCE-WP-0012` and `RAILIANCE-WP-0015`
deliberately moved the deployable surface to the rapp repos while this repo
kept custody and policy. The split is right and the question is misrouted
by one hop.

*Recommend:* accept §8.2 with the scope stated — **this repo owns the rule,
`rapp-postgres` owns the number**. We declare *that* a ceiling must be
published and what happens at it; they declare what it is. Same shape for
§19.9's retention floor and ceiling. `rapp-postgres`'s own analysis already
concedes the point: memory probably binds before connections do, at roughly
10MB per backend, and that is an observation only the package owner can
make.

**F4 — the posture vector is service-shaped; this repo is a layer.**
§5 asks a *service* to state one level per axis. `railiance-platform` is an
OAS layer that holds custody of several services with different postures.
One vector for the repo would be an average, which is exactly the
inaccuracy §6 prohibits. §20.2 invites this: "if a repo cannot express
itself in these five ladders, the ladders are wrong and this document
changes, not the repo."

*Recommend:* a layer repo publishes a **vector set** — one per service it
has custody of — plus a statement of which it owns versus operates. T01
does that and routes the finding back to `net-kingdom` as the framework's
first real correction from review rather than from research.

Refined while writing T01: the sharper form of F4 is that **the five
ladders describe a consumer of storage, not a provider of it.** Every S3
service scores at or near zero on I, A and E for the same structural
reason — a storage or credential platform has no tenant dimension of its
own. The `openbao` E line is the demonstration: `E: 0` is literally correct
and actively misleading, because the mechanism in place is
credential-scoped structural separation, the machinery E4 describes,
pointed at a consumer boundary rather than a tenant one. Proposed remedy is
a **provider declaration** beside the consumer vector, stating per axis the
maximum level the platform makes reachable and what the consumer must do to
reach it. Offered as an addition, not a renumbering.

**F5 — `policy-nexus` T02/T05 cannot be built against the corpus as it
stands.** Measured across the workstation on 2026-08-17: **69 ADRs in 19
repos** — closely matching that workplan's "roughly 68 across 18" — of
which **21 carry YAML frontmatter**, **41 carry any status field**, and
**2 carry any notion of a review date**. T02 specifies a front-matter-driven
renderer taking title, status, revision and review date from the source; T05
requires every page to show status, revision and last-reviewed, with a
staleness marker once a review interval is exceeded. Against this corpus
that renderer has nothing to read for 48 of 69 documents, and the currency
half of the repo's purpose has data for 2.

*Recommend:* T03 of that workplan should treat frontmatter as an **ingestion
precondition**, not a rendering input — a document without the required
fields is reported as non-conformant and left unpublished, rather than
rendered with blanks or with dates the site inferred. Inferring them is the
failure mode that workplan already names as its top risk: the publication
becomes a second source of truth. The corollary is that policy-nexus needs
a conformance report aimed at source repos before it needs a site, and this
repo's `docs/adr/README.md` is one repo's answer to it.

## Boundaries

- No workload moves placement level in this workplan. Declaring where
  things are is separate from changing where they are.
- No monitoring is built here. T03 records the gap; closing it belongs
  with `railiance-telemetry`.
- Co-signature with `adaptive-pricing` is *requested*, not assumed. If they
  decline, T02 records single ownership and says so.
- This repo does not amend NetKingdom canon. Findings are routed; the
  standard's owner decides.

## Tasks

```task
id: RPF-WP-0018-T01
status: done
priority: high
state_hub_task_id: "88d1342b-5093-5fbc-aa84-1608d163b979"
```
**Publish the S3 posture vector set.** Write `docs/tenancy-posture.md`:
one vector per service under S3 custody (`openbao`, `apps-pg`, and the
`rapp-postgres`-operated clusters we hold policy for), each with `current`,
`target`, `reviewed`, and a `gap` note per axis below target. State plainly
which services this repo *owns* and which it only holds *policy* for.
Route F4 to `net-kingdom` with the vector set as the evidence.

```task
id: RPF-WP-0018-T02
status: done
priority: high
state_hub_task_id: "03f0a5bd-7876-5784-bf02-11cbcdf005bb"
```
**Accept placement ownership, scoped.** Write `docs/placement-policy.md`:
adopt the P0–P4 ladder by reference (do not restate it — the canon copy is
the source), record the default (P1 for platform services), and record a
named **placement owner per workload** for every consumer on an S3-custody
cluster. State the F3 split explicitly: rule here, number in
`rapp-postgres`. Request `adaptive-pricing` co-signature; record the answer
either way.

```task
id: RPF-WP-0018-T03
status: done
priority: medium
state_hub_task_id: "b602226f-8eb5-5609-995f-94f9074b0895"
```
**Make triggers monitorable or honestly unmonitored.** For each of the five
§8 triggers, record in `docs/placement-policy.md` what signal would fire it,
who reads that signal, and at what cadence — or the literal marker
`unmonitored: pending railiance-telemetry`. Include the §8.3.3 obligation:
report which service classes are co-resident. Today that is
`latency-critical` (`tenant-engine`) beside `batch` (`audit-core`) on
`platform-pg`, which becomes a stated risk rather than an invisible one.

```task
id: RPF-WP-0018-T04
status: done
priority: medium
state_hub_task_id: "92ce14f6-afee-50f6-abd4-197c4724a589"
```
**Disclose quotas to consumers (§10.2).** Extend
`docs/s3-consumer-interfaces.md` to `1.1.0` — additive under its own
compatibility rule — adding per-interface connection limits, statement and
idle-transaction timeouts, and backup retention to `apps-pg.v1` and
`rapp-postgres.v1`. Add the standing obligation that a change to any of
these is announced to bound consumers, not discovered by them.

```task
id: RPF-WP-0018-T05
status: done
priority: medium
state_hub_task_id: "58ef22f8-7f1b-5647-babd-eeb817b3ae31"
```
**Create the ADR surface (F2).** Create `docs/adr/` with an ADR template
carrying the frontmatter `policy-nexus` T02/T05 consume: title, status,
revision, owner, last-reviewed, review interval. Promote the decisions that
are already load-bearing and already written down elsewhere — the S3
boundary rule, the credential-lane model, the consumption-mode gate,
and the outcome of T02 — into ADRs. Runbooks stay prose. State in each ADR
which hub `record_decision()` id it supersedes, so the hub stops being the
only home for a decision.

```task
id: RPF-WP-0018-T06
status: done
priority: low
state_hub_task_id: "49c682a0-a9b7-59f0-ad65-79b4fb9bb79c"
```
**Answer §19.9 — retention floor and ceiling.** Decide whether
`backupRetentionDays` gets a platform minimum (so a consumer asking for one
day gets a validation error rather than a quiet disappointment) and a
maximum (so nobody exhausts the volume). Record the rule here; the
enforcing validator is `rapp-postgres`'s. Carry `rapp-postgres` ADR-0002's
consequence forward: on a shared cluster a consumer's erasure horizon is the
maximum declared across co-residents, so a shorter horizon is a P2 trigger.

```task
id: RPF-WP-0018-T07
status: done
priority: high
state_hub_task_id: "ad7a159b-a395-50e0-a517-d605a1d70108"
```
**Route the findings.** Reply to `rapp-postgres` and `tenant-engine` with
T01/T02 outcomes and F3/F4. Reply to `policy-nexus` with F1 (substrate
misassignment, with the S1/S2 split recommended) and F2 (ADR surface now
being built, plus the hub-decisions gap). Reply to `railiance-master` on
`ba477968`, since a second public name on reef-railiance depends on the
same answer. Mark the routed messages read.

## Sequencing

T01 and T02 are the ratification inputs and go first; T07 cannot be
answered without them. T03 hangs off T02's document. T04 and T05 are
independent and can run any time. T06 is last and cheap.

Deliberately not blocking on ratification: this repo publishes its
declaration whether or not the standard is ratified, because §6 makes
accuracy the conformance test and an accurate declaration is useful even if
the ladders are later renumbered.

## Risks

**Accepting ownership of a policy we cannot enforce.** §8.1 monitoring is
the specific case. Mitigation is T03's explicit `unmonitored` marker — an
owner who says what is not covered still owns it usefully; one who implies
coverage does not.

**Scope creep into S1/S2.** F1 is the live instance. Mitigation is that
this workplan routes the finding and does not build the ingress.

**A declaration that goes stale the day it is written.** Mitigation is the
`reviewed:` date on the vector set and the review interval in the ADR
template — the same currency mechanism `policy-nexus` T05 will read.

## Closed 2026-08-18

All seven tasks done. What the workplan produced, and what it changed
elsewhere:

- `docs/tenancy-posture.md` + `tenancy.yaml` — the vector set, machine-readable
  with the human reasoning kept beside it.
- `docs/placement-policy.md` — placement rule, owner per workload, triggers,
  retention floor and ceiling.
- `docs/s3-consumer-interfaces.md` `1.1.0` — quota disclosure.
- `docs/adr/` — created from nothing; `ADR-0001`, `ADR-0002`, `ADR-0003`.

**Two findings were adopted upstream.** The provider-declaration proposal (F4,
narrowed) is in the framework and its canonical form is the `provider:` block
in `tenancy.yaml`. `adaptive-pricing` declined the standing co-signature and
supplied a stronger replacement — typed tier minima joined at tier definition —
which draft-8 adopted; `ADR-0002` records the outcome as single ownership plus
a mandatory typed constraint join, not as an absent signature.

**Three corrections were issued against our own output**, all in the same
direction — claiming levels we could not evidence. `openbao A: 2` retracted to
`A: 0`; the provider finding narrowed once §6's `flex-auth` precedent was read;
the §11 summary to `adaptive-pricing` corrected, since §11.2 keeps marketing
vocabulary free and only the *cannot-reach* claim is restricted, to E4. All
three are recorded in the documents rather than edited away.

**What this workplan deliberately did not do:** fix anything. It found that
`apps-pg` had no backup, no per-consumer controls and no isolation probes, and
published those as visible defects. `RPF-WP-0019` closes them.

**Left open, not owned here:** `bao.coulomb.social` still needs confirmation
against live reef state (`railiance-master` `ba477968`), and F1's substrate
split is with `policy-nexus` to act on.
