Establish Railiance architecture home

This commit is contained in:
codex 2026-07-25 10:54:37 +02:00
parent dd54aee0da
commit 8022665b35
22 changed files with 2925 additions and 1 deletions

20
.repo-classification.yaml Normal file
View file

@ -0,0 +1,20 @@
repo_classification:
standard: Repo Classification Standard
version: "1.0"
classified_at: "2026-07-25"
classified_by: agent
category: project
domain: financials
secondary_domains:
- infotech
capability_tags:
- platform
- governance
- documentation
- coordination
business_stake:
- technology
- operations
business_mechanics:
- coordination
- control

246
AGENTS.md Normal file
View file

@ -0,0 +1,246 @@
# railiance-master — Agent Instructions
## Repo Identity
**Purpose:** Railiance framework architecture home: repository taxonomy, architectural boundaries, framework-level ADRs, and cross-repo workplans for changes spanning multiple Railiance repositories.
**Domain:** financials
**Repo slug:** railiance-master
**Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38`
**Workplan prefix:** `RAILIANCE-WP-`
---
## State Hub Integration
The Custodian State Hub tracks work across all domains. Interact via HTTP REST —
there is no MCP server for Codex agents.
| Context | URL |
|---------|-----|
| Local workstation | `http://127.0.0.1:8000` |
| Remote via tunnel | `http://127.0.0.1:18000` |
| Optional local edge relay | `http://127.0.0.1:18080` |
When an operator has enabled the edge relay, set `API_BASE` to the relay URL.
Queueable writes return an explicit queued receipt if the central hub is
unreachable. Treat that as pending local evidence, then ask the operator to run
`statehub outbox status` or `statehub outbox replay` after connectivity returns.
### Orient at session start
```bash
# Offline brief — works without hub connection
cat .custodian-brief.md
# Active workplans for this domain
python3 - <<'PY'
import json, urllib.request
with urllib.request.urlopen("http://127.0.0.1:8000/workplans/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active") as r:
print(json.dumps(json.loads(r.read().decode()), indent=2))
PY
# Check inbox
python3 - <<'PY'
import json, urllib.request
with urllib.request.urlopen("http://127.0.0.1:8000/messages/?to_agent=railiance-master&unread_only=true") as r:
print(json.dumps(json.loads(r.read().decode()), indent=2))
PY
```
Mark a message read:
```bash
python3 - <<'PY'
import json, urllib.request
req = urllib.request.Request(
"http://127.0.0.1:8000/messages/<id>/read",
data=b"{}",
headers={"Content-Type": "application/json"},
method="PATCH",
)
with urllib.request.urlopen(req) as r:
print(r.read().decode())
PY
```
### Log progress (required at session close)
```bash
python3 - <<'PY'
import json, urllib.request
payload = {
"summary": "what was done",
"event_type": "note",
"author": "codex",
"workplan_id": "<uuid>",
"task_id": "<uuid>",
}
req = urllib.request.Request(
"http://127.0.0.1:8000/progress/",
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req) as r:
print(r.read().decode())
PY
```
Omit `workplan_id` or `task_id` when not applicable.
### Update task status
```bash
python3 - <<'PY'
import json, urllib.request
req = urllib.request.Request(
"http://127.0.0.1:8000/tasks/<task_id>",
data=json.dumps({"status": "progress"}).encode(),
headers={"Content-Type": "application/json"},
method="PATCH",
)
with urllib.request.urlopen(req) as r:
print(r.read().decode())
PY
# values: wait | todo | progress | done | cancel
```
### Flag a task for human review
```bash
python3 - <<'PY'
import json, urllib.request
req = urllib.request.Request(
"http://127.0.0.1:8000/tasks/<task_id>",
data=json.dumps({"needs_human": True, "intervention_note": "reason"}).encode(),
headers={"Content-Type": "application/json"},
method="PATCH",
)
with urllib.request.urlopen(req) as r:
print(r.read().decode())
PY
```
---
## Session Protocol
**Start:**
1. `cat .custodian-brief.md` — domain goal and open workplans (offline-safe)
2. Check inbox: `GET /messages/?to_agent=railiance-master&unread_only=true`; mark read
3. Scan `workplans/` — note `status: ready`, `active`, or `blocked` files and open tasks
4. Check human-needed tasks: `GET /tasks/?needs_human=true`
**During work:**
- Update task statuses in workplan files as tasks progress
- Record significant decisions via `POST /decisions/`
**Close:**
1. Update workplan file task statuses to reflect progress
2. If finishing a workplan: hand off residuals as live work records first
3. Log `POST /progress/` with a summary of what changed
4. After workplan file changes, run:
```bash
statehub fix-consistency
```
Coding agents should run this directly; ask the operator only if the CLI or
State Hub API is unavailable. This syncs task status from files into the hub DB.
---
## Credential and access routing
**Audience:** Codex, Claude Code, Grok, and custodian agents that call **llm-connect**
for inference. Run this check **before** requesting secrets, API keys, SSH access,
login tokens, or database passwords — in any repo, not only `ops-warden`.
`ops-warden` **issues SSH certificates only** (`warden sign`, `cert_command`).
Every other credential need belongs to another subsystem. Do not message
`ops-warden` on State Hub expecting a secret value; the reply is a pointer, not a key.
### Lookup
```bash
warden route find "<describe your need>" --json
warden route show <catalog-id> --json
```
Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run warden`).
### Quick routing table
| I need… | Owner | ops-warden executes? |
| --- | --- | --- |
| SSH cert (`adm`/`agt`/`atm`) | ops-warden | Yes — `warden sign` |
| API key, DB password, provider token | OpenBao (`railiance-platform`) | No — route only |
| Login / OIDC / MFA | key-cape / Keycloak | No — route only |
| Authorization decision | flex-auth | No — route only |
| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only |
### Anti-patterns
- `POST /messages/` to `ops-warden` asking for secret values
- inventing unsupported `warden` subcommands
- pasting secrets into Git, State Hub, workplans, logs, or chat
---
## Workplan Convention (ADR-001)
Work items originate as files in this repo — not in the hub. The hub is a
read/cache/index layer that rebuilds from files.
**File location:** `workplans/RAILIANCE-WP-NNNN-<slug>.md`
**Archived location:** finished workplans may move to
`workplans/archived/YYMMDD-RAILIANCE-WP-NNNN-<slug>.md`. The `YYMMDD` prefix is
the completion/archive date; the frontmatter `id` does not change.
**Ad Hoc Tasks:** small opportunistic fixes discovered during a session use
`workplans/ADHOC-YYYY-MM-DD.md` with task ids `ADHOC-YYYY-MM-DD-T01`, etc.
Use this only for low-risk work completed directly; create a normal workplan
for anything needing analysis, design, approval, dependencies, or multiple phases.
**Frontmatter:**
```yaml
---
id: RAILIANCE-WP-NNNN
type: workplan
title: "..."
domain: financials
repo: railiance-master
status: proposed | ready | active | blocked | backlog | finished | archived
owner: codex
topic_slug: ...
created: "YYYY-MM-DD"
updated: "YYYY-MM-DD"
state_hub_workstream_id: "<uuid>" # written by fix-consistency — do not edit
---
```
Use `proposed` for a new draft, `ready` after review against current repo
state, and `finished` after implementation. `stalled` and `needs_review`
are derived health labels, not frontmatter statuses.
**Task block format** (one per `##` section):
```task
id: RAILIANCE-WP-NNNN-T01
status: wait | todo | progress | done | cancel
priority: high | medium | low
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
```
Status progression: `todo``progress``done`; use `wait` for waiting or
blocked work and `cancel` for stopped work.
### Repo-specific guidance
Use `railiance-master` workplans for framework changes that span multiple
Railiance repos, especially repository taxonomy changes, architecture boundary
changes, and migrations introducing `rail-*`, `rapp-*`, or `reef-*` concepts.
Do not use this repo to track implementation work that belongs entirely inside
one concrete ownership repo such as `railiance-platform` or `railiance-apps`.

