Finish RAILIANCE-WP-0021: family schemas, validator, and ADR-0007
Add rail and reef schemas, derive reef bound_rapps from rapp.bound_reefs, and ship a standalone family-declaration validator with an inventory-fed coverage check. Point the bootstrap contract at the schemas, record the dimension and cardinality decisions in ADR-0007, correct the first-wave candidates document, and release the shape to downstream repos.
This commit is contained in:
parent
d3b3512a60
commit
3cc0dc31d6
20 changed files with 1509 additions and 187 deletions
76
docs/adr/ADR-0007-rapp-declaration-contract.md
Normal file
76
docs/adr/ADR-0007-rapp-declaration-contract.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# ADR-0007: Rapp Declaration Contract
|
||||
|
||||
Date: 2026-08-13
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
`RAILIANCE-WP-0017` through `RAILIANCE-WP-0019` established the four-axis
|
||||
model and materialized the first family repos. The model held up. Its
|
||||
enforcement did not.
|
||||
|
||||
A 2026-08-11 survey by `railiance-platform` found that the three live
|
||||
`rapp.yaml` files were mutually unreadable: rollout, smoke, and rollback
|
||||
contracts used different shapes; metadata that both rails carry consistently
|
||||
appeared in only one rapp; `reef-railiance` `bound_rapps` listed `rapp-qonto`
|
||||
only, while `rapp-openbao` and `rapp-postgres` were already live on the same
|
||||
reef. `docs/repo-family-bootstrap-contract.md` named fields in prose and
|
||||
could not catch any of this.
|
||||
|
||||
The same survey treated rapp grouping as something that might be derived from
|
||||
Forgejo organizations or from State Hub domains. Neither works. A repo lives
|
||||
in exactly one Forgejo org, so `org:repo` is one-to-many. A repo may
|
||||
legitimately contribute to more than one rapp, so `rapp:repo` is
|
||||
many-to-many. A many-to-many grouping cannot be derived from a one-to-many
|
||||
one. Domains fail in both directions. The three dimensions also change at
|
||||
different speeds.
|
||||
|
||||
Canon OAS P1 requires independent perspectives to be separate orthogonal
|
||||
dimensions. Decision `d07ee5f9` already recorded this from the
|
||||
`railiance-platform` side; this ADR is the framework record.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **Bounded rapp context is its own dimension.** It is derived neither from
|
||||
Forgejo organizations nor from State Hub domains. Grouping is a first-class
|
||||
declaration, not a projection of some other axis.
|
||||
|
||||
2. **Two cardinalities stay distinct.** Repos to rapps is many-to-many: a
|
||||
repo may appear in the `composition.member_repos` of more than one rapp.
|
||||
Deployables to rapps is one-to-one: every running deployable has exactly
|
||||
one rapp that owns its rollout. The coverage question — *does every live
|
||||
deployable belong to exactly one rapp?* — is well-formed only if these
|
||||
stay distinct.
|
||||
|
||||
3. **Granularity is grouped-by-bounded-context.** One rapp per cohesive group
|
||||
that deploys, versions, and rolls back together, not one rapp per
|
||||
deployable. Grouping is legitimate only where members share rollout and
|
||||
rollback fate. A single-repo rapp is the one-member case of the same
|
||||
`composition` block, not a second shape.
|
||||
|
||||
4. **The schema is normative.** `schemas/rapp.schema.json`,
|
||||
`schemas/rail.schema.json`, and `schemas/reef.schema.json` define the
|
||||
shapes. Framework prose cites those files. It does not restate their
|
||||
fields. Reef `bound_rapps` is a derived projection of `rapp.bound_reefs`,
|
||||
not a hand-maintained registry.
|
||||
|
||||
The detailed shapes, including the single normative form of the rollout,
|
||||
smoke, and rollback contracts, live in the schema files and
|
||||
`schemas/README.md`.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Drift across family declarations fails in
|
||||
`tools/validate-family-declarations.py` instead of accumulating in prose.
|
||||
- `railiance-platform` `RAILIANCE-WP-0015-T02` can converge `rapp-openbao`
|
||||
and `rapp-postgres` onto one shape. Migration belongs to the owning repos;
|
||||
this ADR does not move any declaration.
|
||||
- `reef-railiance` must stop treating `bound_rapps: [rapp-qonto]` as source
|
||||
of truth. The list is already stale.
|
||||
- Three further `rapp-*` repos (`rapp-secrets-engine`, `rapp-tenant-engine`,
|
||||
`rapp-user-engine`) carry the family prefix and no declaration. They are
|
||||
visible to the validator as undeclared and must be declared, renamed, or
|
||||
retired by their owners.
|
||||
- Calling the validator from `fix-consistency` still waits on
|
||||
`the-custodian` admitting the family prefixes into the classification
|
||||
standard. That sequencing is not this repo's.
|
||||
Loading…
Add table
Add a link
Reference in a new issue