Propose ADR-0011 and the release-unit schema.
Amends ADR-0007 with a fate-group declaration whose claim is the coverage authority. Founder review is RMASTER-WP-0028. release-registry validates against this file and does not copy it. Assistant: grok Assistant-Session: 01a15f9f-3d77-7d21-911b-d93c86f9d14f
This commit is contained in:
parent
a0be0d3142
commit
56fe6bda80
4 changed files with 538 additions and 0 deletions
126
docs/adr/ADR-0011-release-units-and-federated-registry.md
Normal file
126
docs/adr/ADR-0011-release-units-and-federated-registry.md
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
---
|
||||
id: RMASTER-ADR-0011
|
||||
title: "Release units and the federated release-unit registry"
|
||||
status: proposed
|
||||
revision: "proposed-1"
|
||||
owner: railiance-master
|
||||
last_reviewed: "2026-10-21"
|
||||
review_interval: 6m
|
||||
---
|
||||
|
||||
# ADR-0011: Release units and the federated release-unit registry
|
||||
|
||||
Date: 2026-10-21
|
||||
Status: Proposed
|
||||
|
||||
Amends ADR-0007. Founder review is `RMASTER-WP-0028`.
|
||||
|
||||
## Context
|
||||
|
||||
ADR-0007 requires every managed running deployable to have exactly one rollout
|
||||
owner, grouped by shared rollback fate. It stored each group as a `rapp-*`
|
||||
repository and a `declarations/rapp.yaml` file validated by
|
||||
`schemas/rapp.schema.json`.
|
||||
|
||||
That cardinality is right. The storage is not, once a group is only a
|
||||
declaration, a pin of another repository's files, and a render script. Those
|
||||
repositories do not make the coverage question checkable. A hand-maintained
|
||||
namespace map, an orphaned Helm release, a unit declared twice, and a Helm
|
||||
history that no longer matches the live workload all stayed invisible.
|
||||
|
||||
`release-registry` is the composer and the read-only checker. This repository
|
||||
keeps the normative declaration, as it does for rapp, rail, and reef.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **Three layers.** A workload is a live object, observed and never declared
|
||||
by hand. A release unit is the governed fate group. Composition is a
|
||||
relation between release units: containment, and separately a dependency
|
||||
between units that still roll back on their own. Repositories that
|
||||
contribute to a unit stay a third relation, many-to-many, as ADR-0007
|
||||
already has for repos and rapps.
|
||||
|
||||
2. **The coverage invariant stands.** Every managed running deployable belongs
|
||||
to exactly one release unit. ADR-0007's `unknown` and `not-applicable`
|
||||
outcomes stay distinct. A child object controlled by a claimed workload is
|
||||
the same fate, not a second subject.
|
||||
|
||||
3. **The claim is the authority.** The declaration names each workload. The
|
||||
label `railiance.io/release-unit` on that object must carry the same unit
|
||||
id. The label assigns no owner. A missing or different label is a
|
||||
disagreement, not a second way to resolve ownership. The checker reports
|
||||
three coverage findings and does not collapse them: unclaimed (`unknown`),
|
||||
a claim whose object is absent, and a label mismatch.
|
||||
|
||||
4. **The schema is normative.** `schemas/release-unit.schema.json` defines the
|
||||
declaration. It keeps the rapp composition block, the rollout, smoke and
|
||||
rollback contracts, exposure, `data_classification` and `criticality`, and
|
||||
adds the claim, the two relations, and a specification-level OCM pin
|
||||
subset. This ADR cites that file. It does not restate its fields.
|
||||
|
||||
5. **Repo policy.** A separate `rapp-*` repository exists only for a unit
|
||||
that has substantial content of its own: its own manifests or tests, or
|
||||
several source repositories combined. A thin unit is a declaration in the
|
||||
owner's repository at `registry/release-units/`. Retiring a thin repository
|
||||
waits until this ADR is accepted and the owner has declared the unit.
|
||||
|
||||
6. **Deviations.** Anything this schema does on purpose that OCM or Backstage
|
||||
would not do is listed below, with the reason. Elsewhere the declaration
|
||||
follows those norms. There is no OCM library or controller dependency.
|
||||
|
||||
7. **This repository does not compose or check.** `release-registry` validates
|
||||
against the schema file here. It does not copy the schema. It does not
|
||||
deploy, and a declaration grants no authority.
|
||||
|
||||
## Deviations
|
||||
|
||||
- **OCM component references are one list.** Containment and ordering are
|
||||
different fate rules: an umbrella does not share rollback, and a dependency
|
||||
orders units that roll back alone. The pin block keeps OCM references. The
|
||||
operational relations are the ones the coverage model uses. One reference
|
||||
list would hide which edge shares fate.
|
||||
|
||||
- **An OCM resource version is not a Helm release revision.** Chart version
|
||||
and Helm history revision move apart. The pin records the revision beside
|
||||
the chart version because the drift that matters is the history against the
|
||||
live object. The chart version remains the OCM resource version.
|
||||
|
||||
- **An OCM digest value is raw bytes under a normalisation algorithm.** The
|
||||
pin stores the digest string the live workload already shows, including the
|
||||
`sha256:` prefix on an image. The drift check is a comparison with that
|
||||
object. A second encoding would report a match as drift.
|
||||
|
||||
- **Backstage `owner` is a Group.** Here the owner is the accountable
|
||||
repository. This estate has no catalog runtime, and rollout accountability
|
||||
is already a repository.
|
||||
|
||||
- **Backstage `spec.system` and `dependsOn` name catalog entities.** The
|
||||
relations name release-unit ids. A later catalog export can prefix them.
|
||||
Inventing System and Component entities now would invent a catalog.
|
||||
|
||||
- **`app.kubernetes.io/*` has no fate-group id.** The additional label
|
||||
`railiance.io/release-unit` carries the unit id so the checker can see
|
||||
disagreement. It is agreement with the claim. ADR-0007 still forbids
|
||||
inferring an owner from a label, a namespace, or a repository name.
|
||||
|
||||
- **OCM signing, transport, and controllers are unused.** OCM v2's own case
|
||||
is that a consumer takes the specification without the monolith. Coverage
|
||||
and drift need the descriptor shape, not a controller.
|
||||
|
||||
## Consequences
|
||||
|
||||
- `schemas/rapp.schema.json` remains the schema for a `rapp-*` declaration.
|
||||
A release unit is a further declaration, not a silent rewrite of every
|
||||
rapp file.
|
||||
- Until this ADR is accepted, `release-registry` may validate against the
|
||||
proposed schema. An amendment during review updates those fixtures.
|
||||
- Owner repositories declare units. `release-registry` does not write those
|
||||
files.
|
||||
- The checker is read-only. A Helm fact that exists only inside a release
|
||||
Secret stays unobservable. The checker does not read Secret values.
|
||||
|
||||
## Confirmation
|
||||
|
||||
Proposed on 2026-10-21 for founder review under `RMASTER-WP-0028`.
|
||||
Acceptance records the revision here. No release-unit declaration is
|
||||
normative before that.
|
||||
Loading…
Add table
Add a link
Reference in a new issue