docs: chapters 20-60, ADR-0019, and the worked example set - #64
Merged
Conversation
Lands the remainder of the v1 specification. Chapters 10 and 16 merged as #58 and #59; this carries 20, 30, 40, 50 and 60 together, plus the revisions those chapters make to earlier ADRs and the examples. Combined rather than stacked, because the stack could not be salvaged after the first two squash-merges: each branch was cut from the pre-squash tip of the one below, so rebasing them onto the merged base conflicted. Splitting them again after the fact would also have produced PRs that do not stand alone -- chapters 50 and 60 revise 30 and 40 (prune semantics, class C's home, two resolved open items), and the glossary correction touches all of them. #60 through #63 remain as the per-chapter review record. Chapter 20, the Resolved Deployment. One rule carries the specification: every assignment is a pure function of Service Intent, the pinned Cluster Context and the pinned locks. Nothing is allocated or remembered between renders. Applying it exposed a hole in ADR-0003 -- taken literally it forbids declaring the Service Id -- so identity is separated from pool: identity is declared and checked, a pool is assigned. Not one live hostname derives from a Service Id, so an exposure carries a name. Also corrects something said repeatedly and wrongly: layer 2 assigns a selector and an affinity, never a node. Chapter 30, the Deliverable Set. Closes the coverage question with a measurement: 450 objects, 39 kinds, 329 files, split 364 intent-derived, 41 pack-delivered, 45 authored. 328 of the 364 have an adapter; the 36-object gap is 14 that need only registering and 22 that need writing. Chapter 40, composition. 26 estate-wide invariants across identity, references, secrets and completeness. The unit of publication is a repository rather than a domain, which resolves the homelab-collections split question without a decision. Order-independence forces every collision to be an error rather than a last-write-wins merge. Chapter 50, lifecycle, with ADR-0019. Push delivery gated by relationship-scoped aggregators; Flux keeps the foundation, because 18 of the 41 pack-delivered objects are HelmRelease and applying one with kubectl does nothing without helm-controller. The cluster is the inventory: a deployer label supplies what Flux gets from a Kustomization's record. Drift correction is an in-cluster CronJob, not an Actions schedule, because the estate measured Actions crons at four to seven runs per day regardless of the declared interval. Chapter 60, setup and adoption. The ordering hazard is the point: Flux prunes, so spec.prune must be set false BEFORE a Service's manifests leave the Flux source, or adoption deletes it. Also: the glossary was materially stale and is corrected -- Claim Mode described a model that no longer exists, Contended Value conflated identity with pool, and seven terms were missing. 39 terms to 47. Four workflows, an Aggregator declaration, a Renovate custom manager, the generated deployer RBAC, the reapply CronJob and a negative fixture. Every workflow is one job with many steps, because jobs bill by the minute rounded up. Audit at commit time: 11 mermaid blocks valid across three diagram types, 18 example files parsing, no broken relative links, no stale vocabulary.
This was referenced Aug 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands the remainder of the v1 specification. Chapters 10 and 16 merged as #58 and #59.
Why this is combined rather than stacked. After #58 and #59 squash-merged, the remaining branches could not be rebased onto the merged base — each was cut from the pre-squash tip of the one below, so the replay conflicted. Splitting them again would also have produced PRs that don't stand alone: chapters 50 and 60 revise 30 and 40 (prune semantics, class C's home, two resolved open items), and the glossary correction touches all of them. #60–#63 stay open as the per-chapter review record and can be closed once this merges.
Content is byte-identical to
docs/ch50-lifecycle, verified before committing.What's in it
Chapter 20 — Resolved Deployment. The purity rule: every assignment is a pure function of Service Intent, the pinned Cluster Context and the pinned locks. Applying it exposed a hole in ADR-0003 — taken literally it forbids declaring the Service Id — so identity (declared, checked) is separated from pool (assigned). Not one live hostname derives from a Service Id, so an exposure carries a
name. Also corrects something the spec said repeatedly and wrongly: layer 2 assigns a selector and affinity, never a node.Chapter 30 — Deliverable Set. Closes coverage with a measurement: 450 objects, 39 kinds, 329 files → 364 intent-derived / 41 pack-delivered / 45 authored. 328 of the 364 have an adapter; the 36-object gap is 14 that need only registering and 22 that need writing.
Chapter 40 — Composition. 26 estate-wide invariants. The publication unit is a repository, not a domain, which resolves the
homelab-collectionssplit question without a decision. Order-independence forces every collision to be an error rather than last-write-wins.Chapter 50 + ADR-0019 — Lifecycle. Push delivery gated by aggregators; Flux keeps the foundation, because 18 of the 41 pack-delivered objects are
HelmReleaseand applying one withkubectldoes nothing withouthelm-controller— and those charts arevault,vault-secrets-operator,metrics-stack, both Traefiks,cert-manager,metallb. The cluster is the inventory. Drift correction is an in-cluster CronJob, not an Actions schedule.Chapter 60 — Setup and adoption. The ordering hazard is the point: Flux prunes, so
spec.prune: falsemust be set before a Service's manifests leave the Flux source, or adoption deletes it.The glossary was materially stale and is corrected:
Claim Modedescribed a model that no longer exists,Contended Valueconflated identity with pool, and seven terms were missing. 39 → 47.Examples: four workflows (each one job with many steps, because jobs bill by the minute rounded up), the
Aggregatordeclaration, a Renovate custom manager, the generated deployer RBAC, the reapply CronJob, and a negative fixture so an invariant that stops running is detectable.Audit at commit time