4
CLAUDE.md Normal file
View file

@ -0,0 +1,4 @@
# railiance-master — Claude Code Instructions
@SCOPE.md
@AGENTS.md

188
INTENT.md Normal file
View file

@ -0,0 +1,188 @@
# INTENT
> This file captures **why this repository exists**,
> the **direction it is moving toward**, and
> the **kind of system it is meant to become**.
> It is intentionally **aspirational and stable**, not a description of current implementation.
---
## One-liner
**The Railiance architecture-definition home — turning evolving repo families, workload models, and substrate realities into a coherent framework vocabulary and boundary model.**
---
## Why This Exists
As Railiance grows, implementation repos naturally solve immediate problems:
infrastructure, cluster runtime, platform services, forge operations,
application releases, and ecosystem modeling.
What those repos cannot safely do on their own is define the framework's shared
meaning.
Without a canonical architecture home:
* the same terms drift across repos,
* new repo families appear without clear boundaries,
* execution models and workload wrappers get mixed into the wrong layers,
* and migrations happen by local habit rather than deliberate framework design.
This repository exists to define the **shared architectural language** of
Railiance before that language hardens accidentally inside implementation repos.
---
## Operating Context
Railiance does not exist in isolation.
It is part of a wider, coevolving ecosystem around **Railiance**, **Net
Kingdom**, and the **Helix Forge** software factory. That ecosystem is
intended to support the full path from:
* product ideation,
* discovery,
* delivery,
* operation,
* marketing,
* and monetization.
The architecture therefore has to work across experimental and production-grade
realities at the same time.
That matters because repo boundaries in Railiance are not only about code
organization. They shape how humans and agents coordinate responsibilities,
reason about workload placement, and evolve operating models without losing the
ability to scale into more mature security and delivery expectations.
---
## The Mission
> *Where we are going.*
To become the **canonical home for Railiance framework architecture**
where repository taxonomy, architectural boundaries, execution-model concepts,
managed workload patterns, substrate concepts, and migration direction are
defined once and referenced everywhere else.
This means:
* Railiance vocabulary is defined through **explicit architectural documents**
* New repo families and framework terms are introduced through **clear decisions**
* Ownership, execution mode, workload identity, and substrate identity remain
**separate and composable**
* Explorations mature into **stable decisions** before they spread across the
wider repo landscape
* The framework can support both **early-stage experimentation** and
**production-grade operation** without collapsing those needs into one vague
structure
---
## Core Principles
### 1. Architecture Before Proliferation
New repo patterns should be named and bounded deliberately before they multiply
across the ecosystem.
### 2. Shared Vocabulary Is Infrastructure
Terms such as `railiance-*`, `rail-*`, `rapp-*`, and `reef-*` are not cosmetic.
They shape ownership, tooling, and operator understanding.
### 3. Separate Axes Cleanly
Ownership, execution architecture, workload packaging, and substrate reality
must not collapse into one ambiguous repo type.
### 4. Decisions Need A Canonical Home
Framework-level architecture decisions should live in one source-controlled
place rather than being reconstructed from scattered repo-local assumptions.
### 5. Stable Meaning, Evolvable Model
The framework vocabulary should stay understandable over time even as specific
rails, workloads, and substrates evolve.
### 6. Guide Implementation, Do Not Shadow It
This repo should define structure and direction, not absorb the operational
content that belongs in the implementation repos themselves.
### 7. Stabilize The Default Path First
Railiance should not introduce multiple top-level rails speculatively.
The default path for platform services and managed applications is
`rail-kubernetes` until there is a concrete workload need and a sound argument
for a distinct rail.
### 8. Managed Packaging Is Not Ownership
`rapp-*` repos exist to wrap third-party or self-built workloads so they can be
run as fully managed Railiance workloads in the wider Railiance and Net Kingdom
context.
They do not replace the ownership repos that define why a capability exists.
### 9. Substrates Need Purpose, Not Just Names
`reef-*` repos should represent compute resources organized around a defined
purpose and operational boundary.
They should not be created merely because a named machine exists.
---
## What This Is (Conceptually)
This repository is:
* an **architecture-definition home**
* a **repository taxonomy authority**
* a home for **framework-level ADRs and conceptual models**
* a place to define how Railiance repos **compose across multiple axes**
* a **migration map** from current repo reality toward cleaner framework
structure
---
## What This Is Not
This repository is not:
* the infrastructure substrate
* the Kubernetes runtime or workload execution layer
* the shared platform-services layer
* the forge runtime
* the application release surface
* the implementation of the ecosystem graph registry
* a dumping ground for operational runbooks that belong elsewhere
It is the **place where the framework explains itself**.
---
## Direction of Evolution
This repository is expected to evolve toward:
* clearer **repository-family definitions** and lifecycle rules
* stable **rail**, **rapp**, and **reef** contracts
* stronger **boundary guidance** for new repos and migrations
* better linkage between architecture decisions and `railiance-fabric`
declarations
* a repeatable path from **exploration -> ADR -> adopted framework pattern**
* a clear model for when experimental multi-rail substrates are acceptable and
when production-grade separation is the better default
---
## Guiding Question
> **How can Railiance define its own structure clearly enough that every new repo, rail, managed workload, and substrate increases capability without increasing ambiguity, even as the ecosystem grows from exploratory operation into production-grade responsibility?**

