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.
|
||||
|
|
@ -1,15 +1,48 @@
|
|||
# First-Wave `rapp-*` Candidates
|
||||
|
||||
Date: 2026-07-25
|
||||
Updated: 2026-08-13 (RAILIANCE-WP-0021-T08)
|
||||
|
||||
## Purpose
|
||||
|
||||
Choose and order the first `rapp-*` candidates for Railiance.
|
||||
Choose and order the first `rapp-*` candidates for Railiance, and record
|
||||
what was actually built against that plan.
|
||||
|
||||
`rapp-*` repos are for managed workload packaging and scaffolding. They are not
|
||||
new ownership homes. The decision here is therefore not "which repos are
|
||||
important?" but "which workloads already have a strong enough package boundary
|
||||
to become first-class managed wrappers without weakening ownership?"
|
||||
`rapp-*` repos are for managed workload packaging and scaffolding. They are
|
||||
not new ownership homes. The decision is not "which repos are important?"
|
||||
but "which workloads already have a strong enough package boundary to become
|
||||
first-class managed wrappers without weakening ownership?"
|
||||
|
||||
## What Was Actually Built
|
||||
|
||||
The 2026-07-25 plan was:
|
||||
|
||||
1. `rapp-openbao`
|
||||
2. `rapp-vergabe-teilnahme`
|
||||
3. `rapp-forgejo` after the forge runtime target stabilized
|
||||
|
||||
What exists on 2026-08-13:
|
||||
|
||||
| Repo | Status | How it arrived |
|
||||
|---|---|---|
|
||||
| `rapp-openbao` | live, declared | as planned |
|
||||
| `rapp-postgres` | live, declared | ad hoc, from the need for a shared platform database |
|
||||
| `rapp-qonto` | live, declared | ad hoc, from the need to run Qonto on `rail-knative` |
|
||||
| `rapp-vergabe-teilnahme` | never built | the user-facing wrapper it existed to prove is unproven |
|
||||
| `rapp-forgejo` | not built | forge placement is now decided (`d151d817`): workload to `rapp-forgejo`, layer to S4 |
|
||||
| `rapp-secrets-engine` | exists, undeclared | family prefix, no `declarations/` |
|
||||
| `rapp-tenant-engine` | exists, undeclared | family prefix, no `declarations/` |
|
||||
| `rapp-user-engine` | exists, undeclared | family prefix, no `declarations/` |
|
||||
|
||||
The platform-service pattern is proven twice (`rapp-openbao`,
|
||||
`rapp-postgres`). The user-facing wrapper pattern is unproven. That is the
|
||||
consequence of building to immediate need instead of to the planned second
|
||||
slot.
|
||||
|
||||
The operator decision that follows is: build `rapp-vergabe-teilnahme` to
|
||||
prove the user-facing shape before mass extraction. Do not treat the three
|
||||
engine repos, or any other live undeclared workload, as a substitute for
|
||||
that proof.
|
||||
|
||||
## Selection Criteria
|
||||
|
||||
|
|
@ -23,147 +56,159 @@ The first-wave candidates should satisfy most of the following:
|
|||
- low ambiguity between packaging ownership and domain ownership
|
||||
- good demonstration value for later `rapp-*` extractions
|
||||
|
||||
## Assessed Candidates
|
||||
## Planned First-Wave Assessment (2026-07-25)
|
||||
|
||||
The original assessment is kept below so the gap between plan and outcome
|
||||
stays visible. It is not the current worklist.
|
||||
|
||||
### 1. OpenBao from `railiance-platform`
|
||||
|
||||
Assessment: **choose first**
|
||||
Assessment: **choose first** — and this one landed.
|
||||
|
||||
Why it fits:
|
||||
Why it fitted:
|
||||
|
||||
- It is a clear third-party upstream product with durable identity.
|
||||
- The workload already has a substantial Railiance packaging surface:
|
||||
`helm/openbao-values.yaml`, middleware, UI overlay assets, deploy/verify
|
||||
scripts, and operator runbooks.
|
||||
- The repo already distinguishes between the OpenBao workload itself and the
|
||||
wider S3 platform policy that consumes it.
|
||||
- It is important enough to prove that `rapp-*` is not only for user-facing
|
||||
apps; platform services can also be managed workloads.
|
||||
- The workload already had a substantial Railiance packaging surface.
|
||||
- The repo already distinguished the OpenBao workload from the wider S3
|
||||
platform policy that consumes it.
|
||||
- It proved that `rapp-*` is not only for user-facing apps.
|
||||
|
||||
What should move into `rapp-openbao`:
|
||||
|
||||
- Helm values and Kubernetes-facing package assets for the OpenBao workload
|
||||
- UI overlay wrapper assets
|
||||
- generic deploy, verify, and workload-health runbooks
|
||||
- workload-specific smoke and recovery expectations
|
||||
|
||||
What should remain in `railiance-platform`:
|
||||
|
||||
- the S3 ownership of secrets custody as a platform capability
|
||||
- workload lane policy, credential approval, and platform-wide access models
|
||||
- cross-workload secret-delivery conventions consumed by many workloads
|
||||
|
||||
Conclusion:
|
||||
|
||||
`rapp-openbao` should be the first `rapp-*` extraction.
|
||||
What stayed in `railiance-platform`: secrets custody as a platform
|
||||
capability, lane policy, credential approval, and cross-workload
|
||||
secret-delivery conventions.
|
||||
|
||||
### 2. Forge workload from `railiance-forge`
|
||||
|
||||
Assessment: **defer from first wave**
|
||||
Assessment then: **defer from first wave**. That deferral still holds as a
|
||||
first-wave fact, but the placement question is now closed. Decision
|
||||
`d151d817` puts the Forgejo workload in `rapp-forgejo` and the layer
|
||||
responsibility (runner placement and labels, registry retention, artifact
|
||||
lifecycle, package credentials) in S4 `railiance-enablement`.
|
||||
`railiance-forge` is placed, not retired. Gitea is confirmed replaced.
|
||||
|
||||
Why it is not first:
|
||||
|
||||
- The current live workload is still Gitea on CoulombCore.
|
||||
- The intended production direction is Forgejo on Railiance01.
|
||||
- Packaging identity is therefore not stable enough yet: extracting now would
|
||||
either enshrine a temporary Gitea compatibility package or pretend the
|
||||
Forgejo cutover is already complete.
|
||||
- The runtime and migration story still spans current Gitea operation, future
|
||||
Forgejo deployment, runner substrate, registries, and cutover sequencing.
|
||||
|
||||
Decision:
|
||||
|
||||
- Do **not** make the forge workload the first `rapp-*` extraction.
|
||||
- Prefer `rapp-forgejo` as the eventual target package once the production
|
||||
direction is the real operating target.
|
||||
- Create `rapp-gitea` only if Railiance discovers it needs a long-lived
|
||||
compatibility wrapper for the current workload rather than a short migration
|
||||
bridge.
|
||||
|
||||
What this means:
|
||||
|
||||
- `railiance-forge` keeps runtime ownership for now.
|
||||
- The forge wrapper should follow after the current Gitea-versus-Forgejo
|
||||
packaging identity stops moving.
|
||||
|
||||
Conclusion:
|
||||
|
||||
The forge workload is packaging-worthy, but it should not be first-wave
|
||||
`rapp-*`.
|
||||
`rapp-forgejo` is therefore a wave-2 package with a decided home, not an
|
||||
open placement debate.
|
||||
|
||||
### 3. User-facing S5 workload from `railiance-apps`
|
||||
|
||||
Assessment: **choose `vergabe-teilnahme` for wave 1**
|
||||
Assessment then: **choose `vergabe-teilnahme` for wave 1**. It was never
|
||||
built. The reasons it was the right user-facing slot remain: one named
|
||||
workload, explicit release surface, secret handling that is not entangled
|
||||
with shared platform semantics. That is why it is still the package that
|
||||
must prove the user-facing shape before mass extraction.
|
||||
|
||||
Why `vergabe-teilnahme` wins the S5 slot:
|
||||
`reuse-surface` remains the strongest follow-on self-built service
|
||||
candidate. `core-hub` should still wait.
|
||||
|
||||
- It is clearly user-facing and already operates as one named workload package.
|
||||
- Its release surface is explicit: chart, values, ingress, deployment targets,
|
||||
migration command, smoke checks, and operator runbook.
|
||||
- Secret handling is clear without being entangled with shared platform
|
||||
semantics: app credentials are consumed from Kubernetes Secrets and the app
|
||||
env secret is locally rebuilt by operator procedure.
|
||||
- It is simpler and more stable than the current Core Hub / Inter-Hub history
|
||||
and more obviously user-facing than service-style workloads such as
|
||||
`reuse-surface`.
|
||||
## Wave-2 Inventory
|
||||
|
||||
What should move into `rapp-vergabe-teilnahme`:
|
||||
Grouped by bounded context, in the composition shape from ADR-0007. These
|
||||
are indicative packages, not created repos. A package is listed only where
|
||||
members share rollout and rollback fate. Names that already exist as
|
||||
undeclared `rapp-*` repos are marked so they are not invented twice.
|
||||
|
||||
- the chart and workload values
|
||||
- the ingress and app-specific release runbook
|
||||
- workload-specific rollout, migration, smoke, and rollback guidance
|
||||
- workload-specific secret consumption contract
|
||||
### `rapp-vergabe-teilnahme` — prove the user-facing wrapper
|
||||
|
||||
What should remain in `railiance-apps`:
|
||||
```yaml
|
||||
composition:
|
||||
purpose: Package the Vergabe Teilnahme application as a managed user-facing workload.
|
||||
member_repos:
|
||||
- repo: vergabe-teilnahme
|
||||
role: application source and chart
|
||||
deployables: [vergabe-teilnahme]
|
||||
```
|
||||
|
||||
- S5 ownership of generic application release patterns
|
||||
- reusable onboarding and operator recipes
|
||||
- cross-app S5 guardrails that should not be duplicated per workload package
|
||||
Build this before any further user-facing extraction.
|
||||
|
||||
Second-wave S5 note:
|
||||
### `rapp-forgejo` — decided placement
|
||||
|
||||
- `reuse-surface` is the strongest follow-on self-built service candidate after
|
||||
`vergabe-teilnahme`, because it already shows explicit OpenBao-backed runtime
|
||||
secret lanes and a tidy single-workload chart surface.
|
||||
- `core-hub` and retired `inter-hub` should wait because their packaging
|
||||
history is still entangled with cutover and legacy service evolution.
|
||||
```yaml
|
||||
composition:
|
||||
purpose: Package Forgejo, its runner, and the package registry as one managed forge.
|
||||
member_repos:
|
||||
- repo: railiance-forge
|
||||
role: operational helm, manifests, runner, and registry assets
|
||||
deployables: [forgejo, forgejo-runner, forgejo-registry]
|
||||
```
|
||||
|
||||
Conclusion:
|
||||
Layer concerns stay in `railiance-enablement`. Do not create `rapp-gitea`.
|
||||
|
||||
`rapp-vergabe-teilnahme` should be the first user-facing S5 `rapp-*`.
|
||||
### `rapp-netkingdom-identity` — identity bounded context
|
||||
|
||||
## First-Wave Order
|
||||
```yaml
|
||||
composition:
|
||||
purpose: Package NetKingdom identity — users, tenants, SSO, MFA, and authorization — as one rollback unit.
|
||||
member_repos:
|
||||
- repo: user-engine
|
||||
role: user identity
|
||||
deployables: [user-engine]
|
||||
- repo: tenant-engine
|
||||
role: tenant identity
|
||||
deployables: [tenant-engine]
|
||||
- repo: key-cape
|
||||
role: SSO and MFA
|
||||
deployables: [keycloak]
|
||||
- repo: flex-auth
|
||||
role: authorization decisions
|
||||
deployables: [flex-auth]
|
||||
```
|
||||
|
||||
The recommended order is:
|
||||
`rapp-user-engine` and `rapp-tenant-engine` already exist as undeclared
|
||||
prefix claims. They are not separate rapps under grouped-by-bounded-context
|
||||
granularity. Their owners should either fold them into this package or
|
||||
justify an independent rollback fate and then declare them. `rapp-secrets-engine`
|
||||
is the same question against `rapp-openbao` / `railiance-platform`, not a
|
||||
fourth identity member.
|
||||
|
||||
1. `rapp-openbao`
|
||||
2. `rapp-vergabe-teilnahme`
|
||||
3. `rapp-forgejo` after the forge runtime target is stable enough to avoid
|
||||
immediate rename or migration churn
|
||||
### `rapp-coulomb-social`
|
||||
|
||||
This order is intentional.
|
||||
```yaml
|
||||
composition:
|
||||
purpose: Package the Coulomb Social application as a managed user-facing workload.
|
||||
member_repos:
|
||||
- repo: coulomb-social
|
||||
role: application
|
||||
deployables: [coulomb-social]
|
||||
```
|
||||
|
||||
- `rapp-openbao` proves the third-party platform-service wrapper model.
|
||||
- `rapp-vergabe-teilnahme` proves the self-built user-facing app wrapper model.
|
||||
- The forge wrapper then follows with a clearer target identity and after the
|
||||
first two wrappers have established the pattern.
|
||||
Do not start this until `rapp-vergabe-teilnahme` has proven the user-facing
|
||||
shape.
|
||||
|
||||
### `rapp-helix-forge`
|
||||
|
||||
```yaml
|
||||
composition:
|
||||
purpose: Package the Helix Forge methodological workspace as a managed workload.
|
||||
member_repos:
|
||||
- repo: helix-forge
|
||||
role: capability-first development ecosystem
|
||||
deployables: [helix-forge]
|
||||
```
|
||||
|
||||
Helix Forge is a different lineage from `railiance-forge`. It is not a
|
||||
rename of `rapp-forgejo`.
|
||||
|
||||
## Risks To Watch
|
||||
|
||||
- If `rapp-openbao` absorbs platform-wide policy and credential-governance
|
||||
logic, the wrapper will become a shadow S3 repo.
|
||||
- If `rapp-vergabe-teilnahme` absorbs generic S5 onboarding or app recipes, it
|
||||
will weaken `railiance-apps` as the shared S5 release home.
|
||||
- If the forge wrapper is extracted too early, Railiance will immediately face
|
||||
a Gitea-versus-Forgejo package rename or parallel-wrapper problem.
|
||||
logic, the wrapper becomes a shadow S3 repo.
|
||||
- If `rapp-postgres` is asked to mint the backup account, key, or bucket, a
|
||||
consumed destination is being mistaken for package ownership. The bucket
|
||||
is `resource-control` (`RESOURCE-WP-0002`); the credential is
|
||||
`railiance-platform` OpenBao custody; purchase is decision `9c21c0e0`.
|
||||
- If `rapp-vergabe-teilnahme` absorbs generic S5 onboarding, it weakens
|
||||
`railiance-apps`.
|
||||
- If the three undeclared engine repos are treated as rapps without a
|
||||
declaration, the coverage check cannot see them and will list their live
|
||||
deployables as uncovered.
|
||||
- If wave-2 extraction starts before the user-facing wrapper is proven,
|
||||
Railiance will mass-produce the platform-service shape and still not know
|
||||
whether the other shape works.
|
||||
|
||||
## Outcome
|
||||
|
||||
Railiance now has a concrete first-wave `rapp-*` sequence:
|
||||
|
||||
- first `rapp-openbao`
|
||||
- then `rapp-vergabe-teilnahme`
|
||||
- then the forge wrapper once the production package identity is stable
|
||||
|
||||
That is enough to start repo-local extraction planning without pretending every
|
||||
workload needs its own `rapp` immediately.
|
||||
Wave 1 proved the platform-service wrapper, twice, and did not prove the
|
||||
user-facing wrapper. The next package that must exist is
|
||||
`rapp-vergabe-teilnahme`. Everything else in the wave-2 inventory waits on
|
||||
that proof, on owner-side declaration of the three undeclared prefix
|
||||
claims, and on the schema migration owned by `RAILIANCE-WP-0015-T02`.
|
||||
|
|
|
|||
|
|
@ -65,54 +65,51 @@ described.
|
|||
|
||||
The first wave should standardize one obvious declaration path per repo family.
|
||||
|
||||
The field lists below are an index, not a specification. The JSON Schema for
|
||||
each family is normative. If this document and a schema disagree, the schema
|
||||
wins. Shapes, types, enums, and cardinality live in the schema files; do not
|
||||
restate them here.
|
||||
|
||||
### `rail-*`
|
||||
|
||||
Path:
|
||||
Path: `declarations/rail.yaml`
|
||||
|
||||
`declarations/rail.yaml`
|
||||
Schema: [`schemas/rail.schema.json`](../schemas/rail.schema.json)
|
||||
|
||||
Minimum fields:
|
||||
|
||||
- `rail_id`
|
||||
- `ownership_repo`
|
||||
- `execution_architecture`
|
||||
- `substrate_prerequisites`
|
||||
- `supported_rollout_modes`
|
||||
- `compatibility_notes`
|
||||
A rail is either `composition_kind: base` or `composition_kind: derived`.
|
||||
A derived rail names its base contract rather than copying it. See
|
||||
[`docs/rail-composition-contract.md`](rail-composition-contract.md) and
|
||||
ADR-0005. The live name for substrate needs is
|
||||
`required_substrate_capabilities`; the earlier `substrate_prerequisites`
|
||||
label is retired.
|
||||
|
||||
### `rapp-*`
|
||||
|
||||
Path:
|
||||
Path: `declarations/rapp.yaml`
|
||||
|
||||
`declarations/rapp.yaml`
|
||||
Schema: [`schemas/rapp.schema.json`](../schemas/rapp.schema.json)
|
||||
|
||||
Minimum fields:
|
||||
A rapp is a composition: a stated purpose, first-party member repos, and
|
||||
pinned third-party components. Repos to rapps is many-to-many; deployables
|
||||
to rapps is one-to-one. See ADR-0007. `bound_reefs` is how a rapp names the
|
||||
reefs it is placed on; that field is the source of a reef's `bound_rapps`.
|
||||
|
||||
- `rapp_id`
|
||||
- `workload_identity`
|
||||
- `ownership_repo`
|
||||
- `supported_rails`
|
||||
- `runtime_dependencies`
|
||||
- `rollout_contract`
|
||||
- `smoke_contract`
|
||||
- `rollback_contract`
|
||||
`runtime_dependencies` names capabilities, not the resources that satisfy
|
||||
them. Who provisions a capability (for example the postgres backup object
|
||||
store) is owned outside the rapp: the bucket by `resource-control`, the
|
||||
credential by `railiance-platform`. The rapp consumes a reviewed destination.
|
||||
|
||||
### `reef-*`
|
||||
|
||||
Path:
|
||||
Path: `declarations/reef.yaml`
|
||||
|
||||
`declarations/reef.yaml`
|
||||
Schema: [`schemas/reef.schema.json`](../schemas/reef.schema.json)
|
||||
|
||||
Minimum fields:
|
||||
|
||||
- `reef_id`
|
||||
- `substrate_kind`
|
||||
- `ownership_repo`
|
||||
- `lifecycle_state`
|
||||
- `criticality`
|
||||
- `hosted_rails`
|
||||
- `bound_rapps`
|
||||
- `primary_rail`
|
||||
`bound_rapps` is a derived projection of every rapp whose `bound_reefs`
|
||||
lists this reef. It is not a hand-maintained registry. A reef may omit the
|
||||
field; if it keeps the field, the validator requires an exact match against
|
||||
the projection. `primary_rail` must appear in `hosted_rails`. Hosting a rail
|
||||
or binding a rapp is topology, not readiness — see ADR-0006.
|
||||
|
||||
## Required Boundary Rules
|
||||
|
||||
|
|
@ -145,20 +142,11 @@ defined in `railiance-master`.
|
|||
|
||||
## First-Wave Candidates
|
||||
|
||||
The first materialization wave should target:
|
||||
|
||||
- `rail-kubernetes`
|
||||
- `rapp-openbao`
|
||||
- `reef-railiance`
|
||||
|
||||
The follow-on first-wave candidates after those anchors are stable:
|
||||
|
||||
- `rapp-vergabe-teilnahme`
|
||||
- `reef-coulombcore`
|
||||
- `reef-ops-workstations`
|
||||
|
||||
This keeps the first concrete rollout narrow while still covering all three new
|
||||
repo families.
|
||||
The planned first materialization wave was `rail-kubernetes`, `rapp-openbao`,
|
||||
`reef-railiance`, then `rapp-vergabe-teilnahme`. What was actually built, and
|
||||
the wave-2 inventory, is recorded in
|
||||
[`docs/rapp-first-wave-candidates.md`](rapp-first-wave-candidates.md). Do not
|
||||
restate that list here.
|
||||
|
||||
## Integration Expectations
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue