Brings the specification in line with implementation main at 50c8719, which the operator ruled the latest and accepted state on 2026-11-08.
Merging is the acceptance.AGENTS.md §11 and decisions/README.md reserve spec changes and ADR acceptance for the human. These edits were made by an AI System Architect under the operator's explicit delegation for this one task. ADRs marked Accepted here take effect only when you merge.
How to review this
Start with docs/16-known-gaps.md and the eight amended requirements below. Those are where judgement was exercised; most of the remaining diff is the same facts carried through the domain docs.
Accepted changes now in the spec
ADR
Decision
Replaces
0016
Cloudflare Tunnel ingress. Text corrected to match what was built, then accepted
Proposed version
0017
One environment: bare-metal production; dev retired
ADR-0001 provisioning clause
0018
TrueNAS NFS bulk tier; Velero/kopia + Barman to Cloudflare R2; no Longhorn backup target
ADR-0003 backup and bulk clauses
0019
PostgreSQL via CloudNativePG
new
0020
One VPN egress gateway node, no failover; Cilium enforces fail-closed
ADR-0015 kill-switch and resilience
0021
Inbound WireGuard remote access
new
0022
Forward-auth through per-app oauth2-proxy sidecars
ADR-0014 enforcement point and app list
0023
Renovate for images and charts, every change PR-gated
ADR-0009
0024
The CI gate is the approver; sensitive-path review; attributed admin override
new
0025
In-cluster AI Program Manager
new
Accepted ADR text was not rewritten. Partial replacements follow the ADR-0013 precedent: the older ADR stays Accepted and its Status line names the superseded clause.
Requirement changes
No R-* ID was added, removed or renumbered. Eight were amended:
R-PLAT-01, R-ENV-01, R-ENV-02, R-ENV-03: single bare-metal environment.
R-NET-05: single shared node-level gateway.
R-UPD-02: machine-authored PRs through the gate. Majors and designated blast-radius components may wait for review.
R-DNS-05: "public" now includes registered platform routes. unifi and crafty-mc may keep DNS-only records at LAN addresses. Look closely at this one: the impl pins those records in a check, but an earlier handoff recorded the question as "not decided".
R-IDP-02: exceptions added for UniFi, read-only /runbooks, and Crafty web.
Gaps kept, not written out of the spec
Where the implementation simply has not met a requirement and no decision accepted that, the requirement stands. The 57 entries are in docs/16-known-gaps.md, a dated snapshot. The largest:
Homepage at the public apex has no enforced authentication (R-IDP-02).
No off-cluster Gitea mirror exists, while Flux's source is that in-cluster Gitea.
L2/L3 conformance does not run in CI. The implementation's status tool reports zero requirements currently proven.
Also: no API server audit log, no git-history secret scan, no ACME revocation, and VPN port forwarding not built.
Your decisions needed
These are listed at the top of docs/16-known-gaps.md. None blocks this merge.
Is the photos/ tree on the bulk tier irreplaceable? It has no platform backup.
Homepage: enforce the gate, or rule on an exception?
ACME revocation: amend R-TLS-02, or keep it as an open gap?
Is automated fault injection against production acceptable once CI is wired?
Kasm: onboard it, or retire it from the catalog?
After merging
The implementation pins the old spec.ci/SPEC_PIN must be bumped to the merge commit in an implementation PR. ci/ is a sensitive path, so that PR needs your review or your own override.
Update your local spec checkout to the new main when that lands. Until the pin matches it, a local gate reports blocked. It is already blocked today: the pin is at b633b7f and spec main is at 1ddc14b.
What was checked, and what was not
Checked: the set of requirement IDs is unchanged; every relative link resolves; the spec text that implementation checks parse (the docs/07 auditability section, the Phase 7 wording, the requirement definitions) is intact; no IP addresses or secret-like strings in the diff.
Not checked: anything live. This came from reading the two repositories. No cluster, tunnel, router or DNS state was measured, so statements about what is "public" mean what the manifests declare. The spec repo has no CI, so no automated gate ran on this PR. The implementation's gate was not run against this branch. One item is flagged as unmeasured in the register: whether block-mode VM disks can be captured by the file-system backup path at all.
Brings the specification in line with implementation `main` at `50c8719`, which the operator ruled the latest and accepted state on 2026-11-08.
**Merging is the acceptance.** `AGENTS.md` §11 and `decisions/README.md` reserve spec changes and ADR acceptance for the human. These edits were made by an AI System Architect under the operator's explicit delegation for this one task. ADRs marked `Accepted` here take effect only when you merge.
## How to review this
Start with `docs/16-known-gaps.md` and the eight amended requirements below. Those are where judgement was exercised; most of the remaining diff is the same facts carried through the domain docs.
## Accepted changes now in the spec
| ADR | Decision | Replaces |
|---|---|---|
| 0016 | Cloudflare Tunnel ingress. Text corrected to match what was built, then accepted | Proposed version |
| 0017 | One environment: bare-metal production; dev retired | ADR-0001 provisioning clause |
| 0018 | TrueNAS NFS bulk tier; Velero/kopia + Barman to Cloudflare R2; no Longhorn backup target | ADR-0003 backup and bulk clauses |
| 0019 | PostgreSQL via CloudNativePG | new |
| 0020 | One VPN egress gateway node, no failover; Cilium enforces fail-closed | ADR-0015 kill-switch and resilience |
| 0021 | Inbound WireGuard remote access | new |
| 0022 | Forward-auth through per-app oauth2-proxy sidecars | ADR-0014 enforcement point and app list |
| 0023 | Renovate for images and charts, every change PR-gated | ADR-0009 |
| 0024 | The CI gate is the approver; sensitive-path review; attributed admin override | new |
| 0025 | In-cluster AI Program Manager | new |
Accepted ADR text was not rewritten. Partial replacements follow the ADR-0013 precedent: the older ADR stays `Accepted` and its Status line names the superseded clause.
## Requirement changes
No `R-*` ID was added, removed or renumbered. Eight were amended:
- **R-PLAT-01, R-ENV-01, R-ENV-02, R-ENV-03**: single bare-metal environment.
- **R-NET-05**: single shared node-level gateway.
- **R-UPD-02**: machine-authored PRs through the gate. Majors and designated blast-radius components may wait for review.
- **R-DNS-05**: "public" now includes registered platform routes. `unifi` and `crafty-mc` may keep DNS-only records at LAN addresses. **Look closely at this one**: the impl pins those records in a check, but an earlier handoff recorded the question as "not decided".
- **R-IDP-02**: exceptions added for UniFi, read-only `/runbooks`, and Crafty web.
## Gaps kept, not written out of the spec
Where the implementation simply has not met a requirement and no decision accepted that, the requirement stands. The 57 entries are in `docs/16-known-gaps.md`, a dated snapshot. The largest:
- **Homepage at the public apex has no enforced authentication** (R-IDP-02).
- **No off-cluster Gitea mirror exists**, while Flux's source is that in-cluster Gitea.
- **L2/L3 conformance does not run in CI.** The implementation's status tool reports zero requirements currently proven.
- Also: no API server audit log, no git-history secret scan, no ACME revocation, and VPN port forwarding not built.
## Your decisions needed
These are listed at the top of `docs/16-known-gaps.md`. None blocks this merge.
1. Is the `photos/` tree on the bulk tier irreplaceable? It has no platform backup.
2. Homepage: enforce the gate, or rule on an exception?
3. ACME revocation: amend R-TLS-02, or keep it as an open gap?
4. Is automated fault injection against production acceptable once CI is wired?
5. Kasm: onboard it, or retire it from the catalog?
## After merging
1. **The implementation pins the old spec.** `ci/SPEC_PIN` must be bumped to the merge commit in an implementation PR. `ci/` is a sensitive path, so that PR needs your review or your own override.
2. **Update your local spec checkout** to the new `main` when that lands. Until the pin matches it, a local gate reports blocked. It is already blocked today: the pin is at `b633b7f` and spec `main` is at `1ddc14b`.
## What was checked, and what was not
Checked: the set of requirement IDs is unchanged; every relative link resolves; the spec text that implementation checks parse (the `docs/07` auditability section, the Phase 7 wording, the requirement definitions) is intact; no IP addresses or secret-like strings in the diff.
**Not checked: anything live.** This came from reading the two repositories. No cluster, tunnel, router or DNS state was measured, so statements about what is "public" mean what the manifests declare. The spec repo has no CI, so no automated gate ran on this PR. The implementation's gate was not run against this branch. One item is flagged as unmeasured in the register: whether block-mode VM disks can be captured by the file-system backup path at all.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The operator ruled the implementation repo's main (50c8719) the latest
and accepted state. Sync the spec to it.
Accepted changes are reflected: one bare-metal environment, TrueNAS bulk
storage, R2 off-cluster backup, CloudNativePG, single-node VPN gateway
with Cilium fail-closed, inbound WireGuard, per-app auth sidecars,
Renovate, the CI gate as approver, and the pm-agent. New ADR-0017..0025;
ADR-0016 corrected and accepted; R-* IDs unchanged, eight amended.
Where the implementation has simply not met a requirement, the
requirement stands and the shortfall is recorded in docs/16-known-gaps.md.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Brings the specification in line with implementation
mainat50c8719, which the operator ruled the latest and accepted state on 2026-11-08.Merging is the acceptance.
AGENTS.md§11 anddecisions/README.mdreserve spec changes and ADR acceptance for the human. These edits were made by an AI System Architect under the operator's explicit delegation for this one task. ADRs markedAcceptedhere take effect only when you merge.How to review this
Start with
docs/16-known-gaps.mdand the eight amended requirements below. Those are where judgement was exercised; most of the remaining diff is the same facts carried through the domain docs.Accepted changes now in the spec
Accepted ADR text was not rewritten. Partial replacements follow the ADR-0013 precedent: the older ADR stays
Acceptedand its Status line names the superseded clause.Requirement changes
No
R-*ID was added, removed or renumbered. Eight were amended:unifiandcrafty-mcmay keep DNS-only records at LAN addresses. Look closely at this one: the impl pins those records in a check, but an earlier handoff recorded the question as "not decided"./runbooks, and Crafty web.Gaps kept, not written out of the spec
Where the implementation simply has not met a requirement and no decision accepted that, the requirement stands. The 57 entries are in
docs/16-known-gaps.md, a dated snapshot. The largest:Your decisions needed
These are listed at the top of
docs/16-known-gaps.md. None blocks this merge.photos/tree on the bulk tier irreplaceable? It has no platform backup.After merging
ci/SPEC_PINmust be bumped to the merge commit in an implementation PR.ci/is a sensitive path, so that PR needs your review or your own override.mainwhen that lands. Until the pin matches it, a local gate reports blocked. It is already blocked today: the pin is atb633b7fand specmainis at1ddc14b.What was checked, and what was not
Checked: the set of requirement IDs is unchanged; every relative link resolves; the spec text that implementation checks parse (the
docs/07auditability section, the Phase 7 wording, the requirement definitions) is intact; no IP addresses or secret-like strings in the diff.Not checked: anything live. This came from reading the two repositories. No cluster, tunnel, router or DNS state was measured, so statements about what is "public" mean what the manifests declare. The spec repo has no CI, so no automated gate ran on this PR. The implementation's gate was not run against this branch. One item is flagged as unmeasured in the register: whether block-mode VM disks can be captured by the file-system backup path at all.
🤖 Generated with Claude Code