View file

@ -1,3 +1,38 @@
# railiance-master
Framework architecture for railiance applications, railiance rails, railiance tooling. This repo explains and evolves the concepts in and around railiance.
Architecture home for the Railiance framework.
This repository defines how Railiance concepts map to repositories, how the
different repo families compose, and where new architecture decisions should be
recorded before they are spread across implementation repos.
## Current Architecture Baseline
- [docs/repository-axes.md](docs/repository-axes.md)
- [docs/reef-substrate-model.md](docs/reef-substrate-model.md)
- [docs/rail-kubernetes-boundary.md](docs/rail-kubernetes-boundary.md)
- [docs/rapp-first-wave-candidates.md](docs/rapp-first-wave-candidates.md)
- [docs/reef-first-wave-rollout.md](docs/reef-first-wave-rollout.md)
- [docs/fabric-state-hub-adaptation.md](docs/fabric-state-hub-adaptation.md)
- [docs/adr/ADR-0001-repository-prefix-architecture.md](docs/adr/ADR-0001-repository-prefix-architecture.md)
- [docs/adr/ADR-0002-rail-kubernetes-wave-1-boundary.md](docs/adr/ADR-0002-rail-kubernetes-wave-1-boundary.md)
- [docs/adr/ADR-0003-rapp-first-wave-selection.md](docs/adr/ADR-0003-rapp-first-wave-selection.md)
- [docs/adr/ADR-0004-first-wave-reef-rollout.md](docs/adr/ADR-0004-first-wave-reef-rollout.md)
## Current Explorations
- [history/260724-InitialExplorationOfOperationModels.md](history/260724-InitialExplorationOfOperationModels.md)
- [history/260724-InitialExplorationOfWrapperConcepts.md](history/260724-InitialExplorationOfWrapperConcepts.md)
## Purpose
`railiance-master` is the canonical place to define:
- repo-family vocabulary such as `railiance-*`, `rail-*`, `rapp-*`, and `reef-*`
- cross-repo architectural boundaries
- the relationship between ownership, execution mode, workload packaging, and
substrate realities
- the migration direction when current repos must be split or renamed
Implementation repos should follow the architecture recorded here rather than
each inventing local meanings for the same terms.

133
SCOPE.md Normal file
View file

@ -0,0 +1,133 @@
# SCOPE
> This file helps you quickly understand what this repository is about,
> when it is relevant, and when it is not.
> It is intentionally lightweight and may be incomplete.
---
## One-liner
Architecture-definition home for Railiance: repository taxonomy, framework ADRs,
cross-repo boundary rules, and cross-repo workplans for architecture changes.
---
## Core Idea
`railiance-master` is the framework-level architecture repo for Railiance.
It exists so shared concepts such as `railiance-*`, `rail-*`, `rapp-*`, and
`reef-*` are defined once, with explicit boundaries, before they spread across
implementation repos.
It also serves as the natural workplan home for changes that span multiple
Railiance repos and cannot be owned cleanly by only one of them.
---
## In Scope
- Framework-level architecture documents for Railiance
- Repository taxonomy and naming conventions
- Architectural boundaries between ownership repos, rails, `rapp`s, and reefs
- Architecture decision records affecting multiple Railiance repos
- Cross-repo Railiance workplans whose implementation spans multiple sibling repos
---
## Out of Scope
- OS provisioning and host hardening work owned by `railiance-infra`
- Kubernetes runtime implementation owned by `railiance-cluster`
- Platform-service implementation owned by `railiance-platform`
- Application release implementation owned by `railiance-apps`
- Forge runtime implementation owned by `railiance-forge`
- Fabric graph implementation owned by `railiance-fabric`
---
## Relevant When
- Defining a new Railiance repo family or framework term
- Clarifying boundaries between existing Railiance repos
- Planning migrations that touch multiple Railiance repos
- Recording a framework-level architecture decision
---
## Not Relevant When
- The work belongs entirely inside one implementation repo
- The work is operational rather than architectural
- The work is workload-specific rather than framework-wide
---
## Current State
- Status: maintained / evolving
- Implementation: architecture baseline documents are present and the first cross-repo separation workplan has been completed and handed off to sibling repos
- Stability: evolving
- Usage: internal Railiance framework architecture home and handoff point for cross-repo planning
The repo now holds the canonical framework decisions and boundary documents for
separating `rail-*`, `rapp-*`, and `reef-*` concerns out of the existing
Railiance repos. Active implementation follow-up continues in the sibling
ownership repos.
---
## How It Fits
- Upstream dependencies: `the-custodian` canon and State Hub conventions
- Downstream consumers: all `railiance-*`, future `rail-*`, future `rapp-*`, and future `reef-*` repos
- Often used with: `railiance-fabric`, `railiance-platform`, `railiance-cluster`, `state-hub`
---
## Terminology
- Preferred terms: architecture home, repository axis, rail, `rapp`, reef, ownership repo
- Also known as: framework architecture repo
- Potentially confusing terms: this repo defines framework structure; it does not implement the lower-layer systems it describes
---
## Related / Overlapping Repositories
- `railiance-fabric` — models the ecosystem graph; `railiance-master` defines framework taxonomy and boundaries
- `state-hub` — indexes and coordinates work; `railiance-master` provides the framework architecture to be coordinated
- `repo-scoping` — explains what repos are useful for; `railiance-master` defines how Railiance repo families fit together
---
## Getting Oriented
- Start with: `README.md`, `INTENT.md`
- Key files / directories: `docs/`, `history/`, `workplans/`
- Entry points: `docs/repository-axes.md`, `docs/reef-substrate-model.md`, `docs/adr/`
---
## Provided Capabilities
```capability
type: documentation
title: Railiance repository taxonomy
description: Defines the canonical Railiance repo families and how ownership repos, rails, managed workloads, and substrate boundaries compose.
keywords: [railiance, architecture, taxonomy, rail, rapp, reef]
```
```capability
type: governance
title: Railiance framework architecture decisions
description: Records framework-level architecture decisions and boundary guidance for changes spanning multiple Railiance repos.
keywords: [architecture, adr, governance, boundaries, framework]
```
---
## Notes
Use this repo for architecture that must stay shared. Push concrete
implementation outward into the ownership repos once the framework boundary is clear.

