# Publication contract for source owners How a governing document gets a permanent address on `https://policy.coulomb.social`. This note is the owner-facing contract from PNEX-WP-0002-T01. It is not itself a published policy document. `policy-nexus` publishes. It does not author your document and it does not write back. ## What can be published | Kind | What it is | Typical source path | | --- | --- | --- | | `standards` | Governing standard | `canon/standards/_vN.md` | | `architecture` | One arc42 document per system | `docs/architecture/_v0.1.md` or `canon/architecture/_v0.1.md` | | `constitution` | Estate constitution | `canon/constitution/` | | `adr` | Architecture decision record | `docs/adr/.md` | | `findings` | A finding explicitly marked public by `risk-nexus` | `findings/RISK-F-NNNN-.md` | | `methods` | A public risk judgement instrument | `docs/method/.md` | Risk findings and methods are published only after `risk-nexus` has made the disclosure decision and an explicit `publication.json` entry names the file. Embargoed or restricted findings fail that admission test. Workplans, evidence, runbooks, review ledgers, rulings, and general docs are out. An ADR is published only after an explicit `publication.json` entry. Architecture documents follow the same rule. Discovery (`source-inventory.config.json`) is not publication. ## Front-matter the builder requires ```yaml --- id: title: "Human title" status: proposed | accepted | adopted | fixed | superseded | withdrawn owner: revision: "accepted-1" last_reviewed: "YYYY-MM-DD" review_interval: 6m --- ``` | Field | Rule | | --- | --- | | `id` | Must equal the `publication.json` `id`. Globally unique. Repo-prefix ADRs (`RMASTER-ADR-0001`, `policy-nexus-adr-0001`). Bare `ADR-001` will collide. | | `title` | Shown on the page and the site index. | | `status` | Honesty with the body. If the prose says relocated, the status is `superseded`. | | `owner` | Who answers for the content. | | `revision` or `version` | Becomes the immutable revision slug. | | `last_reviewed` or `updated` | ISO date. Currency starts here. | | `review_interval` | `Nd`, `Nm`, or `Ny`. Default `6m` if you do not declare one; the publication entry may also set it. | A document missing any of those fields fails the build. Do not ask this repo to invent them. ## Addresses From ADR-0001: ```text //// ////revisions// ``` - `` is one of the six kinds above. - `` is a kebab-case slug, unique on the site. If two systems would share a short name, prefix with the system slug (`railiance-repository-prefix`, not `repository-prefix`). - `` is the document series (`v0.1`, `v1`). A new major version is a new current address; the old one stays and is marked superseded. - `` is the front-matter `revision` (for example `draft-8`, `accepted-1`). That URL is write-once. Examples: ```text /standards/tenancy-posture/v0.1/ /architecture/policy-nexus/v0.1/ /adr/addressing-and-permanence/v1/ /adr/railiance-repository-prefix/v1/ /findings/flex-auth-unauthenticated-check/v1/ /methods/risk-severity/v1/ ``` No URL is derived from a checkout path, branch, or build number. ## Architecture documents (arc42) One markdown file per system, following `markitect-main/examples/templates/TEMPLATE-ARC42.md`. - Chapter 9 **lists** that system's ADRs (id, status, pointer). It does not paste them. - First-wave complete means chapters **1, 3, 4, 5.1, 9 and 12** are real. Every other chapter is real or explicitly `N/A` with a reason. - A stub that can be published early has real chapters **1, 3 and 9** plus this front-matter. Validate: ```sh markitect validate docs/architecture/_v0.1.md \ --schema /path/to/markitect-main/markitect/schemas/arc42-schema-v1.0.md ``` Catalog id: `arc42-v1`. ## Infospace index The collection index lives at `the-custodian/canon/architecture/infospace/`. It **references** the owning-repo documents. It does not copy them. InfoTechCanon owns the information-space model, not this estate's building-block view. ```sh markitect infospace check --config \ the-custodian/canon/architecture/infospace/infospace.yaml ``` ## How to request publication 1. Put the front-matter on the source document in the owning repo. 2. For an architecture document, meet the stub or first-wave bar above. 3. Open a PR against `policy-nexus` that adds one `publication.json` entry (and a `repositories` path if the repo is new here). 4. `make check` and `make build` must pass. Do not glob a tree into `publication.json`. Inventory records every matching source; publication stays one explicit entry per document. ## First-wave architecture collection | Publication id | System slug | Owning repo | Source path | | --- | --- | --- | --- | | `coulomb-estate-architecture` | `coulomb-estate` | `the-custodian` | `canon/architecture/coulomb-estate_v0.1.md` | | `railiance-architecture` | `railiance` | `railiance-master` | `docs/architecture/railiance_v0.1.md` | | `net-kingdom-architecture` | `net-kingdom` | `net-kingdom` | `docs/architecture/net-kingdom_v0.1.md` | | `state-hub-architecture` | `state-hub` | `state-hub` | `docs/architecture/state-hub_v0.1.md` | | `policy-nexus-architecture` | `policy-nexus` | `policy-nexus` | `docs/architecture/policy-nexus_v0.1.md` | ## Machine-readable build-mode authorization The build-mode standard's publication entry declares `guardrail_path: guardrails/build-mode-change-authorization.json`. The builder extracts its single machine-checkable YAML block from the canonical Markdown and emits JSON at that stable path. No second policy copy is maintained. The release manifest binds the artifact digest to the document's source provenance; release verification rejects missing, changed or unsupported rule artifacts. `expires_on` is shown in the document header. A consumer can evaluate a change record with the stdlib-only checker: ```sh python3 tools/guardrails.py build/guardrails/build-mode-change-authorization.json change.json --build-mode ``` ```json { "categories": [], "diff_ref": "reviewed.patch", "rollback": "Restore the previous deployment image and source revision", "abort_owner": "owning-repo", "receipt_path": "execution-receipt.json" } ``` Category declarations are mandatory, even when empty. The checker returns `blue` only with all four nonempty preparation references and confirmed build mode. Missing references, unknown categories or unconfirmed/expired build mode return `incomplete`. Red overrides orange when both are declared. Only `blue` returns exit code zero. Classification does not verify the referenced review or grant credentials, autopilot, public publication approval or runtime authority. Public publication goes in the founder's daily red-lane batch; orange identity acts go in the attended-window checklist. Source generation and local checks can proceed before publication approval. ## Review staged inventory changes The inventory's discovery selectors and each row's disposition/reason are reviewed source. `source_inventory.py refresh` rewrites the inventory and must be followed by review; its default metadata-pending rows are not public publication consent. Before applying such changes, run `make source-inventory-review`. It reads the Git index, so unstaged selectors or documents do not enter the proposed delta. The existing refresh function runs only on a temporary copy. The command writes `build/source-inventory-review.json` (ignored, not a second registry), exits 1 when added/removed source rows require review, and leaves authored files and the Git index unchanged. Existing dispositions and reasons are preserved; duplicate rows, symlink inputs and unresolved index conflicts fail closed. Review and edit the authoritative source explicitly, then stage it and rerun review/source-audit. No candidate is automatically applied or committed. The existing scheduled `.forgejo/workflows/publish-image.yaml` already generates release inventory evidence and publication artifacts from fetched source revisions. The review command is not another scheduler or release gate; current source-audit, currency and founder publication requirements remain in force.