The forcing case is now tenancy-posture_v0.1, not Custodian ADR-008, and the renderer is tools/render.py rather than a path in another repo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
285 lines
14 KiB
Markdown
285 lines
14 KiB
Markdown
---
|
||
id: POLICY-NEXUS-WP-0001
|
||
type: workplan
|
||
title: "Stand up policy.coulomb.social as the permanent publication surface"
|
||
domain: government
|
||
repo: policy-nexus
|
||
status: proposed
|
||
owner: unassigned
|
||
topic_slug: policy-nexus
|
||
created: "2026-08-17"
|
||
updated: "2026-08-17"
|
||
---
|
||
|
||
# POLICY-NEXUS-WP-0001 — permanent publication surface
|
||
|
||
## Goal
|
||
|
||
Replace disposable artifact-page publication with permanent infrastructure at
|
||
`policy.coulomb.social` that keeps policy **available**, **addressable**,
|
||
**current**, and **honest about its own staleness**.
|
||
|
||
Done means: a governing document lives in its owning repo, is published
|
||
automatically, keeps its URL, shows its status and review date, retains its
|
||
superseded versions, and can be reached by someone outside the estate.
|
||
|
||
## The forcing case
|
||
|
||
`net-kingdom/canon/standards/tenancy-posture_v0.1.md` (*Tenancy Posture*,
|
||
draft-5) needs review from six repos —
|
||
`tenant-engine`, `flex-auth`, `rapp-postgres`, `railiance-platform`,
|
||
`adaptive-pricing`, `audit-core`. It is currently served from a private,
|
||
disposable artifact URL. Routing a document that governs six repos to a link
|
||
that may not resolve later is the problem this workplan exists to end.
|
||
|
||
Tenancy Posture is therefore the first publication and the acceptance test. If the site
|
||
cannot carry it correctly — five ladders, a threat matrix, an E×P grid, twelve
|
||
owner-attributed open questions — the site is not finished.
|
||
|
||
## Existing structure this workplan must respect
|
||
|
||
**The renderer is already here.** `tools/render.py` and `tools/style.css`
|
||
arrived from `the-custodian` on 2026-08-17, along with `make build`. Stdlib
|
||
only, no dependency tree, recognising conventions already present in the
|
||
document rather than requiring extra markup. It was written because the page
|
||
and the source had diverged. T02 generalises it from one document to many; it
|
||
does not start from scratch.
|
||
|
||
**Source of truth stays upstream.** Canon lives in `the-custodian/canon`;
|
||
per-repo ADRs live in their own repos. This repo reads and never writes back.
|
||
A publication surface with write authority is a second source of truth, and the
|
||
estate has a standing rule against that.
|
||
|
||
**The adoption stance applies** (Tenancy Posture §14): adopt published standards and
|
||
structural patterns; build tooling ground-up unless it is an established
|
||
industry standard with broad application. A static-site generator with a
|
||
plugin ecosystem is exactly what this rule excludes.
|
||
|
||
**Platform packages are consumed, not rebuilt.** TLS, DNS, ingress, and any
|
||
credential come from the existing platform. If this repo needs storage it is a
|
||
`rapp-postgres` consumer and declares a posture vector like anyone else.
|
||
|
||
## Non-goals
|
||
|
||
- No editing surface. No CMS, no browser drafting, no comments.
|
||
- No ratification workflow. The site may *show* that a draft is in flight and
|
||
for how long; advancing it is a canon-process decision.
|
||
- No authentication in this workplan. Everything published here is
|
||
public-by-intent; anything that is not does not belong on this surface.
|
||
- No search index in this workplan. Deferred until there is enough content for
|
||
search to beat a good index page.
|
||
|
||
## Tasks
|
||
|
||
### T01 — Addressing scheme and permanence contract
|
||
|
||
Decide, once, how a document maps to a URL, and write down what the estate is
|
||
promising about that URL.
|
||
|
||
- URL shape for a document, and for a specific revision of it.
|
||
- What happens on supersession: the old URL keeps resolving and gains a
|
||
superseded banner pointing forward.
|
||
- What happens on withdrawal: distinguish *withdrawn* (kept, marked) from
|
||
*deleted* (does not happen).
|
||
- Where the version history lives, given the source is git in another repo.
|
||
- The commitment being made — a URL published here is expected to resolve
|
||
indefinitely, and what would have to happen for that to be broken.
|
||
|
||
**Output:** `docs/adr/ADR-0001-addressing-and-permanence.md`.
|
||
|
||
**Why first:** everything downstream bakes in the answer, and changing it later
|
||
breaks the one promise the repo exists to make.
|
||
|
||
### T02 — Generalise the renderer
|
||
|
||
Lift `tools/render.py` from one document to many.
|
||
|
||
- Multi-document: a manifest of sources rather than one path argument.
|
||
- Front-matter driven: title, status, revision, review date, owner from the
|
||
source document rather than from command-line flags.
|
||
- Index generation: a landing page listing documents with status and currency.
|
||
- Keep the convention recognisers (level ladders, threat matrix, E×P grid,
|
||
evidence chips, section rail) and keep it stdlib-only.
|
||
- Keep the "generated from canon — do not edit" marker on every page.
|
||
|
||
**Acceptance:** Tenancy Posture renders byte-identically in substance to the current
|
||
generated page, plus an index entry.
|
||
|
||
### T03 — Source ingestion
|
||
|
||
Define how a document gets from its owning repo to this one.
|
||
|
||
- Manifest format: source repo, path, publication URL, owner.
|
||
- **Scope is canon and ADRs only.** The corpus is bounded and countable today:
|
||
two canon trees (`the-custodian/canon`, `net-kingdom/canon`) and roughly 68
|
||
ADRs across 18 repositories. Workplans, evidence and runbooks are out — a
|
||
site that publishes everything publishes nothing in particular. Enumerate the
|
||
actual list during T03; a glob over `docs/adr/*.md` plus the canon trees is
|
||
the starting point, but each canon subdirectory (`standards`, `architecture`,
|
||
`constitution`, `values`, `tpsc`, `projects`) needs a yes or no rather than a
|
||
wildcard.
|
||
- Fetch mechanism for documents in other repositories, and how a fetch failure
|
||
is surfaced rather than silently serving stale content.
|
||
- Determinism: the same source commit must produce the same page.
|
||
- Record the source commit on the published page, so a reader can tell exactly
|
||
what was rendered.
|
||
|
||
**Open decision for T03:** pull (this repo fetches on a schedule) or push (the
|
||
owning repo triggers on merge). Pull is simpler and keeps the direction of
|
||
dependency clean; push is fresher. Recommend pull with a manual trigger, and
|
||
record the choice.
|
||
|
||
### T04 — Deploy to policy.coulomb.social
|
||
|
||
- DNS, TLS, ingress via the existing platform packages.
|
||
- Static hosting — the output is static files by construction, so the serving
|
||
layer should be the least interesting part of this workplan.
|
||
- Availability expectation stated plainly, with the honest caveat that a
|
||
single-node rail gives restart recovery, not high availability. Do not claim
|
||
an SLA the substrate cannot support.
|
||
- Rollback: republishing a previous build must be a single command.
|
||
- Smoke check after every deploy: the index resolves, Tenancy Posture resolves, and a
|
||
known superseded URL still resolves.
|
||
|
||
### T05 — Currency and staleness
|
||
|
||
The relevance half of the repo's purpose. A permanently available document that
|
||
is quietly out of date is worse than no document.
|
||
|
||
- Every page shows status, revision, and last-reviewed date.
|
||
- A review interval per document, and a visible marker once exceeded.
|
||
- A report of documents past review, and where it is delivered.
|
||
- Drafts show how long they have been in flight. The
|
||
`shared-platform-relational-storage_v0.1` draft has been routed and
|
||
unratified since 2026-08-10; that fact should be visible on the site, because
|
||
invisibility is precisely why it stalled.
|
||
|
||
### T06 — Regulatory intake
|
||
|
||
The information-gathering half, scoped to **regulation bearing on the estate**.
|
||
Deliberately last: the publication path must work before a second content type
|
||
is added.
|
||
|
||
**Inclusion test.** A rule is in scope when it constrains something the estate
|
||
actually does — governs data it holds, a market it sells into, or an obligation
|
||
it has taken on. Public policy that is merely interesting is out. This is a
|
||
compliance surface, not a civic-information corpus.
|
||
|
||
**Record format.** What the source says; the source URL; the date retrieved;
|
||
the jurisdiction; the instrument and article or section; which internal
|
||
document or decision it bears on; who recorded it; when it should next be
|
||
checked.
|
||
|
||
**The hard rule, written into the format itself:** a record states what a
|
||
source said and when it said it. It does **not** state what the estate must
|
||
therefore do. Interpretation belongs to the repo making the decision, and a
|
||
record that reads as a ruling has failed. The estate has no legal function and
|
||
this repo must not grow one by accident.
|
||
|
||
**Staleness is sharper here than for internal documents.** External policy
|
||
changes without telling us, so a record is a dated snapshot, never current law.
|
||
The retrieval date is displayed as prominently as the content, and a record
|
||
past its check date is visibly stale rather than quietly wrong.
|
||
|
||
**Candidate register, to confirm rather than assume.** These are the domains
|
||
the estate's own activity implies; T06 should verify which actually apply
|
||
before treating any as in scope:
|
||
|
||
| Area | Why the estate touches it | Already live in |
|
||
|---|---|---|
|
||
| Data protection / erasure and retention | Tenant personal data, the erasure horizon, whether key destruction satisfies an erasure obligation | ADR-008 plane R; `rapp-postgres` ADR-0002 |
|
||
| Data residency | The `P4` placement level exists for exactly this and has no occupants yet | ADR-008 plane P |
|
||
| Public procurement | `vergabe-teilnahme` is a procurement-participation app and the delivery-lane reference implementation | `business-app-service-contract` |
|
||
| Identity assurance | The IAM Profile's `aal2` class drives live re-query rather than cached claims | `iam-profile_v0.3`; ADR-008 plane I |
|
||
| Sector and cybersecurity obligations | Whether the estate is an in-scope entity at all is itself an open question worth recording once | — |
|
||
| AI and agentic entities | The tenant taxonomy has an `agentic` grouping for financially enabled AI entities | ADR-0013 |
|
||
|
||
**Worked example already in hand.** The ADR-008 retention research holds a
|
||
finding of exactly this shape: data protection authorities have accepted key
|
||
destruction as erasure where physical deletion is disproportionate, under
|
||
conditions, and the EDPB has not formally endorsed it. True as recorded, likely
|
||
to move, and dangerous if ever restated as settled. Migrating that finding into
|
||
the T06 format is the acceptance test for the format.
|
||
|
||
**Acceptance:** the format holds that finding without distortion; the record
|
||
displays its retrieval date as prominently as its content; and a reader can get
|
||
from a record to the internal document it bears on, and back.
|
||
|
||
## Sequencing
|
||
|
||
T01 gates everything. T02 and T03 can proceed in parallel once addressing is
|
||
fixed. T04 needs both. T05 is additive. T06 is deliberately last.
|
||
|
||
The temporary artifact URL for ADR-008 stays live until T04 passes its smoke
|
||
check, and the review is routed to the permanent URL, not before.
|
||
|
||
## Risks
|
||
|
||
**This repo becomes a second source of truth.** The likeliest failure and the
|
||
most damaging. Mitigation: no editing surface, generated pages carry a
|
||
do-not-edit marker, and the manifest records the source commit for every page.
|
||
|
||
**Permanence is promised before it can be delivered.** A URL committed to in
|
||
T01 and broken in year two is worse than never having promised. Mitigation:
|
||
T01 states what would break the promise, and T04 declines to claim an
|
||
availability level the single-node rail cannot support.
|
||
|
||
**Scope drift toward a CMS.** Every publication surface attracts requests for
|
||
editing, comments, and workflow. Mitigation: the non-goals above are part of
|
||
the workplan, not a preface to it.
|
||
|
||
**The renderer grows a dependency tree.** The moment it needs a framework, it
|
||
becomes something only CI can run. Mitigation: stdlib-only is an acceptance
|
||
criterion on T02, not a preference.
|
||
|
||
## Resolved by the operator, 2026-08-17
|
||
|
||
- **Publication scope is canon and ADRs.** Not workplans, evidence, runbooks or
|
||
general documentation. Folded into T03 and INTENT.
|
||
- **Intake scope is regulation bearing on the estate.** Not a broader
|
||
public-interest corpus. T06 is specified accordingly, with an inclusion test
|
||
and a candidate register to confirm.
|
||
|
||
The README's one-line description — "a convergence and publication point for
|
||
government policies" — reads broader than this. Worth updating so the repo does
|
||
not attract the wrong contributions.
|
||
|
||
## Open questions for the operator
|
||
|
||
1. **Owner.** This workplan is `unassigned`. It spans infrastructure and canon
|
||
process and does not obviously belong to an existing repo's agent.
|
||
2. **Canon subdirectory scope.** `standards` and `architecture` are clearly
|
||
policy. Are `constitution`, `values`, `tpsc` and `projects` in or out? T03
|
||
needs a yes or no per directory rather than a wildcard.
|
||
|
||
## Deferred: controlled disclosure
|
||
|
||
**Resolved for now (operator, 2026-08-17): full public disclosure is fine.** The
|
||
estate is in build mode, not production. Publishing architecture, known gaps and
|
||
residual risks openly costs little while there are no users to expose and no
|
||
attacker with anything to gain.
|
||
|
||
**That stops being true at production.** ADR-0001 §5 publishes a blast radius
|
||
because its consumers must read it; the same discipline applied publicly, once
|
||
real tenant data exists, hands an attacker a map. The estate will then need a
|
||
**controlled-disclosure scheme**: a way to hold a finding while it is fixed, and
|
||
publish it once it is — embargo, coordinated timing, and a record that the delay
|
||
was deliberate rather than a document quietly going missing.
|
||
|
||
This workplan does **not** build that, and should not. Two reasons:
|
||
|
||
1. It is a different problem. Publication is about permanence and currency;
|
||
embargo is about risk assessment, severity and timing. Building embargo into
|
||
a publication surface would put risk judgement in the repo least qualified to
|
||
make it.
|
||
2. It likely belongs to a service of its own — a **`risk-nexus`**, by analogy —
|
||
owning finding intake, severity, remediation tracking and disclosure timing,
|
||
with this repo as its publication surface rather than its brain.
|
||
|
||
**What T01 must do about it now:** nothing more than leave room. The addressing
|
||
scheme should not assume every document is public from the moment it exists, so
|
||
that adding an embargo state later is a new status rather than a URL migration.
|
||
Recording that constraint costs nothing today and is expensive to retrofit.
|
||
|
||
**Trigger to revisit:** the first real tenant, or the first finding that would
|
||
be dangerous to publish before it is fixed — whichever comes first.
|