18
WORK-RECORDS.md Normal file
View file

@ -0,0 +1,18 @@
# Work Records — railiance-master
> Generated by `statehub fix-consistency` (CUST-WP-0061-T04, work-record
> stage 3). Do not edit by hand — edit the source file/block listed for
> each record and re-run fix-consistency to refresh this index. Archived
> workplans are omitted; closed decisions/intakes/engagements stay listed
> so recently-resolved work is still visible. [auto]
| Kind | ID | Status | Lane | Source |
| --- | --- | --- | --- | --- |
| workplan | RAILIANCE-WP-0017 | finished | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T01 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T02 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T03 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T04 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T05 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T06 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |
| task | RAILIANCE-WP-0017-T07 | done | — | workplans/RAILIANCE-WP-0017-rail-rapp-reef-repo-separation.md |

View 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.

View 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.

View 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.

View 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.

View 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

View 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.

View 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.

View 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.

View 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
View 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.

View file

@ -0,0 +1,397 @@
Exploration of railiance modes to operate managed workloads
===========================================================
--worsch, 24.7.26 r1
# Intro
We need to consistently run workloads and there are tradeoffs depending on which operations architecture aka "rail" one uses for a specific workload.
This is an exploration how we can do that, with knative as the first example.
This is about how and which rails might be relevant.
# Knative in one sentence
**Knative adds a serverless application platform on top of Kubernetes.** Instead of developers managing `Deployment`, `Service`, autoscaling, ingress, revisions, and traffic splitting separately, they deploy a Knative service or function and let Knative construct and operate those resources.
Knative is now a **CNCF Graduated project** and consists of three related parts:
* **Knative Serving** — request-driven container deployment, revisions, traffic routing, autoscaling, and scale-to-zero.
* **Knative Eventing** — CloudEvents-based routing from sources through brokers and triggers to event consumers.
* **Knative Functions** — a developer-oriented function framework built on Serving and Eventing. ([CNCF][1])
## Conceptual architecture
```text
Developer / GitOps / CI
Knative Service
Configuration
immutable Revisions
Route
Gateway / Ingress
┌───┴─────────────────┐
│ │
Activator Running revision
cold-start path │
│ queue-proxy
└───────────────────────│
application container
Event producer
Source
Broker / Channel
Trigger filter
Sink: Knative Service, Kubernetes Service, etc.
```
Each change creates an immutable **Revision**, and traffic can be distributed between revisions for canary, blue-green, or rollback scenarios. When a service is at zero replicas, the Activator can hold incoming requests while the autoscaler starts a revision. Requests reaching an active revision normally pass through Knatives `queue-proxy` sidecar before reaching the application container. ([knative.dev][2])
---
# What Knative changes in your infrastructure
## 1. Kubernetes becomes an application platform
Without Knative, your application platform typically exposes:
```text
Deployment + Service + Gateway/Ingress + HPA + rollout tooling
```
With Knative, the primary developer abstraction becomes:
```text
Knative Service + optional Eventing resources
```
This is a meaningful architectural improvement when you want HelixForge-style repositories to publish applications through a consistent platform contract. It is less attractive when infrastructure teams want applications to remain completely explicit and close to native Kubernetes resources.
The benefit is **platform standardization**. The cost is that Knative becomes another reconciliation layer whose behaviour must be understood during incidents.
## 2. The network architecture changes
Knative Serving needs a compatible networking layer. Current installation options include Kourier, Contour, Istio, and a Gateway API integration. The Knative project currently tests Gateway API implementations based on Istio, Contour, and Envoy Gateway. ([knative.dev][3])
This has practical consequences:
* Your existing ingress controller might not be reusable.
* Knative may introduce a second gateway or service-mesh data plane.
* DNS and wildcard domains become part of the platform contract.
* External TLS, internal routing, Activator routing, and ordinary Kubernetes service routing need to be observed separately.
For a k3s installation using its typical Traefik setup, for example, you should expect either an additional supported Knative gateway or a deliberate migration to a supported Gateway API implementation. That conclusion follows from the supported and tested networking options rather than from a general inability of Traefik to route HTTP traffic.
## 3. Autoscaling becomes request-aware
Knatives default KPA autoscaler can scale based on request concurrency and supports scale-to-zero. The ordinary HPA option supports CPU-based scaling but does not provide Knatives scale-to-zero behaviour. ([knative.dev][4])
That works particularly well for:
* Bursty APIs.
* Webhook receivers.
* Infrequently used tenant-specific services.
* Preview environments.
* Internal tools with long idle periods.
* Lightweight event handlers.
It is less suitable for services requiring:
* Predictable sub-second latency at all times.
* Persistent in-memory state.
* Sticky sessions.
* Long-lived connections that cannot tolerate revision replacement.
* Large runtimes or models with expensive initialization.
Scale-to-zero reduces idle consumption, but converts part of your capacity problem into a **cold-start engineering problem**. Container pull time, application initialization, secrets retrieval, database connection setup, readiness checks, and node capacity all become part of request latency.
## 4. Every application pod gains platform behaviour
Knative normally adds a `queue-proxy` sidecar to revision pods. The Activator may additionally enter the request path during scale-from-zero or capacity transitions. ([knative.dev][5])
This affects:
* Pod resource requests and limits.
* Service-mesh sidecar combinations.
* Network policy.
* Request tracing.
* Graceful termination.
* Per-request metrics.
* Failure analysis.
* Capacity calculations.
For a large number of small services, platform sidecars and control-plane objects can become a significant portion of total resource consumption.
## 5. The control plane becomes larger
A basic Serving installation introduces CRDs, controllers, admission webhooks, an autoscaler, Activator components, networking integration, and configuration objects. Eventing adds its own controllers, brokers, dispatchers, sources, channels, and potentially Kafka infrastructure.
The official single-node installation guidance currently begins at 6 CPUs, 6 GB RAM, and 30 GB disk, although real production sizing depends heavily on the number of revisions, services, requests, and Eventing resources. ([knative.dev][3])
Knative also follows a relatively fast Kubernetes compatibility schedule. As of July 24, 2026, the supported Knative release lines are 1.21 and 1.22, requiring Kubernetes 1.33 and 1.34 respectively; Knative 1.23 is scheduled for July 28, 2026. ([GitHub][6])
That means Knative can influence when your k3s or Kubernetes platform must be upgraded.
## 6. Observability becomes more important
Scale-to-zero means pods and their local logs disappear regularly. Knative explicitly recommends centralized log collection because Serving deletes pods as they are no longer needed. Its control plane and request path expose metrics and support OpenTelemetry-based integration. ([knative.dev][7])
Your OpsCatalog should distinguish at least:
```text
Gateway → Knative Route → Activator → queue-proxy → application
```
Otherwise, an apparent application outage may really be:
* A gateway routing problem.
* A Knative Route or Revision condition.
* Failed scale-from-zero.
* Unschedulable pods.
* Image pull delay.
* A queue-proxy readiness issue.
* Application initialization failure.
## 7. Knative is not a hard multitenancy boundary
Knatives own threat model describes a **Namespace-as-a-Service** model for teams within a common organization sharing a cluster, control plane, and nodes. ([knative.dev][8])
That aligns well with trusted internal platform teams. It does not by itself establish strong isolation between mutually hostile customers.
For your multi-vendor and government/corporate security ambitions, Knative should therefore sit inside a broader tenancy architecture involving:
* RBAC and admission policy.
* Resource quotas and limit ranges.
* Default-deny network policy.
* Workload identity.
* Secret isolation.
* Separate node pools where appropriate.
* Separate clusters or control planes for high-assurance tenant boundaries.
Kubernetes itself distinguishes trusted multi-team sharing from multi-customer tenancy and requires additional controls around resource and security isolation. ([Kubernetes][9])
There is also an important current security qualification: Knative documents its cluster-local and system-internal TLS features as experimental, and states that not all control-plane traffic is encrypted. ([knative.dev][10])
---
# SWOT assessment
| | Positive | Negative |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Internal** | **Strengths:** Strong Kubernetes-native serverless abstraction; container rather than language lock-in; scale-to-zero; immutable revisions; built-in traffic splitting; CloudEvents integration; pluggable networking; compatible with GitOps; mature CNCF governance. | **Weaknesses:** Significant CRD and controller footprint; additional network data path; cold-start latency; queue-proxy overhead; more difficult troubleshooting; assumes largely stateless and fungible instances; Kubernetes-version coupling; Eventing can add another messaging abstraction. |
| **External** | **Opportunities:** A standard application-runtime surface for HelixForge; tenant- or project-specific services that consume no resources while idle; disposable environments; webhook and adapter execution; KServe-based AI inference; consistent rollout and rollback; a common event vocabulary across projects. | **Threats:** Duplication with Gateway API, service mesh, Argo Rollouts, KEDA, Dapr, Temporal, and existing brokers; platform lock-in at the Kubernetes-CRD level; accidental use for stateful or latency-critical workloads; insufficient isolation for hostile tenants; uncontrolled creation of revisions and services; upgrade burden becoming larger than saved application effort. |
## Overall SWOT verdict
Knatives greatest strength is not merely scale-to-zero. It is the creation of a **coherent application execution contract**.
Its greatest weakness is also that contract: once adopted broadly, networking, rollout, autoscaling, observability, security, and deployment semantics become tied to Knative.
---
# Alternative open-source approaches
There is no universally “more advanced” alternative. Several tools are more advanced for a **narrower problem**.
## KEDA plus ordinary Kubernetes workloads
KEDA is the strongest alternative when you primarily want event-driven scaling rather than a serverless application platform.
It works alongside the Kubernetes HPA, can scale deployments and other resources to zero based on queues, databases, APIs, or other external metrics, and can create Kubernetes Jobs for event-driven batch processing. KEDA is CNCF Graduated. ([KEDA][11])
**Prefer KEDA when:**
* You want to retain standard `Deployment`, `StatefulSet`, and `Job` objects.
* Workers pull from Kafka, RabbitMQ, NATS, Redis, or another queue.
* You do not need revision-aware HTTP routing.
* You want incremental, low-impact adoption.
* Different workloads require different scaling models.
KEDAs HTTP add-on remains beta, so Knative is currently the more established choice for transparent HTTP scale-from-zero routing. ([KEDA][12])
**For your infrastructure, KEDA is likely the better default autoscaling component, with Knative reserved for services that specifically benefit from request-driven scale-to-zero and revision routing.**
## Fission
Fission is a function-oriented serverless platform. Developers can submit source code against language environments without constructing container images themselves. It maintains warm runtime pools and emphasizes fast function startup and developer productivity. The project remains Apache-2.0 licensed and released version 1.27.0 on June 22, 2026. ([Fission][13])
**Prefer Fission when:**
* The primary product is a FaaS developer experience.
* Developers should submit small Python, JavaScript, Go, or similar functions.
* Building and managing OCI images should be hidden.
* Warm runtime pools are acceptable.
* Functions are the primary unit, rather than arbitrary containerized applications.
Fission is more specialized and potentially more convenient for function developers, but Knative is the broader and more composable application platform.
## Nuclio
Nuclio concentrates on high-performance event and data processing, including CPU- and GPU-intensive execution and integration with streaming and data-science environments. It is Apache-2.0 licensed and released version 1.17.1 on July 7, 2026. ([GitHub][14])
**Prefer Nuclio when:**
* Functions consume high-volume streams.
* Processing is data-, I/O-, or compute-intensive.
* GPU execution matters.
* Jupyter, Kubeflow, or data-science integration is central.
* Function processor performance is more important than a generic application-platform abstraction.
Nuclio may be “more advanced” for high-performance data functions, but not for general microservice platform governance.
## Dapr
Dapr is not a Knative replacement at the deployment level. It is a distributed application runtime exposing building blocks for service invocation, pub/sub, state, actors, jobs, secrets, configuration, and workflows. It normally adds a Dapr runtime process or sidecar to each participating service and is CNCF Graduated. ([Dapr Docs][15])
**Prefer or add Dapr when:**
* Applications need portable infrastructure APIs.
* You want to swap brokers or state stores without rewriting application integration.
* Service-to-service resiliency is more important than scale-to-zero.
* Actors, pub/sub, or application-level workflows are required.
Knative answers **“how is this container deployed and activated?”**
Dapr answers **“how does this distributed application use infrastructure capabilities?”**
They can be combined, but combining their sidecars and control planes should be justified by concrete use cases.
## Temporal
Temporal is paramount when events initiate **durable, stateful, multi-step coordination**.
A Knative event handler can receive an event and execute code, but it does not replace durable workflow state, replay, long-lived waiting, activity retries, compensation, or workflow versioning. Temporal provides those capabilities and supports self-hosted production operation. ([Temporal Docs][16])
Given your existing Temporal-centered event-backbone direction, I would preserve this separation:
```text
Knative Serving → bursty request-driven execution
KEDA → queue- and metric-driven worker scaling
Temporal → durable coordination and control loops
Kafka/NATS/etc. → durable event transport
```
Knative Eventing can then act as a CloudEvents routing and adaptation surface rather than becoming the authoritative workflow or event-history system.
## SpinKube or wasmCloud
SpinKube and wasmCloud represent a more radical WebAssembly-based architecture.
SpinKube runs Spin-based Wasm applications through Kubernetes and is currently a CNCF Sandbox project. wasmCloud provides a distributed Wasm component platform spanning Kubernetes, cloud, datacenter, and edge, and is a CNCF Incubating project. ([SpinKube][17])
**Prefer evaluating Wasm when:**
* Very high workload density is important.
* Edge or intermittently connected environments matter.
* Applications are small, portable components.
* Fast startup and low runtime overhead outweigh ecosystem maturity.
* You want stronger capability-oriented sandboxing for extension code.
* Polyglot components must run consistently across Kubernetes and non-Kubernetes environments.
This is potentially more forward-looking than Knative, but it imposes a more substantial programming and runtime model change. I would currently treat it as an experimental runtime class, not the default foundation for all services.
## KServe
For model inference, KServe is more appropriate than building a generic Knative function platform yourself. KServes default deployment mode currently uses Knative for request-driven serverless inference; its Standard mode can optionally use KEDA, although Standard mode does not currently support HTTP scale-from-zero. ([kserve.github.io][18])
Thus, Knative may become an **underlying dependency of an AI inference platform**, rather than the user-facing AI platform itself.
## OpenFaaS caveat
OpenFaaS remains technically capable, but it is no longer a straightforward fully open-source production alternative for a business platform. Its Community Edition is limited to personal exploration and short commercial proofs of concept; production features and commercial use require a paid edition, and scale-from-zero is not included in CE. ([openfaas.com][19])
That licensing model appears poorly aligned with your preference for sovereign, commercially usable open-source infrastructure.
---
# When a different architecture should take precedence
| Dominant requirement | Prefer |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Stateless HTTP services with scale-to-zero and traffic splitting | **Knative Serving** |
| Queue workers and event-driven batch jobs | **KEDA + Deployments/Jobs** |
| Source-code-oriented FaaS developer experience | **Fission** |
| High-performance stream, data, CPU, or GPU functions | **Nuclio** |
| Portable distributed-application APIs | **Dapr** |
| Durable processes, retries, waiting, compensation, control loops | **Temporal** |
| ML model serving | **KServe**, possibly backed by Knative |
| Edge and high-density component execution | **wasmCloud or SpinKube** |
| Stateful, latency-critical, always-on services | **Standard Kubernetes Deployments/StatefulSets** |
| Mutually untrusted customers or high-assurance isolation | **Separate clusters/control planes**, possibly with Knative inside each boundary |
---
# Recommendation for your platform
I would introduce Knative as an **optional execution capability**, not as the universal deployment model.
A sensible initial architecture would be:
```text
Platform deployment classes
┌──────────────────────┼──────────────────────┐
│ │ │
Standard Kubernetes Knative Serving KEDA workers
long-lived/stateful bursty HTTP/events queues and jobs
│ │ │
└──────────────────────┴──────────────────────┘
Temporal coordination
Kafka/NATS/RabbitMQ events
```
Start with **Knative Serving only**. Reuse a supported Gateway API implementation where possible, keep Eventing out of the first deployment, and evaluate three representative workloads:
1. A bursty webhook or adapter service.
2. An infrequently used internal API.
3. A tenant- or project-specific disposable service.
Measure:
* Idle control-plane and sidecar consumption.
* Cold-start median and tail latency.
* Time from request to ready revision.
* Behaviour under node exhaustion.
* Revision rollout and rollback.
* Log and trace completeness.
* Network-policy compatibility.
* Upgrade effort.
* Failure isolation between namespaces.
Add Knative Eventing later only where its SourceBrokerTrigger model demonstrably simplifies CloudEvents routing. For your architecture, **Temporal should remain the durable coordination layer and KEDA the default event-driven scaler**. Knative then becomes a valuable, bounded runtime for stateless, bursty services rather than an additional universal control plane competing with the systems you already intend to establish.
[1]: https://www.cncf.io/projects/knative/?utm_source=chatgpt.com "Knative | CNCF"
[2]: https://knative.dev/docs/serving/?utm_source=chatgpt.com "Knative Serving"
[3]: https://knative.dev/docs/install/yaml-install/serving/install-serving-with-yaml/?utm_source=chatgpt.com "Install Serving with YAML"
[4]: https://knative.dev/docs/serving/autoscaling/autoscaler-types/?utm_source=chatgpt.com "Supported autoscaler types"
[5]: https://knative.dev/docs/serving/request-flow/?utm_source=chatgpt.com "HTTP Request Flows"
[6]: https://github.com/knative/community/blob/main/mechanics/RELEASE-SCHEDULE.md?utm_source=chatgpt.com "community/mechanics/RELEASE-SCHEDULE.md at main"
[7]: https://knative.dev/docs/serving/observability/logging/collecting-logs/?utm_source=chatgpt.com "Collecting Serving logs"
[8]: https://knative.dev/docs/reference/security/threat-model/?utm_source=chatgpt.com "Threat Model"
[9]: https://kubernetes.io/docs/concepts/security/multi-tenancy/?utm_source=chatgpt.com "Multi-tenancy"
[10]: https://knative.dev/docs/serving/encryption/encryption-overview/?utm_source=chatgpt.com "Serving Encryption Overview"
[11]: https://keda.sh/docs/2.20/concepts/?utm_source=chatgpt.com "KEDA Concepts"
[12]: https://keda.sh/docs/2.20/setupscaler/?utm_source=chatgpt.com "Setup Autoscaling with KEDA"
[13]: https://fission.io/docs/?utm_source=chatgpt.com "Serverless Functions for Kubernetes - Fission"
[14]: https://github.com/nuclio/nuclio/releases?utm_source=chatgpt.com "Releases · nuclio/nuclio"
[15]: https://docs.dapr.io/concepts/overview/?utm_source=chatgpt.com "Overview"
[16]: https://docs.temporal.io/self-hosted-guide?utm_source=chatgpt.com "Self-hosted Temporal Service guide"
[17]: https://www.spinkube.dev/?utm_source=chatgpt.com "SpinKube"
[18]: https://kserve.github.io/website/docs/admin-guide/kubernetes-deployment?utm_source=chatgpt.com "Kubernetes Deployment Installation Guide"
[19]: https://www.openfaas.com/pricing/?utm_source=chatgpt.com "Plans & Pricing"

