Establish Railiance architecture home
This commit is contained in:
parent
dd54aee0da
commit
8022665b35
22 changed files with 2925 additions and 1 deletions
133
docs/adr/ADR-0001-repository-prefix-architecture.md
Normal file
133
docs/adr/ADR-0001-repository-prefix-architecture.md
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# ADR-0001: Repository Prefix Architecture
|
||||
|
||||
Date: 2026-07-25
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Railiance already has a meaningful set of ownership repos such as
|
||||
`railiance-infra`, `railiance-cluster`, `railiance-platform`,
|
||||
`railiance-enablement`, `railiance-apps`, `railiance-forge`, and
|
||||
`railiance-fabric`.
|
||||
|
||||
That structure is useful, but it does not by itself capture all of the
|
||||
dimensions Railiance now needs.
|
||||
|
||||
In particular, the architecture needs clear source-controlled homes for:
|
||||
|
||||
- workload execution contracts across different operations architectures,
|
||||
- managed workload packages as first-class repos,
|
||||
- and concrete substrate boundaries such as named servers, workstations, or
|
||||
grouped environments.
|
||||
|
||||
Without that separation, Kubernetes-specific workload semantics remain mixed
|
||||
into `railiance-cluster`, workload wrappers remain mixed into ownership repos,
|
||||
and concrete substrates remain under-described.
|
||||
|
||||
Railiance also operates inside a wider ecosystem around Railiance, Net Kingdom,
|
||||
and the Helix Forge software factory. That wider context needs architecture
|
||||
that can support both exploratory operation and production-grade evolution
|
||||
without leaving key responsibilities ambiguous.
|
||||
|
||||
## Decision
|
||||
|
||||
Railiance adopts four canonical repository families:
|
||||
|
||||
1. `railiance-*` for ownership and responsibility areas
|
||||
2. `rail-*` for workload execution contracts
|
||||
3. `rapp-*` for Railiance-managed workload packages
|
||||
4. `reef-*` for durable substrate boundaries
|
||||
|
||||
The current implementation wave is explicitly centered on `rail-kubernetes` as
|
||||
the default base rail. Additional rails are introduced only when a concrete
|
||||
workload has a sound reason to run on a distinct execution architecture.
|
||||
|
||||
`rail-knative` is the first expected follow-on rail, motivated by the need to
|
||||
support `qonto-assistent`, but it should follow the `rail-kubernetes` boundary
|
||||
cleanup rather than bypass it.
|
||||
|
||||
## Meaning Of Each Family
|
||||
|
||||
### `railiance-*`
|
||||
|
||||
Owns major architectural responsibilities, shared policies, and durable layer
|
||||
boundaries.
|
||||
|
||||
### `rail-*`
|
||||
|
||||
Owns how workloads run on a specific execution architecture such as Kubernetes,
|
||||
Knative, KEDA, Fission, or Nuclio.
|
||||
|
||||
In the current phase, `rail-kubernetes` is the default path for platform
|
||||
services and managed applications.
|
||||
|
||||
### `rapp-*`
|
||||
|
||||
Owns the managed workload package for one service or application, whether it is
|
||||
an internal workload or a wrapped upstream product.
|
||||
|
||||
Its role is to provide the managed wrapper and scaffolding needed to run that
|
||||
workload in the Railiance and Net Kingdom context. It does not replace
|
||||
responsibility ownership.
|
||||
|
||||
### `reef-*`
|
||||
|
||||
Owns the concrete substrate reality where rails and `rapp`s are bound, such as
|
||||
a named server, cluster, workstation, or grouped substrate class.
|
||||
|
||||
A reef is about purpose-bound compute resources, not merely about individual
|
||||
machines.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Ownership, execution, workload identity, and substrate identity become
|
||||
separate concerns.
|
||||
- Railiance can support multiple execution architectures without forcing all
|
||||
workload semantics into `railiance-cluster`.
|
||||
- Platform services and applications can both become first-class managed
|
||||
workload packages where appropriate.
|
||||
- Concrete substrates gain a clear architectural home without overloading the
|
||||
ownership repos.
|
||||
- The framework gains a disciplined default path for introducing new rails
|
||||
instead of proliferating them speculatively.
|
||||
|
||||
### Required Follow-On Work
|
||||
|
||||
- Define the initial `rail-*` contracts, starting with `rail-kubernetes`.
|
||||
- Evolve the current `railiance/app.toml` and overlay pattern into a
|
||||
rail-aware, eventually rail-neutral workload packaging contract.
|
||||
- Identify which current workloads should become `rapp-*` repos.
|
||||
- Extend `railiance-fabric` so rails, `rapp`s, and reefs become graph-native.
|
||||
- Define when mixed-rail reefs are acceptable and when clearer substrate
|
||||
separation should be preferred.
|
||||
|
||||
### Constraints
|
||||
|
||||
- `reef-*` must not become a default one-repo-per-machine pattern.
|
||||
- Generic logic stays in the appropriate ownership repo.
|
||||
- A named machine gets its own reef only when that machine is itself a durable
|
||||
substrate boundary.
|
||||
- `rapp-*` repos must not become shadow ownership repos.
|
||||
- Transitional substrate labels should not be canonized before the pattern is
|
||||
operationally stable.
|
||||
|
||||
## Current Interpretation For Existing Repos
|
||||
|
||||
- `railiance-*` repos remain the primary ownership axis.
|
||||
- Current workload-execution logic in `railiance-cluster` is a candidate to
|
||||
migrate into `rail-kubernetes`.
|
||||
- Current workload wrappers inside `railiance-apps`, `railiance-platform`, or
|
||||
`railiance-forge` may evolve into `rapp-*` repos over time.
|
||||
- Current named substrates such as COULOMBCORE, RAILIANCE01, and WORKSTATION
|
||||
may justify `reef-*` repos when they represent real operational boundaries.
|
||||
- A reef may host more than one rail in early or mixed environments, but
|
||||
production-critical substrates should prefer clearer purpose and primary-rail
|
||||
boundaries unless a mixed design is justified.
|
||||
|
||||
## Notes
|
||||
|
||||
This ADR defines the repository taxonomy. It does not yet mandate a full
|
||||
migration or rename of existing repos. Migration should happen when it produces
|
||||
clearer ownership and lower ambiguity, not merely for naming purity.
|
||||
64
docs/adr/ADR-0002-rail-kubernetes-wave-1-boundary.md
Normal file
64
docs/adr/ADR-0002-rail-kubernetes-wave-1-boundary.md
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
# ADR-0002: Wave 1 `rail-kubernetes` Boundary
|
||||
|
||||
Date: 2026-07-25
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Railiance wants `rail-*` repos to represent workload execution contracts rather
|
||||
than abstract naming ideas.
|
||||
|
||||
Today, the concrete Kubernetes workload contract already exists, but it is
|
||||
embedded in `railiance-cluster`. That repo currently owns both:
|
||||
|
||||
- the S2 Kubernetes substrate
|
||||
- and the generic workload lifecycle and tooling that run on top of it
|
||||
|
||||
That mixed ownership is the main blocker to introducing the first real rail.
|
||||
|
||||
## Decision
|
||||
|
||||
Railiance will treat `rail-kubernetes` as the wave-1 base rail.
|
||||
|
||||
The boundary is:
|
||||
|
||||
- `railiance-cluster` owns the Kubernetes substrate and its prerequisites
|
||||
- `rail-kubernetes` owns the generic workload-on-Kubernetes execution contract
|
||||
|
||||
Workload-specific helper flows currently living in `railiance-cluster` are
|
||||
temporary exceptions and must be rehomed rather than carried forward as part of
|
||||
the generic rail.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- The first real rail gains a concrete ownership boundary.
|
||||
- `railiance-cluster` can return to a clean S2 substrate identity.
|
||||
- Future rails such as `rail-knative` get a stable base boundary to extend from.
|
||||
- `rapp-*` repos gain a clearer execution-contract home for Kubernetes-managed
|
||||
workloads.
|
||||
|
||||
### Required Follow-On Work
|
||||
|
||||
- Create the detailed `rail-kubernetes` boundary contract and migration map.
|
||||
- Split generic lifecycle docs, schema, examples, and Stage 1-3 tooling out of
|
||||
`railiance-cluster`.
|
||||
- Leave a compatibility path so current users of the cluster repo are not
|
||||
broken during the migration.
|
||||
- Rehome workload-specific helpers that do not belong in either boundary.
|
||||
|
||||
### Constraints
|
||||
|
||||
- `rail-kubernetes` must not take ownership of cluster bootstrap, operators, or
|
||||
kubeconfig management.
|
||||
- `railiance-cluster` must not continue as the owner of generic workload
|
||||
promotion semantics after the split.
|
||||
- `rail-knative` should follow this cleanup, not bypass it.
|
||||
|
||||
## Notes
|
||||
|
||||
This ADR does not require all current files to move immediately.
|
||||
|
||||
It requires the ownership line to be explicit now, so practical repo separation
|
||||
can proceed without ambiguity.
|
||||
57
docs/adr/ADR-0003-rapp-first-wave-selection.md
Normal file
57
docs/adr/ADR-0003-rapp-first-wave-selection.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# ADR-0003: First-Wave `rapp-*` Selection
|
||||
|
||||
Date: 2026-07-25
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Railiance wants `rapp-*` repos to represent managed workload packages rather
|
||||
than new ownership layers.
|
||||
|
||||
The current workload surfaces already suggest several candidates:
|
||||
|
||||
- OpenBao in `railiance-platform`
|
||||
- the forge workload in `railiance-forge`
|
||||
- multiple S5 workloads in `railiance-apps`
|
||||
|
||||
But they are not equally ready for first extraction.
|
||||
|
||||
## Decision
|
||||
|
||||
The first-wave `rapp-*` order is:
|
||||
|
||||
1. `rapp-openbao`
|
||||
2. `rapp-vergabe-teilnahme`
|
||||
3. later `rapp-forgejo` after the forge runtime target stabilizes
|
||||
|
||||
The forge workload is explicitly deferred from the first wave because current
|
||||
Gitea operation and future Forgejo direction are both active realities.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- The first `rapp-*` extraction proves the third-party platform-service wrapper
|
||||
model.
|
||||
- The second proves the user-facing self-built app wrapper model.
|
||||
- The deferred forge wrapper avoids immediate rename churn and packaging
|
||||
ambiguity.
|
||||
|
||||
### Required Follow-On Work
|
||||
|
||||
- Write repo-local extraction work for `rapp-openbao`.
|
||||
- Write repo-local extraction work for `rapp-vergabe-teilnahme`.
|
||||
- Reassess the forge wrapper when the production package target is no longer
|
||||
split between current Gitea and future Forgejo.
|
||||
|
||||
### Constraints
|
||||
|
||||
- `rapp-*` repos must stay packaging-focused and must not become shadow
|
||||
ownership repos.
|
||||
- Shared S3 policy stays in `railiance-platform`.
|
||||
- Shared S5 release patterns stay in `railiance-apps`.
|
||||
|
||||
## Notes
|
||||
|
||||
This ADR chooses sequence, not a mandatory destination for every workload in the
|
||||
ecosystem.
|
||||
61
docs/adr/ADR-0004-first-wave-reef-rollout.md
Normal file
61
docs/adr/ADR-0004-first-wave-reef-rollout.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# ADR-0004: First-Wave `reef-*` Rollout
|
||||
|
||||
Date: 2026-07-25
|
||||
Status: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
Railiance now has a reef model, but it needs a concrete first rollout.
|
||||
|
||||
The current substrate reality is not uniform:
|
||||
|
||||
- Railiance01 is the clearest new-workload home
|
||||
- CoulombCore is still active but transitional
|
||||
- the workstation role is operator edge compute rather than server substrate
|
||||
|
||||
At the same time, S1 ownership is ambiguous because `railiance-hosts` and
|
||||
`railiance-infra` duplicate each other.
|
||||
|
||||
## Decision
|
||||
|
||||
The first-wave reef rollout is:
|
||||
|
||||
1. `reef-railiance01`
|
||||
2. `reef-coulombcore`
|
||||
3. `reef-ops-workstations`
|
||||
|
||||
`railiance-infra` is the canonical S1 ownership repo going forward.
|
||||
|
||||
`railiance-hosts` is treated as predecessor or duplicate state to be retired,
|
||||
frozen, or reduced later rather than as a second canonical S1 architecture home.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Railiance gets a primary home-reef seed without waiting for a multi-node
|
||||
future.
|
||||
- Transitional CoulombCore reality is acknowledged without being treated as the
|
||||
long-term preferred production pattern.
|
||||
- Operator edge compute is modeled without defaulting to one repo per machine.
|
||||
- Reef planning now rests on one canonical S1 ownership line.
|
||||
|
||||
### Required Follow-On Work
|
||||
|
||||
- Create repo-local rollout work for the first reef repos.
|
||||
- Decide whether Railiance01 later remains a singleton reef or becomes part of
|
||||
a grouped home reef.
|
||||
- Plan the `railiance-hosts` cleanup direction relative to `railiance-infra`.
|
||||
|
||||
### Constraints
|
||||
|
||||
- Multi-rail reefs are acceptable early, especially on transitional substrates.
|
||||
- Production-grade separation should still prefer clearer purpose and primary
|
||||
rail boundaries as criticality rises.
|
||||
- Transitional substrate nicknames should remain provisional until the pattern
|
||||
is stable enough to canonize.
|
||||
|
||||
## Notes
|
||||
|
||||
This ADR chooses the first rollout set. It does not require that every future
|
||||
substrate be modeled the same way.
|
||||
187
docs/fabric-state-hub-adaptation.md
Normal file
187
docs/fabric-state-hub-adaptation.md
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
# Fabric And State Hub Adaptation For `rail-*`, `rapp-*`, And `reef-*`
|
||||
|
||||
Date: 2026-07-25
|
||||
|
||||
## Purpose
|
||||
|
||||
List the minimum adaptation requirements so rails, `rapp`s, and reefs become
|
||||
visible ecosystem entities rather than only naming conventions.
|
||||
|
||||
This is a requirements document, not an implementation plan for one repo.
|
||||
|
||||
## Current Gaps
|
||||
|
||||
The current ecosystem tooling still reflects the older repo shape.
|
||||
|
||||
Observed gaps:
|
||||
|
||||
- `railiance-fabric/registry/railiance-repos.yaml` does not yet onboard
|
||||
`railiance-master` or `railiance-forge`.
|
||||
- Fabric has a `kubernetes-runtime` capability type, but no first-class
|
||||
vocabulary for execution rails, managed workload packages, or substrate
|
||||
boundaries.
|
||||
- `railiance-apps` is modeled as one aggregate S5 release surface rather than a
|
||||
future set of `rapp-*` package repos.
|
||||
- State Hub registration and generated repo summaries do not expose repo family
|
||||
or rail/rapp/reef-specific metadata.
|
||||
|
||||
If left unchanged, Git will know the new taxonomy before the coordination and
|
||||
graph systems do.
|
||||
|
||||
## Minimum Questions The Systems Must Answer
|
||||
|
||||
After adaptation, the systems should be able to answer at least:
|
||||
|
||||
- which `rail-*` repos exist?
|
||||
- which rail is the default base rail?
|
||||
- which `rapp-*` packages support which rails?
|
||||
- which reefs host which rails?
|
||||
- which reefs bind or approve which `rapp`s?
|
||||
- which ownership repo remains responsible for a given rail, `rapp`, or reef?
|
||||
|
||||
## Minimal State Hub Requirements
|
||||
|
||||
State Hub does not need a second work-tracking model, but it does need better
|
||||
repo metadata.
|
||||
|
||||
### Required repo metadata
|
||||
|
||||
Add or derive the following repo-level concepts:
|
||||
|
||||
- `repo_family`: `ownership` | `rail` | `rapp` | `reef`
|
||||
- `ownership_repo`: canonical owning `railiance-*` repo when the repo family is
|
||||
not `ownership`
|
||||
- `primary_rail`: for reefs or workloads where one rail is the declared default
|
||||
- `supported_rails`: for `rapp-*` repos
|
||||
- `substrate_kind`: for `reef-*` repos, such as `server`, `cluster`,
|
||||
`workstation-group`, or `edge`
|
||||
|
||||
These fields may start in `.repo-classification.yaml` or a repo-local
|
||||
companion metadata file if the classification schema should stay smaller.
|
||||
|
||||
### Required indexing behavior
|
||||
|
||||
- State Hub should index `rail-*`, `rapp-*`, and `reef-*` repos like any other
|
||||
repo for workplans, tasks, and progress.
|
||||
- Generated repo briefs should display repo family and any declared ownership
|
||||
repo or primary rail when available.
|
||||
- Repo search and inventory views should be filterable by repo family.
|
||||
|
||||
### Not required
|
||||
|
||||
- no separate workplan model for rails, `rapp`s, or reefs
|
||||
- no special task state machine
|
||||
- no custom approval workflow just because a repo uses one of the new prefixes
|
||||
|
||||
## Minimum Fabric Requirements
|
||||
|
||||
Fabric needs enough typed vocabulary to model the new repo families without
|
||||
waiting for a perfect new object taxonomy.
|
||||
|
||||
### Immediate onboarding requirements
|
||||
|
||||
- add `railiance-master` to `registry/railiance-repos.yaml`
|
||||
- add `railiance-forge` to `registry/railiance-repos.yaml`
|
||||
- be ready to add future `rail-*`, `rapp-*`, and `reef-*` repos as first-class
|
||||
registered repositories
|
||||
|
||||
### Immediate modeling requirements
|
||||
|
||||
Fabric should add typed representation for:
|
||||
|
||||
- execution rails
|
||||
- managed workload packages
|
||||
- substrate boundaries
|
||||
|
||||
The minimum viable way to do that is:
|
||||
|
||||
- add repo-family-aware metadata in registration and graph export
|
||||
- add new `service_type` values:
|
||||
- `execution-rail`
|
||||
- `managed-workload-package`
|
||||
- `substrate-boundary`
|
||||
- add one new capability type for rails:
|
||||
- `workload-execution-contract`
|
||||
|
||||
This keeps the first rail queryable as a provider-like ecosystem object without
|
||||
forcing `rapp`s and reefs into the wrong provider/consumer semantics.
|
||||
|
||||
### Relation requirements
|
||||
|
||||
Fabric needs explicit relations for:
|
||||
|
||||
- `supports_rail`: `rapp` -> `rail`
|
||||
- `hosts_rail`: reef -> `rail`
|
||||
- `binds_rapp`: reef -> `rapp`
|
||||
- `governed_by`: rail/`rapp`/reef -> ownership repo
|
||||
|
||||
These relations may begin as projected registry edges even if the declaration
|
||||
schema evolves later.
|
||||
|
||||
The important part is that the graph can answer the topology questions above.
|
||||
|
||||
## Minimum Repo-Local Declaration Requirements
|
||||
|
||||
Every future repo family needs a small, obvious declaration surface.
|
||||
|
||||
### `rail-*`
|
||||
|
||||
Minimum declaration concepts:
|
||||
|
||||
- rail id
|
||||
- owning repo
|
||||
- execution architecture
|
||||
- substrate prerequisites
|
||||
- supported rollout modes
|
||||
- compatibility notes for participating `rapp`s
|
||||
|
||||
### `rapp-*`
|
||||
|
||||
Minimum declaration concepts:
|
||||
|
||||
- workload package id
|
||||
- upstream or source workload identity
|
||||
- owning repo
|
||||
- supported rails
|
||||
- runtime dependencies
|
||||
- rollout, smoke, and rollback contract
|
||||
|
||||
### `reef-*`
|
||||
|
||||
Minimum declaration concepts:
|
||||
|
||||
- substrate id
|
||||
- substrate kind
|
||||
- lifecycle and criticality
|
||||
- hosted rails
|
||||
- bound or approved `rapp`s
|
||||
- primary rail, if one exists
|
||||
|
||||
These declarations may begin as repo-local YAML files or be projected from
|
||||
existing source files. The key requirement is that they are source-controlled
|
||||
and ingestible.
|
||||
|
||||
## Compatibility Guidance
|
||||
|
||||
Do not block the repo-family rollout on a perfect Fabric redesign.
|
||||
|
||||
Recommended compatibility-first path:
|
||||
|
||||
1. register the repos and family metadata
|
||||
2. add the minimum new service and relation vocabulary
|
||||
3. let the first `rail-*`, `rapp-*`, and `reef-*` repos publish small
|
||||
declaration files
|
||||
4. ingest those declarations into Fabric and State Hub projections
|
||||
5. only then decide whether stronger first-class schema kinds are needed
|
||||
|
||||
This avoids waiting for a large graph refactor before the architecture can move.
|
||||
|
||||
## Outcome
|
||||
|
||||
The minimal adaptation target is:
|
||||
|
||||
- State Hub understands which repo family a repo belongs to
|
||||
- Fabric can show rails, `rapp`s, and reefs as typed ecosystem entities
|
||||
- the graph can answer rail/package/substrate placement questions
|
||||
- new repo families are coordinated by the same workplan and progress system as
|
||||
the existing Railiance repos
|
||||
200
docs/rail-kubernetes-boundary.md
Normal file
200
docs/rail-kubernetes-boundary.md
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
# Wave 1 `rail-kubernetes` Boundary
|
||||
|
||||
Date: 2026-07-25
|
||||
|
||||
## Purpose
|
||||
|
||||
Define the wave-1 extraction boundary between `railiance-cluster` and a future
|
||||
`rail-kubernetes` repo.
|
||||
|
||||
This document exists to make `rail-kubernetes` real rather than rhetorical.
|
||||
Today, `railiance-cluster` already contains the practical contract for running
|
||||
managed workloads on Kubernetes:
|
||||
|
||||
- `docs/deployment-lifecycle.md`
|
||||
- `docs/app-toml-contract.md`
|
||||
- `docs/overlay-repo-pattern.md`
|
||||
- `schemas/railiance-app.schema.json`
|
||||
- `examples/railiance/app.toml`
|
||||
- `bin/railiance`
|
||||
- `tools/cmd/railiance-run`
|
||||
- `tools/cmd/railiance-stage2`
|
||||
- `tools/cmd/railiance-stage3`
|
||||
- `tools/create_railiance_overlay_repo.sh`
|
||||
|
||||
That is already a rail in substance. The problem is that it currently lives
|
||||
inside the S2 cluster-runtime repo.
|
||||
|
||||
## Decision Summary
|
||||
|
||||
- `rail-kubernetes` is the default base rail for wave 1.
|
||||
- `railiance-cluster` remains the S2 owner of the Kubernetes substrate.
|
||||
- `rail-kubernetes` owns the generic workload-on-Kubernetes execution contract.
|
||||
- Workload-specific helpers currently living in `railiance-cluster` are not
|
||||
part of the long-term boundary for either repo. They are migration debt that
|
||||
must be rehomed.
|
||||
|
||||
## What `railiance-cluster` Keeps
|
||||
|
||||
`railiance-cluster` remains responsible for the Kubernetes substrate itself.
|
||||
|
||||
It keeps ownership of:
|
||||
|
||||
- k3s installation, upgrade, and baseline configuration
|
||||
- cluster networking, ingress controllers, DNS, and certificate plumbing
|
||||
- cluster operators and addons such as cert-manager, CloudNative PG operator,
|
||||
ArgoCD, admission controllers, and similar cluster-scoped services
|
||||
- kubeconfig management, runtime access patterns, and cluster backup/restore
|
||||
posture
|
||||
- cluster smoke tests that prove substrate readiness
|
||||
- cluster-level runbooks for substrate recovery, upgrade, access, and failure
|
||||
handling
|
||||
- cluster capability declarations that tell higher layers what the substrate
|
||||
actually supports
|
||||
|
||||
`railiance-cluster` may describe the prerequisites a rail needs from the
|
||||
substrate, but it should not own the workload lifecycle semantics that run on
|
||||
top of those prerequisites.
|
||||
|
||||
## What `rail-kubernetes` Must Own
|
||||
|
||||
`rail-kubernetes` owns the generic contract for Railiance-managed workloads
|
||||
that run on Kubernetes.
|
||||
|
||||
It should own:
|
||||
|
||||
- the three-stage lifecycle semantics for Kubernetes-backed workloads
|
||||
- the canonical `railiance/app.toml` contract for the Kubernetes rail
|
||||
- the machine-readable schema and reference example for that contract
|
||||
- the generic Stage 1, Stage 2, and Stage 3 CLI/tooling
|
||||
- Kubernetes-specific check types, rollout modes, and rollback expectations
|
||||
- the generic packaging pattern for Kubernetes-managed `rapp`s
|
||||
- the generic repo scaffold for Kubernetes-targeting wrappers
|
||||
- compatibility guidance for how a `rapp` declares Kubernetes namespaces,
|
||||
releases, probes, ingress, routing, and rollback
|
||||
- the documented compatibility path from today's overlay pattern into future
|
||||
`rapp-*` repos
|
||||
|
||||
In short:
|
||||
|
||||
- `railiance-cluster` answers "is the Kubernetes substrate present and healthy?"
|
||||
- `rail-kubernetes` answers "how does a Railiance-managed workload run on that
|
||||
substrate?"
|
||||
|
||||
## What Should Not Stay In Either Boundary
|
||||
|
||||
Some items currently inside `railiance-cluster` are not good long-term
|
||||
residents of either `railiance-cluster` or the future `rail-kubernetes`.
|
||||
|
||||
Examples include workload-specific helpers such as:
|
||||
|
||||
- `deploy-triage-robustness`
|
||||
- `admin-sync-smoke`
|
||||
- workload-specific runtime reconcile flows tied to `activity-core` or similar
|
||||
single-workload concerns
|
||||
|
||||
These belong with the owning workload or ownership repo unless they are
|
||||
refactored into clearly generic rail behavior.
|
||||
|
||||
`rail-kubernetes` must not become a second junk drawer after the split.
|
||||
|
||||
## File And Artifact Migration Map
|
||||
|
||||
| Current location in `railiance-cluster` | Target owner | Notes |
|
||||
| --- | --- | --- |
|
||||
| `docs/deployment-lifecycle.md` | `rail-kubernetes` | Generic workload lifecycle, no longer S2-owned |
|
||||
| `docs/app-toml-contract.md` | `rail-kubernetes` | Base rail contract for Kubernetes-managed workloads |
|
||||
| `schemas/railiance-app.schema.json` | `rail-kubernetes` | Versioned workload declaration schema |
|
||||
| `examples/railiance/app.toml` | `rail-kubernetes` | Reference contract example |
|
||||
| `docs/overlay-repo-pattern.md` | `rail-kubernetes` | Keep as compatibility doc, evolve toward `rapp-*` language |
|
||||
| `tools/create_railiance_overlay_repo.sh` | `rail-kubernetes` | Keep behavior initially, then retarget toward `rapp-*` scaffolding |
|
||||
| `docs/railiance-run-command.md` | `rail-kubernetes` | Stage 1 command reference |
|
||||
| `docs/stage2-deploy-observe.md` | `rail-kubernetes` | Stage 2 command reference |
|
||||
| `tools/cmd/railiance-run` | `rail-kubernetes` | Generic Stage 1 tooling |
|
||||
| `tools/cmd/railiance-stage2` | `rail-kubernetes` | Generic Stage 2 tooling |
|
||||
| `tools/cmd/railiance-stage3` | `rail-kubernetes` | Generic Stage 3 tooling |
|
||||
| `bin/railiance` generic lifecycle commands | `rail-kubernetes` | `run`, `deploy`, `observe`, `promote`, `rollback`, `create-overlay` |
|
||||
| `bin/railiance` substrate/bootstrap commands | `railiance-cluster` | `doctor`, `plan-host`, `cloudinit`, `backup`, `preflight`, similar substrate helpers |
|
||||
| `tests/smoke_kube.sh`, cluster bootstrap tests | `railiance-cluster` | Substrate health proof |
|
||||
| workload-specific reconcile helpers | rehome later | Move to owner repo or rewrite as generic rail helpers |
|
||||
|
||||
## The Interface Between The Two Repos
|
||||
|
||||
The clean split depends on a narrow interface.
|
||||
|
||||
`railiance-cluster` should publish a Kubernetes substrate profile that
|
||||
`rail-kubernetes` can consume. At minimum, that profile should declare:
|
||||
|
||||
- cluster distro and supported Kubernetes version range
|
||||
- ingress controller and ingress classes
|
||||
- supported canary modes, such as `isolated` and optional `weighted`
|
||||
- certificate management path
|
||||
- default storage classes and stateful-workload constraints
|
||||
- required or optional operators available to workloads
|
||||
- namespace and RBAC expectations for managed workloads
|
||||
- observability surfaces available for health, logs, and metrics
|
||||
- approved secret-delivery patterns available on this substrate
|
||||
|
||||
`rail-kubernetes` should not assume a capability the substrate profile does not
|
||||
declare.
|
||||
|
||||
This keeps the substrate owner and the rail owner separate while still letting
|
||||
them compose.
|
||||
|
||||
## Migration-Safe Path
|
||||
|
||||
The split should happen in six steps.
|
||||
|
||||
1. Create `rail-kubernetes` with the copied contract docs, schema, examples,
|
||||
and generic Stage 1-3 tooling now living in `railiance-cluster`.
|
||||
2. Leave compatibility shims in `railiance-cluster` for one migration window.
|
||||
The cluster repo may keep a thin `bin/railiance` wrapper that delegates the
|
||||
generic lifecycle commands to `rail-kubernetes`.
|
||||
3. Update the moved docs in `railiance-cluster` to become short boundary notes
|
||||
that point to `rail-kubernetes` as the owning source.
|
||||
4. Keep accepting the current `<app>-railiance-overlay` pattern during the
|
||||
migration window, even though the long-term direction is toward `rapp-*`.
|
||||
5. Rehome or delete workload-specific helpers that do not belong in either the
|
||||
substrate repo or the generic Kubernetes rail.
|
||||
6. Only after `rail-kubernetes` is stable should Railiance add `rail-knative`.
|
||||
|
||||
This path avoids breaking current users while making the new boundary real.
|
||||
|
||||
## Follow-On Path For `rail-knative`
|
||||
|
||||
`rail-knative` is the first expected follow-on rail, motivated by the need to
|
||||
run `qonto-assistent`.
|
||||
|
||||
That follow-on rail should:
|
||||
|
||||
- depend on the Kubernetes substrate being described cleanly first
|
||||
- reuse the top-level Railiance workload and promotion model where that remains
|
||||
sensible
|
||||
- own Knative-specific runtime semantics such as revisions, scale-to-zero,
|
||||
traffic splitting, activator behavior, and event-driven behavior
|
||||
- avoid forcing Knative-specific design choices back into the wave-1
|
||||
`rail-kubernetes` boundary
|
||||
|
||||
The test for wave 1 is not "can Railiance describe all future rails now?"
|
||||
|
||||
The test is "can Railiance separate the Kubernetes base rail cleanly enough
|
||||
that `rail-knative` can be added later without another taxonomy rewrite?"
|
||||
|
||||
## Risks To Watch
|
||||
|
||||
- If `railiance-cluster` keeps generic workload lifecycle ownership,
|
||||
`rail-kubernetes` will be nominal only.
|
||||
- If `rail-kubernetes` absorbs substrate bootstrap and operator ownership, it
|
||||
stops being a rail and becomes a second cluster repo.
|
||||
- If workload-specific helpers are moved unchanged into `rail-kubernetes`, the
|
||||
split will preserve the current ambiguity instead of reducing it.
|
||||
- If `rapp-*` migration is delayed too long, the old overlay naming and the new
|
||||
workload-package model will drift apart.
|
||||
|
||||
## Outcome
|
||||
|
||||
Wave 1 should produce a base Kubernetes rail with a clean contract and a
|
||||
backward-compatible migration path.
|
||||
|
||||
That is enough to start practical repo separation without pretending the rest
|
||||
of the rail family already exists.
|
||||
169
docs/rapp-first-wave-candidates.md
Normal file
169
docs/rapp-first-wave-candidates.md
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
# First-Wave `rapp-*` Candidates
|
||||
|
||||
Date: 2026-07-25
|
||||
|
||||
## Purpose
|
||||
|
||||
Choose and order the first `rapp-*` candidates for Railiance.
|
||||
|
||||
`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?"
|
||||
|
||||
## Selection Criteria
|
||||
|
||||
The first-wave candidates should satisfy most of the following:
|
||||
|
||||
- stable workload identity
|
||||
- clear upstream or source workload boundary
|
||||
- clear Kubernetes package surface already visible in Git
|
||||
- explicit runtime-secret and dependency handling
|
||||
- deploy, verify, and recover behavior already described
|
||||
- low ambiguity between packaging ownership and domain ownership
|
||||
- good demonstration value for later `rapp-*` extractions
|
||||
|
||||
## Assessed Candidates
|
||||
|
||||
### 1. OpenBao from `railiance-platform`
|
||||
|
||||
Assessment: **choose first**
|
||||
|
||||
Why it fits:
|
||||
|
||||
- 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.
|
||||
|
||||
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.
|
||||
|
||||
### 2. Forge workload from `railiance-forge`
|
||||
|
||||
Assessment: **defer from first wave**
|
||||
|
||||
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-*`.
|
||||
|
||||
### 3. User-facing S5 workload from `railiance-apps`
|
||||
|
||||
Assessment: **choose `vergabe-teilnahme` for wave 1**
|
||||
|
||||
Why `vergabe-teilnahme` wins the S5 slot:
|
||||
|
||||
- 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`.
|
||||
|
||||
What should move into `rapp-vergabe-teilnahme`:
|
||||
|
||||
- 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
|
||||
|
||||
What should remain in `railiance-apps`:
|
||||
|
||||
- S5 ownership of generic application release patterns
|
||||
- reusable onboarding and operator recipes
|
||||
- cross-app S5 guardrails that should not be duplicated per workload package
|
||||
|
||||
Second-wave S5 note:
|
||||
|
||||
- `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.
|
||||
|
||||
Conclusion:
|
||||
|
||||
`rapp-vergabe-teilnahme` should be the first user-facing S5 `rapp-*`.
|
||||
|
||||
## First-Wave Order
|
||||
|
||||
The recommended order is:
|
||||
|
||||
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
|
||||
|
||||
This order is intentional.
|
||||
|
||||
- `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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
183
docs/reef-first-wave-rollout.md
Normal file
183
docs/reef-first-wave-rollout.md
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
# First-Wave `reef-*` Rollout
|
||||
|
||||
Date: 2026-07-25
|
||||
|
||||
## Purpose
|
||||
|
||||
Apply the `reef-*` model to the current Railiance substrate reality and choose
|
||||
the first actual reef rollout.
|
||||
|
||||
This document intentionally decides both:
|
||||
|
||||
- which reefs should exist first
|
||||
- and which current repo should remain the canonical S1 ownership home while
|
||||
reefs are introduced
|
||||
|
||||
## Current Substrate Reality
|
||||
|
||||
Railiance currently has three clearly different substrate realities:
|
||||
|
||||
### `RAILIANCE01`
|
||||
|
||||
- HostEurope server at `92.205.62.239`
|
||||
- the most mature current home for new Kubernetes-first workloads
|
||||
- already hosts Forgejo and overlapping platform services
|
||||
- likely seed of a future multi-server Railiance home substrate
|
||||
|
||||
### `COULOMBCORE`
|
||||
|
||||
- HostEurope server at `92.205.130.254`
|
||||
- older, mixed-purpose, still actively used
|
||||
- retains current Gitea fallback and other legacy or transitional runtime
|
||||
realities
|
||||
- not yet fully integrated into the newer operating model
|
||||
|
||||
### operator workstation
|
||||
|
||||
- edge/operator compute, not the same kind of substrate as the servers
|
||||
- hosts operator tools, local keys, bridges, kubeconfig usage, and attended
|
||||
control-plane work
|
||||
- likely to become a class of substrates rather than a forever-singleton machine
|
||||
|
||||
## Decision
|
||||
|
||||
The first-wave reef rollout is:
|
||||
|
||||
1. `reef-railiance01`
|
||||
2. `reef-coulombcore`
|
||||
3. `reef-ops-workstations`
|
||||
|
||||
Do **not** create `reef-workstation` as a singleton first-wave repo.
|
||||
|
||||
## Why These Three
|
||||
|
||||
### `reef-railiance01`
|
||||
|
||||
This should be the first canonical reef.
|
||||
|
||||
Why:
|
||||
|
||||
- it is already the clearest purpose-bound substrate
|
||||
- it is the default home for new Kubernetes-oriented Railiance workloads
|
||||
- it is the likely seed of the future Railiance home reef
|
||||
- its lifecycle, access path, and workload-placement decisions are already
|
||||
distinct enough to justify a dedicated reef
|
||||
|
||||
Primary rail stance:
|
||||
|
||||
- primary rail: `rail-kubernetes`
|
||||
- temporary multi-rail reality is acceptable here during early growth
|
||||
- later `rail-knative` may coexist on this reef if that is the most pragmatic
|
||||
path for early workloads such as `qonto-assistent`
|
||||
- if criticality or security pressure grows, reassess whether a broader grouped
|
||||
home reef or a rail-specific separation is required
|
||||
|
||||
### `reef-coulombcore`
|
||||
|
||||
This should exist, but explicitly as a transitional reef.
|
||||
|
||||
Why:
|
||||
|
||||
- COULOMBCORE is still a real operational boundary
|
||||
- it has its own access path, operational evidence, fallback responsibilities,
|
||||
and recovery decisions
|
||||
- it is exactly the kind of substrate that should be described honestly even if
|
||||
its long-term role is not yet clean
|
||||
|
||||
Interpretation:
|
||||
|
||||
- treat it as a mixed-purpose, legacy, or transition reef
|
||||
- allow multi-rail and compatibility realities here without pretending they are
|
||||
the preferred long-term production pattern
|
||||
- use the reef to make drain, cleanup, fallback, and migration decisions visible
|
||||
|
||||
Do not force a permanent taxonomy label such as "associate", "sidecar", or
|
||||
"comet" yet. Those labels may become useful later, but the operational pattern
|
||||
is not stable enough to canonize.
|
||||
|
||||
### `reef-ops-workstations`
|
||||
|
||||
Use a grouped reef for operator workstations.
|
||||
|
||||
Why:
|
||||
|
||||
- the workstation role is clearly a different substrate class from the servers
|
||||
- the machine count is likely to grow or vary over time
|
||||
- one repo per laptop would create exactly the duplication the reef model is
|
||||
supposed to prevent
|
||||
|
||||
Interpretation:
|
||||
|
||||
- treat current workstation reality as the first member of an operator/edge
|
||||
compute reef class
|
||||
- keep machine-specific details inside the reef topology, not in separate repos
|
||||
|
||||
## Singleton Versus Grouped Rule Applied
|
||||
|
||||
Applying the reef rules to the current hosts yields:
|
||||
|
||||
- `RAILIANCE01`: singleton reef now, because the machine itself is the current
|
||||
durable substrate boundary
|
||||
- `COULOMBCORE`: singleton reef now, because it remains an independent
|
||||
operational and fallback boundary
|
||||
- workstation: grouped reef, because the substrate concept is "operator edge
|
||||
compute" rather than one permanently special laptop
|
||||
|
||||
If Railiance01 later becomes one node in a clearly unified multi-node home
|
||||
substrate with shared lifecycle and placement policy, reassess whether the
|
||||
right target becomes a grouped reef such as `reef-railiance-home`.
|
||||
|
||||
Until then, `reef-railiance01` is the cleaner decision.
|
||||
|
||||
## `railiance-hosts` Versus `railiance-infra`
|
||||
|
||||
Current reality:
|
||||
|
||||
- `railiance-hosts` and `railiance-infra` are functionally duplicate S1 repos
|
||||
- both describe the same S1 provisioning and baseline responsibility
|
||||
- both contain the same authoritative-looking server inventory path
|
||||
- Fabric onboarding already uses `railiance-infra`
|
||||
|
||||
Decision:
|
||||
|
||||
- `railiance-infra` is the canonical S1 ownership repo going forward
|
||||
- `railiance-hosts` should be treated as a predecessor or migration duplicate,
|
||||
not as the long-term authority for new architecture work
|
||||
|
||||
What this means:
|
||||
|
||||
- new framework architecture should anchor on `railiance-infra`
|
||||
- reef introduction should not preserve the `hosts` naming line as a second S1
|
||||
authority
|
||||
- later cleanup should either retire `railiance-hosts` or reduce it to an
|
||||
explicit compatibility/archive role
|
||||
|
||||
## Practical Rollout Sequence
|
||||
|
||||
The reef rollout should happen in this order:
|
||||
|
||||
1. create `reef-railiance01` as the first canonical home reef seed
|
||||
2. create `reef-coulombcore` as the transitional legacy/fallback reef
|
||||
3. create `reef-ops-workstations` as the grouped operator-edge reef
|
||||
4. document `railiance-infra` as canonical S1 and plan the `railiance-hosts`
|
||||
retirement or freeze direction
|
||||
|
||||
## Risks To Watch
|
||||
|
||||
- If `reef-coulombcore` is described as if it were the preferred long-term
|
||||
production substrate, the reef model will normalize transitional mess instead
|
||||
of making it visible.
|
||||
- If `reef-workstation` is created first, the framework will drift toward
|
||||
one-repo-per-machine duplication.
|
||||
- If `railiance-hosts` and `railiance-infra` remain equally canonical, reef
|
||||
ownership will rest on an unstable S1 base.
|
||||
|
||||
## Outcome
|
||||
|
||||
Railiance now has a concrete first reef rollout:
|
||||
|
||||
- `reef-railiance01` as the primary home-reef seed
|
||||
- `reef-coulombcore` as the transitional legacy/fallback reef
|
||||
- `reef-ops-workstations` as the grouped operator-edge reef
|
||||
|
||||
That is enough to move from reef theory into practical repo planning.
|
||||
262
docs/reef-substrate-model.md
Normal file
262
docs/reef-substrate-model.md
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
# Reef Substrate Model
|
||||
|
||||
Date: 2026-07-25
|
||||
|
||||
## Definition
|
||||
|
||||
A `reef-*` repo is the conceptual home for one durable Railiance substrate
|
||||
boundary.
|
||||
|
||||
A reef is the place where:
|
||||
|
||||
- infrastructure becomes a named operational reality,
|
||||
- rails are installed or made available,
|
||||
- managed workloads are bound,
|
||||
- and operators interact with a concrete environment.
|
||||
|
||||
More concretely, a reef represents **compute resources organized for a defined
|
||||
purpose**.
|
||||
|
||||
The substrate may be:
|
||||
|
||||
- a single named server,
|
||||
- a cluster,
|
||||
- a workstation,
|
||||
- an edge site,
|
||||
- a lab substrate,
|
||||
- or a small fleet treated as one unit.
|
||||
|
||||
The important point is not the shape of the hardware. The important point is
|
||||
that the compute resources form one recognizable operational boundary.
|
||||
|
||||
## Why `reef-*` Instead Of `host-*`
|
||||
|
||||
`host-*` is too narrow for the intended concept.
|
||||
|
||||
Railiance substrates are not always just hosts. They may also be:
|
||||
|
||||
- operator workstations,
|
||||
- Kubernetes substrates,
|
||||
- serverless-capable execution surfaces,
|
||||
- grouped node fleets,
|
||||
- or mixed environments with both machines and control surfaces.
|
||||
|
||||
`reef-*` is useful because it names the substrate reality that rails attach to,
|
||||
not merely the hardware object underneath it.
|
||||
|
||||
## Core Responsibility Of A Reef
|
||||
|
||||
A reef repo should answer:
|
||||
|
||||
- What is this substrate called?
|
||||
- What components belong to it?
|
||||
- What access paths and operator assumptions apply?
|
||||
- Which rails exist here?
|
||||
- Which `rapp`s are allowed or deployed here?
|
||||
- Which overlays, exceptions, and evidence are specific to this substrate?
|
||||
|
||||
It should also make the substrate purpose explicit, so the existence of the
|
||||
reef is justified by its role rather than by a hostname alone.
|
||||
|
||||
It is therefore an environment or substrate boundary repo, not a generic
|
||||
infrastructure logic repo.
|
||||
|
||||
## What A Reef Owns
|
||||
|
||||
A reef repo may own:
|
||||
|
||||
- substrate identity and metadata
|
||||
- topology and membership description
|
||||
- rail bindings for this substrate
|
||||
- `rapp` bindings for this substrate
|
||||
- substrate-specific overlays and values
|
||||
- substrate-specific runbooks
|
||||
- substrate-specific evidence and readiness notes
|
||||
- access-path descriptions such as bridges, kubeconfig routes, or workstation
|
||||
assumptions
|
||||
|
||||
## What A Reef Does Not Own
|
||||
|
||||
A reef repo should not become the place for:
|
||||
|
||||
- generic OS provisioning logic that belongs in `railiance-infra`
|
||||
- generic cluster runtime logic that belongs in `railiance-cluster`
|
||||
- generic platform-service logic that belongs in `railiance-platform`
|
||||
- generic workload packaging that belongs in a `rapp-*` repo
|
||||
- generic rail semantics that belong in a `rail-*` repo
|
||||
|
||||
Reefs compose those concerns into a concrete substrate. They do not replace
|
||||
their owning repos.
|
||||
|
||||
## Granularity Rules
|
||||
|
||||
The main risk with reefs is repo explosion through near-duplicate per-machine
|
||||
repos. The default rules below are intended to prevent that.
|
||||
|
||||
### Rule 1: One Reef Per Substrate Boundary, Not Per Node By Default
|
||||
|
||||
If multiple machines form one operational substrate with the same lifecycle,
|
||||
access path, and overlays, prefer one reef.
|
||||
|
||||
Example:
|
||||
|
||||
- Prefer `reef-ops-workstations` over one repo per laptop if they are managed as
|
||||
one operator substrate class.
|
||||
|
||||
### Rule 2: A Single Machine Gets Its Own Reef Only When It Is The Boundary
|
||||
|
||||
A single named machine can justify its own reef when it is itself a durable
|
||||
substrate boundary.
|
||||
|
||||
This is reasonable when the machine has:
|
||||
|
||||
- unique operational identity,
|
||||
- unique overlays or access paths,
|
||||
- unique binding decisions,
|
||||
- or independent migration and recovery decisions.
|
||||
|
||||
### Rule 3: Group Fungible Fleets
|
||||
|
||||
Do not create one reef per fungible worker, node, or ephemeral instance.
|
||||
|
||||
Represent those inside one reef's topology instead.
|
||||
|
||||
### Rule 4: Prefer Stable Operational Names
|
||||
|
||||
A reef name should follow the durable substrate identity used by operators.
|
||||
|
||||
Good examples:
|
||||
|
||||
- `reef-coulombcore`
|
||||
- `reef-railiance01`
|
||||
- `reef-workstation`
|
||||
- `reef-ops-workstations`
|
||||
|
||||
Avoid names tied only to transient VM ids, cloud instance ids, or incidental
|
||||
hardware details.
|
||||
|
||||
### Rule 5: Allow Multi-Rail Reefs Early, Prefer Clearer Separation Later
|
||||
|
||||
It is acceptable for one reef to host multiple rails when the substrate is
|
||||
experimental, preproduction, prototyping, or otherwise intentionally mixed.
|
||||
|
||||
For production-grade, enterprise-grade, or premium-security situations, the
|
||||
better default is clearer separation by substrate purpose and a more explicit
|
||||
primary rail per reef unless there is a reviewed reason to mix rails.
|
||||
|
||||
This is guidance, not a hard prohibition. The point is to keep the substrate
|
||||
model operationally legible as criticality increases.
|
||||
|
||||
### Rule 6: Do Not Canonize Transitional Substrate Labels Too Early
|
||||
|
||||
Railiance may observe loosely planned or historically accumulated compute
|
||||
resources that are still in use but do not yet fit a clean substrate class.
|
||||
|
||||
Those realities should be described plainly in architecture notes or reef-local
|
||||
documents, but the taxonomy should avoid locking in catchy names before the
|
||||
operational pattern is mature enough to deserve a stable term.
|
||||
|
||||
## Guidance For Current Railiance Substrates
|
||||
|
||||
### `COULOMBCORE`
|
||||
|
||||
`reef-coulombcore` is reasonable if COULOMBCORE remains a durable singleton
|
||||
substrate with its own:
|
||||
|
||||
- access paths,
|
||||
- operational evidence,
|
||||
- rail availability,
|
||||
- and workload binding decisions.
|
||||
|
||||
It may also serve as the temporary home for older or transitional workloads
|
||||
that have not yet been integrated into newer operating patterns.
|
||||
|
||||
What should not be decided too early is a permanent taxonomy term for that
|
||||
kind of substrate. Terms such as "associate", "sidecar", or "comet" may be
|
||||
useful exploration language, but they should stay provisional until the pattern
|
||||
repeats and earns a stable place in the framework vocabulary.
|
||||
|
||||
### `RAILIANCE01`
|
||||
|
||||
`reef-railiance01` is reasonable if Railiance01 is separately managed, migrated,
|
||||
or recovered, rather than being just another fungible node in a larger
|
||||
substrate.
|
||||
|
||||
At the current maturity level, it is acceptable for `reef-railiance01` to host
|
||||
`rail-kubernetes` and later also `rail-knative` if that is the most pragmatic
|
||||
way to support early workloads.
|
||||
|
||||
If that substrate becomes production-critical or security-sensitive, reassess
|
||||
whether a clearer reef separation is warranted.
|
||||
|
||||
### `WORKSTATION`
|
||||
|
||||
If there is effectively one operator workstation with unique responsibility,
|
||||
`reef-workstation` is acceptable.
|
||||
|
||||
If Railiance expects multiple equivalent operator machines, prefer a grouped
|
||||
reef such as `reef-ops-workstations` and model individual machines inside that
|
||||
repo instead of multiplying repos.
|
||||
|
||||
This class of reef is best understood as edge or operator compute, not as part
|
||||
of the same substrate category as a home server reef.
|
||||
|
||||
## Suggested Reef Repo Layout
|
||||
|
||||
The exact layout can evolve, but a reef repo should have an obvious substrate
|
||||
home structure.
|
||||
|
||||
```text
|
||||
reef-<substrate-id>/
|
||||
README.md
|
||||
INTENT.md
|
||||
SCOPE.md
|
||||
substrate/
|
||||
identity.yaml
|
||||
topology.yaml
|
||||
bindings/
|
||||
rails.yaml
|
||||
rapps.yaml
|
||||
overlays/
|
||||
runbooks/
|
||||
evidence/
|
||||
```
|
||||
|
||||
Suggested file responsibilities:
|
||||
|
||||
- `substrate/identity.yaml`: substrate id, type, owner, lifecycle, criticality
|
||||
- `substrate/topology.yaml`: members, providers, network zones, access surfaces
|
||||
- `bindings/rails.yaml`: rails available on this substrate
|
||||
- `bindings/rapps.yaml`: `rapp`s bound or approved for this substrate
|
||||
- `overlays/`: substrate-specific values or adapter overlays
|
||||
- `runbooks/`: substrate-local operations and recovery
|
||||
- `evidence/`: substrate readiness, migration, or recovery evidence
|
||||
|
||||
## Relationship To Railiance Fabric
|
||||
|
||||
Reefs should become first-class graph objects in `railiance-fabric`.
|
||||
|
||||
At minimum, Fabric should eventually be able to answer:
|
||||
|
||||
- Which reefs provide `rail-kubernetes`?
|
||||
- Which reefs bind `rapp-openbao`?
|
||||
- Which reefs are production-critical?
|
||||
- Which rails are available on `reef-coulombcore`?
|
||||
- Which `rapp`s depend on a given reef?
|
||||
|
||||
Until Fabric gains first-class reef vocabulary, reef repos should still use
|
||||
clear file-backed declarations so later ingestion is straightforward.
|
||||
|
||||
## Recommended Decision
|
||||
|
||||
Adopt `reef-*` as the substrate-boundary prefix for Railiance.
|
||||
|
||||
Use it carefully:
|
||||
|
||||
- yes for real substrate boundaries,
|
||||
- no for arbitrary one-repo-per-machine duplication,
|
||||
- and yes for grouped substrate classes when that better matches operational
|
||||
reality.
|
||||
|
||||
Treat a reef as purpose-bound compute first. The exact machine count is
|
||||
secondary.
|
||||
254
docs/repository-axes.md
Normal file
254
docs/repository-axes.md
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
# Repository Axes In Railiance
|
||||
|
||||
Date: 2026-07-25
|
||||
|
||||
## Purpose
|
||||
|
||||
Railiance needs more than one way to classify repositories.
|
||||
|
||||
The existing stack already expresses ownership and responsibility well, but it
|
||||
does not yet cleanly express:
|
||||
|
||||
- how workloads are executed on different operations architectures,
|
||||
- how a managed workload package is represented as its own repo,
|
||||
- and how a concrete substrate or deployment reality is represented.
|
||||
|
||||
This document defines the canonical repository axes for Railiance.
|
||||
|
||||
## Current Architectural Stance
|
||||
|
||||
The taxonomy is intentionally broader than the current implementation wave.
|
||||
|
||||
For the current phase of Railiance:
|
||||
|
||||
- `rail-kubernetes` is the default and first-class base rail for platform
|
||||
services and managed applications.
|
||||
- Additional rails should be introduced only when a concrete workload has a
|
||||
sound reason to run better on a different execution architecture.
|
||||
- `rail-knative` is the first expected follow-on rail, driven by the need to
|
||||
run `qonto-assistent`, but it should follow the `rail-kubernetes` boundary
|
||||
cleanup rather than bypass it.
|
||||
|
||||
This means the repo model is intentionally ahead of the repo count.
|
||||
|
||||
## The Four Repo Families
|
||||
|
||||
| Prefix | Axis | Unit | Primary question answered |
|
||||
| --- | --- | --- | --- |
|
||||
| `railiance-*` | ownership and responsibility | one architectural responsibility area | who owns this capability or layer? |
|
||||
| `rail-*` | execution contract | one workload execution architecture | how does a workload run here? |
|
||||
| `rapp-*` | managed workload package | one Railiance-managed workload | what exactly is being packaged and operated? |
|
||||
| `reef-*` | substrate boundary | one durable substrate reality | where does this run and what is bound there? |
|
||||
|
||||
These families are complementary, not competing.
|
||||
|
||||
## 1. `railiance-*`: Responsibility Repos
|
||||
|
||||
`railiance-*` repos are the long-lived architectural homes for major
|
||||
responsibility areas.
|
||||
|
||||
Examples:
|
||||
|
||||
- `railiance-infra`
|
||||
- `railiance-cluster`
|
||||
- `railiance-platform`
|
||||
- `railiance-enablement`
|
||||
- `railiance-apps`
|
||||
- `railiance-forge`
|
||||
- `railiance-fabric`
|
||||
- `railiance-master`
|
||||
|
||||
They answer questions such as:
|
||||
|
||||
- Which layer owns this concern?
|
||||
- Where do the shared rules, runbooks, and contracts live?
|
||||
- Which team or operator domain is responsible for correctness?
|
||||
|
||||
They should not be multiplied per host, per workload, or per execution mode.
|
||||
|
||||
## 2. `rail-*`: Execution-Contract Repos
|
||||
|
||||
`rail-*` repos define how Railiance-managed workloads run on a specific
|
||||
operations architecture.
|
||||
|
||||
Examples:
|
||||
|
||||
- `rail-kubernetes`
|
||||
- `rail-knative`
|
||||
- `rail-keda`
|
||||
- `rail-fission`
|
||||
- `rail-nuclio`
|
||||
|
||||
A rail owns the execution semantics for workloads on that architecture:
|
||||
|
||||
- packaging expectations
|
||||
- deployment adapters
|
||||
- autoscaling and traffic behavior
|
||||
- health and observability contract
|
||||
- promotion and rollback behavior
|
||||
- rail-specific templates and compatibility rules
|
||||
|
||||
A rail is not the workload itself and not the substrate it runs on.
|
||||
|
||||
In the current Railiance model, `rail-kubernetes` is the default base rail.
|
||||
Other rails should be introduced only when their runtime semantics justify a
|
||||
distinct lifecycle, contract, or operator model.
|
||||
|
||||
That makes the first question for a new rail:
|
||||
|
||||
- does this workload truly need a different rail,
|
||||
- or does it only need an adapter or profile on the current Kubernetes path?
|
||||
|
||||
## 3. `rapp-*`: Managed Workload Package Repos
|
||||
|
||||
`rapp-*` repos represent Railiance-managed workloads as first-class packages.
|
||||
|
||||
Examples:
|
||||
|
||||
- `rapp-openbao`
|
||||
- `rapp-forgejo`
|
||||
- `rapp-vergabe-teilnahme`
|
||||
|
||||
A `rapp` may wrap:
|
||||
|
||||
- an upstream third-party product,
|
||||
- an internal service,
|
||||
- a user-facing application,
|
||||
- or a platform service operated as a workload.
|
||||
|
||||
Its purpose is to provide the scaffolding needed to run that workload as a
|
||||
fully managed component in the Railiance and Net Kingdom operating context,
|
||||
including the Helix Forge software-factory environment that produces and runs
|
||||
parts of that ecosystem.
|
||||
|
||||
A `rapp` owns:
|
||||
|
||||
- the Railiance packaging of the workload
|
||||
- rail compatibility declarations
|
||||
- workload-specific health checks and smoke checks
|
||||
- workload-specific rollout and rollback expectations
|
||||
- secret references, dependency declarations, and data handoff expectations
|
||||
|
||||
A `rapp` does not replace the responsibility repo that owns the broader domain.
|
||||
It is explicitly about managed wrapping, not ownership.
|
||||
|
||||
For example:
|
||||
|
||||
- `railiance-platform` may own why OpenBao exists as an S3 platform capability
|
||||
- `rapp-openbao` may own how OpenBao is packaged and operated as a managed workload
|
||||
|
||||
## 4. `reef-*`: Substrate-Boundary Repos
|
||||
|
||||
`reef-*` repos represent concrete substrate realities where rails and `rapp`s
|
||||
are bound.
|
||||
|
||||
Examples:
|
||||
|
||||
- `reef-coulombcore`
|
||||
- `reef-railiance01`
|
||||
- `reef-workstation`
|
||||
- `reef-ops-workstations`
|
||||
|
||||
A reef answers questions such as:
|
||||
|
||||
- What is this substrate?
|
||||
- Which hosts, clusters, namespaces, or operator machines compose it?
|
||||
- Which rails are installed or allowed here?
|
||||
- Which `rapp`s are bound to it?
|
||||
- Which access paths, overlays, and local runbooks apply here?
|
||||
|
||||
A reef does not replace `railiance-infra`, `railiance-cluster`, or
|
||||
`railiance-platform`. It composes them into a named operational reality.
|
||||
|
||||
In practice, a reef represents compute resources organized for a defined
|
||||
purpose.
|
||||
|
||||
One reef may host multiple rails in early-stage, experimental, prototyping, or
|
||||
preproduction situations. For production-grade or premium-security use, the
|
||||
better default is clearer substrate separation and an explicit primary rail per
|
||||
reef unless a mixed-rail design is deliberately justified.
|
||||
|
||||
## How The Axes Compose
|
||||
|
||||
The same deployed reality may appear across all four axes for different reasons.
|
||||
|
||||
Example: OpenBao on COULOMBCORE
|
||||
|
||||
- `railiance-platform` owns the platform-service responsibility and policy
|
||||
- `rail-kubernetes` defines the Kubernetes execution contract
|
||||
- `rapp-openbao` defines the managed workload package
|
||||
- `reef-coulombcore` records that this substrate offers that rail and binds that
|
||||
`rapp`
|
||||
|
||||
This separation reduces confusion between:
|
||||
|
||||
- ownership
|
||||
- execution mode
|
||||
- workload identity
|
||||
- deployment location
|
||||
|
||||
## Creation Rules
|
||||
|
||||
Use the following default rules.
|
||||
|
||||
### Create or extend a `railiance-*` repo when:
|
||||
|
||||
- the concern is a stable responsibility area,
|
||||
- multiple workloads share the same owner and policy boundary,
|
||||
- or the repo must remain the canonical home for a layer or cross-cutting
|
||||
capability.
|
||||
|
||||
### Create a `rail-*` repo when:
|
||||
|
||||
- a workload execution architecture has distinct runtime semantics,
|
||||
- workloads need architecture-specific templates or promotion behavior,
|
||||
- or the current `railiance-cluster` contract would become too Kubernetes-only.
|
||||
|
||||
Default bias:
|
||||
|
||||
- first stabilize `rail-kubernetes`
|
||||
- then add another rail only when a concrete workload needs it
|
||||
|
||||
### Create a `rapp-*` repo when:
|
||||
|
||||
- a workload should be managed as a first-class package,
|
||||
- the workload has its own compatibility, rollout, or recovery contract,
|
||||
- or wrapping logic should be kept separate from both the upstream source and
|
||||
the generic ownership repo.
|
||||
|
||||
Do not create a `rapp` merely to duplicate a responsibility home that already
|
||||
belongs in a `railiance-*` repo.
|
||||
|
||||
### Create a `reef-*` repo when:
|
||||
|
||||
- there is a durable substrate boundary with its own lifecycle,
|
||||
- rails and `rapp`s need to be bound to a named operational reality,
|
||||
- substrate-specific overlays or evidence must be tracked,
|
||||
- or operators need a source-controlled home for that environment.
|
||||
|
||||
Do not create a reef only because a single machine happens to exist. The
|
||||
substrate needs a durable purpose.
|
||||
|
||||
## Migration Direction From The Current Repo Set
|
||||
|
||||
The current Railiance repos already provide the ownership axis.
|
||||
|
||||
The likely next architecture moves are:
|
||||
|
||||
1. Move Kubernetes-specific workload execution contracts out of
|
||||
`railiance-cluster` into `rail-kubernetes`.
|
||||
2. Split first-class workload wrappers out of `railiance-apps`,
|
||||
`railiance-platform`, and `railiance-forge` into `rapp-*` repos where the
|
||||
workload deserves an independent lifecycle.
|
||||
3. Introduce `reef-*` repos only for real substrate boundaries, not as a
|
||||
default per-machine pattern.
|
||||
4. Extend `railiance-fabric` so rails, `rapp`s, and reefs become first-class
|
||||
graph objects rather than implicit naming conventions.
|
||||
|
||||
## Open Discipline
|
||||
|
||||
Railiance should resist naming every observed pattern too early.
|
||||
|
||||
This especially applies to loosely associated or transitional compute
|
||||
resources. Terms for such substrates should stay descriptive until there is a
|
||||
stable operational pattern worth canonizing in the taxonomy.
|
||||
Loading…
Add table
Add a link
Reference in a new issue