View file

@ -0,0 +1 @@
This shall become an exploration about how to wrap apps and services to run them as a railiance managed workloads.

1
workplans/.gitkeep Normal file
View file

@ -0,0 +1 @@

View file

@ -0,0 +1,310 @@
---
id: RAILIANCE-WP-0017
type: workplan
title: "Rail, Rapp, and Reef Repo Separation"
domain: financials
repo: railiance-master
status: finished
owner: codex
topic_slug: railiance
planning_priority: high
planning_order: 17
created: "2026-07-25"
updated: "2026-07-25"
related_repos:
- railiance-master
- railiance-cluster
- railiance-platform
- railiance-apps
- railiance-forge
- railiance-fabric
- railiance-infra
- railiance-hosts
state_hub_workstream_id: "dd794e38-6da0-4acd-8ad8-e00bd2aa62bc"
---
# RAILIANCE-WP-0017 - Rail, Rapp, and Reef Repo Separation
## Goal
Turn the newly defined `rail-*`, `rapp-*`, and `reef-*` concepts into an
executable migration plan for the current Railiance repo family, so the
framework can evolve without leaving workload execution semantics, workload
packaging, and substrate realities mixed into the existing ownership repos.
This workplan is explicitly cross-repo. It belongs in `railiance-master`
because no single implementation repo can own the migration end to end.
## Current Starting Point
The framework baseline is now recorded in `railiance-master`:
- `docs/repository-axes.md`
- `docs/reef-substrate-model.md`
- `docs/adr/ADR-0001-repository-prefix-architecture.md`
The repo is also now prepared and registered with State Hub as the architecture
home for future multi-repo Railiance work.
The architectural direction is now further clarified:
- wave 1 is centered on `rail-kubernetes` as the default base rail
- new rails are introduced only for concrete workload needs with a sound
runtime argument
- `rail-knative` is the first expected follow-on rail, driven by the need to
support `qonto-assistent`, but only after the Kubernetes rail boundary is
clean
- `rapp-*` repos are about managed wrapping and scaffolding, not ownership
- `reef-*` repos are about compute resources organized for a defined purpose
- mixed-rail reefs are acceptable early, but production-grade cases should
prefer clearer substrate and primary-rail separation unless deliberately
justified
The remaining problem is implementation reality:
- `railiance-cluster` still owns Kubernetes-specific workload lifecycle and
overlay semantics that should eventually become `rail-kubernetes`
- first-class workload wrappers are still spread across `railiance-apps`,
`railiance-platform`, and `railiance-forge`
- substrate reality is under-described and split between `railiance-infra` and
`railiance-hosts`
- `railiance-fabric` and State Hub do not yet model rails, `rapp`s, or reefs
as first-class entities
## Target Outcome
When this workplan is complete:
1. Railiance has a clear first migration target for `rail-kubernetes`.
2. The first set of `rapp-*` candidates is chosen and ordered.
3. The first `reef-*` rollout rule is chosen for current named substrates.
4. `railiance-fabric` and State Hub have a defined integration path for the new
repo families.
5. The current repo set has an approved separation plan, not only a naming idea.
## Boundaries
This workplan may define, sequence, and coordinate repo splits.
It must not silently move implementation content between repos without explicit
repo-local follow-up workplans or commits in those repos.
## Tasks
## T01 - Record the framework repo-family baseline in railiance-master
```task
id: RAILIANCE-WP-0017-T01
status: done
priority: high
state_hub_task_id: "7cb6769a-5557-46e5-8e20-c492e5049604"
```
Record the first canonical architecture baseline for:
- `railiance-*` as ownership repos
- `rail-*` as execution-contract repos
- `rapp-*` as managed workload package repos
- `reef-*` as substrate-boundary repos
Acceptance:
- `railiance-master` contains the baseline documents and ADR
- the `reef-*` model is explicitly defined and bounded against repo explosion
## T02 - Prepare railiance-master as the cross-repo workplan home
```task
id: RAILIANCE-WP-0017-T02
status: done
priority: high
state_hub_task_id: "17be5faa-cba2-4838-97af-dc3b79e0511b"
```
Prepare and register `railiance-master` in State Hub so cross-repo architecture
work can live here as first-class workplans.
Acceptance:
- repo is classification-registered
- repo passes `statehub fix-consistency`
- workplan and architecture files can now be indexed from this repo
## T03 - Define the `rail-kubernetes` extraction boundary
```task
id: RAILIANCE-WP-0017-T03
status: done
priority: high
state_hub_task_id: "e25ea023-e2fe-44b9-96c1-cca19c65053f"
```
Define what moves from `railiance-cluster` into a future `rail-kubernetes`
repo, and what must remain owned by `railiance-cluster`.
This is the wave-1 architecture task. It must treat `rail-kubernetes` as the
default base rail for the current ecosystem rather than as one option among
many equally urgent rails.
At minimum, decide the boundary for:
- `railiance/app.toml`
- promotion lifecycle semantics
- overlay repo pattern
- stage-1/2/3 tooling
- cluster-runtime prerequisites versus workload-runtime semantics
- the compatibility path future rails such as `rail-knative` will rely on
Acceptance:
- one written boundary contract names what `railiance-cluster` keeps
- one written boundary contract names what `rail-kubernetes` must own
- at least one migration-safe path exists that does not break current users
- the boundary leaves a coherent follow-on path for `rail-knative` without
forcing knative design decisions into wave 1
2026-07-25: Added `docs/rail-kubernetes-boundary.md` and
`docs/adr/ADR-0002-rail-kubernetes-wave-1-boundary.md`. The boundary now names
the retained S2 substrate scope, the extracted Kubernetes rail contract, the
rehome-required workload-specific helpers, and a compatibility-preserving split
sequence.
## T04 - Identify and sequence the first `rapp-*` candidates
```task
id: RAILIANCE-WP-0017-T04
status: done
priority: high
state_hub_task_id: "674b1a4f-2c5b-499c-b26f-9ed4f9f0861c"
```
Choose the first workload packages that should become first-class `rapp-*`
repos instead of remaining embedded inside ownership repos.
This task must treat `rapp-*` as managed workload packaging for third-party or
self-built workloads in the Railiance and Net Kingdom context. It must not
turn `rapp-*` into an ownership mirror of existing `railiance-*` repos.
Candidate set to assess:
- Forgejo or Gitea from `railiance-forge`
- OpenBao from `railiance-platform`
- one user-facing S5 workload from `railiance-apps`
Acceptance:
- first-wave `rapp-*` candidates are named
- rationale is recorded for each chosen or deferred candidate
- split order is defined so ownership boundaries do not get weaker during migration
- each chosen candidate is justified as a managed wrapper and not as a new
ownership home
2026-07-25: Added `docs/rapp-first-wave-candidates.md` and
`docs/adr/ADR-0003-rapp-first-wave-selection.md`. The first-wave order is now
`rapp-openbao`, then `rapp-vergabe-teilnahme`, with the forge workload
explicitly deferred until the Gitea-versus-Forgejo package target is stable
enough to avoid immediate wrapper churn.
## T05 - Decide the first `reef-*` rollout for current substrates
```task
id: RAILIANCE-WP-0017-T05
status: done
priority: medium
state_hub_task_id: "53c63266-fbcb-4644-86f4-042e7b80744e"
```
Apply the new reef model to the current Railiance substrate reality and decide
whether the first rollout should be:
- `reef-coulombcore`
- `reef-railiance01`
- `reef-workstation`
- or a grouped substrate such as `reef-ops-workstations`
This task must also resolve the conceptual overlap between `railiance-infra`
and `railiance-hosts`.
It should treat reefs as compute resources organized for a defined purpose and
should explicitly decide how much multi-rail mixing is acceptable in early
substrates such as `RAILIANCE01`.
Acceptance:
- first-wave reef repo set is chosen
- the rule for singleton versus grouped reef repos is applied to current hosts
- the `railiance-hosts` versus `railiance-infra` ambiguity has a documented direction
- any provisional terminology for transitional substrates is kept provisional
unless the pattern is stable enough to canonize
2026-07-25: Added `docs/reef-first-wave-rollout.md` and
`docs/adr/ADR-0004-first-wave-reef-rollout.md`. The first rollout is now
`reef-railiance01`, `reef-coulombcore`, and `reef-ops-workstations`, with
`railiance-infra` chosen as the canonical S1 ownership repo and transitional
substrate nicknames intentionally left provisional.
## T06 - Define `railiance-fabric` and State Hub adaptation for the new repo families
```task
id: RAILIANCE-WP-0017-T06
status: done
priority: medium
state_hub_task_id: "4f47d000-6495-4163-8673-f339dd7ef41f"
```
Define the minimum graph and coordination changes needed so rails, `rapp`s, and
reefs are not only naming conventions but visible ecosystem entities.
Acceptance:
- `railiance-fabric` adaptation requirements are listed
- State Hub registration/indexing implications are listed
- the minimum fields or declarations needed in future `rail-*`, `rapp-*`, and
`reef-*` repos are recorded
2026-07-25: Added `docs/fabric-state-hub-adaptation.md`. The minimum
adaptation requirements now cover repo-family metadata, Fabric onboarding
updates, typed service/relation vocabulary, and the smallest repo-local
declaration surface future `rail-*`, `rapp-*`, and `reef-*` repos must expose.
## T07 - Launch the first migration wave into concrete repo-local follow-up work
```task
id: RAILIANCE-WP-0017-T07
status: done
priority: high
state_hub_task_id: "e762c05a-c6f1-439e-98e2-bf4d7b312a74"
```
Create the concrete follow-up workplans in the affected implementation repos for
the first migration wave.
Acceptance:
- at least one repo-local workplan exists for `rail-kubernetes`
- at least one repo-local workplan exists for a first `rapp-*` extraction
- at least one repo-local workplan exists for a first `reef-*` rollout or substrate cleanup
- this master workplan can then govern sequencing rather than holding all implementation detail itself
2026-07-25: Added the first repo-local follow-up workplans:
- `railiance-cluster/workplans/RAIL-BS-WP-0012-rail-kubernetes-extraction.md`
- `railiance-platform/workplans/RAILIANCE-WP-0012-rapp-openbao-extraction-boundary.md`
- `railiance-infra/workplans/RAIL-HO-WP-0007-first-reef-rollout-and-s1-canonicalization.md`
## Exit Criteria
- [x] The architecture baseline is recorded in `railiance-master`
- [x] `railiance-master` is registered and synced with State Hub
- [x] `rail-kubernetes` boundary is written and approved
- [x] first `rapp-*` candidates and split order are written and approved
- [x] first `reef-*` rollout decision is written and approved
- [x] Fabric and State Hub adaptation requirements are written
- [x] first migration-wave follow-up workplans exist in the affected repos
## Notes
This workplan is intended to stay small at the framework level. Once a split or
migration has a concrete owner, the implementation detail should move into the
relevant repo-local workplan rather than expanding this file into a second
control plane.

View file

@ -0,0 +1 @@