Compare commits

..

No commits in common. "dc760eb58e238af820fe56ba360f1744d0d4bc09" and "4825cc93c51ca6d1c72716e66bbaba5c21262e8b" have entirely different histories.

20 changed files with 73 additions and 712 deletions

View file

@ -1,50 +0,0 @@
# 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 (do this first)
```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`).
| Agent runtime | How to orient |
| --- | --- |
| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=railiance-enablement` is for coordination, not secret vending |
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workplans; **still** use `warden route` for credential ownership |
| **llm-connect** (inference service) | Never put secret retrieval in prompts; route custody to OpenBao/operator paths surfaced by `warden route` |
### 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 |
| activity-core → issue-core emission | activity-core + issue-core | No — `warden route show activity-core-issue-sink` |
| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only |
### Anti-patterns (do not do these)
- `POST /messages/` to `ops-warden` asking for `ISSUE_CORE_API_KEY`, `OPENROUTER_API_KEY`, etc.
- Inventing `warden secret`, `warden login`, `warden bao`, `warden tunnel` — they do not exist
- Pasting secrets into Git, State Hub, workplans, logs, or chat
### Other capabilities (reuse-surface)
Non-credential capabilities are usually discovered through **reuse-surface** federation
(`reuse-surface` registry / `capability.*` indexes). Credential routing is inlined in
every repo's agent instructions because it is high-frequency, high-risk, and easy to
get wrong.
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`

View file

@ -1,41 +1,37 @@
## First Session Protocol
Triggered when `get_domain_summary("financials")` shows **no workplans**.
Triggered when `get_domain_summary("railiance")` shows **no workstreams**.
The project is registered but work has not yet been structured.
**Step 1 — Read, don't write**
- `~/the-custodian/canon/projects/financials/project_charter_v0.1.md` — purpose, scope
- `~/the-custodian/canon/projects/financials/roadmap_v0.1.md` — planned phases
- `~/the-custodian/canon/projects/railiance/project_charter_v0.1.md` — purpose, scope
- `~/the-custodian/canon/projects/railiance/roadmap_v0.1.md` — planned phases
- Scan repo root: README, directory structure, existing code or docs
**Step 2 — Survey in-progress work**
Look for TODOs, open branches, half-finished files. Note done vs. started but incomplete.
**Step 3 — Propose workplans to Bernd**
Propose 13 workplans — each a coherent strand, weeks to months, anchored to a
**Step 3 — Propose workstreams to Bernd**
Propose 13 workstreams — each a coherent strand, weeks to months, anchored to a
roadmap phase. **Wait for approval before creating.**
**Step 4 — Write the workplan file; fix-consistency registers it (ADR-001)**
**Step 4 — Create workplan file first, then DB record (ADR-001)**
```
workplans/RAILIANCE-WP-NNNN-<slug>.md ← write this, commit it
workplans/railiance-enablement-WP-NNNN-<slug>.md ← write this first
```
Then register by running the consistency check — do **not** call
`create_workplan`/`create_task` (or legacy `create_workstream`) yourself;
manual registration duplicates what C-06 creates from the file:
```bash
statehub fix-consistency --repo railiance-enablement
Then register in the hub:
```
create_workstream(topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", title="...", owner="...", description="...")
create_task(workstream_id="<id>", title="...", priority="high|medium|low")
```
C-06 creates the hub workplan + tasks and writes `state_hub_workstream_id` /
`state_hub_task_id` back into the file (legacy field names, kept for
compatibility — they hold workplan/task IDs).
**Step 5 — Record the setup**
```
add_progress_event(
summary="First session: structured financials into N workplans, M tasks",
summary="First session: structured railiance into N workstreams, M tasks",
event_type="milestone",
topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38",
detail={"workplans": [...], "tasks_created": M}
detail={"workstreams": [...], "tasks_created": M}
)
```

View file

@ -1,5 +1,5 @@
**Purpose:** OAS S4 Developer Enablement — CI/CD pipelines, developer portal, platform templates
**Domain:** financials
**Domain:** railiance
**Repo slug:** railiance-enablement
**Topic ID:** ca369340-a64e-442e-98f1-a4fa7dc74a38

View file

@ -1,7 +1,6 @@
## Session Protocol
Dev Hub (State Hub API): http://127.0.0.1:8000
MCP server name in `~/.claude.json`: `dev-hub`
State Hub: http://127.0.0.1:8000
**Step 1 — Orient**
@ -11,7 +10,7 @@ cat .custodian-brief.md
```
Then call the MCP tool for richer cross-domain context when MCP tools are exposed:
```
get_domain_summary("financials")
get_domain_summary("railiance")
```
If MCP tools are unavailable in the current agent session, use the REST API:
```bash
@ -40,11 +39,11 @@ curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
ls workplans/
```
For each file with `status: ready`, `active`, or `blocked`, note pending
`wait`/`todo`/`progress` tasks.
`todo`/`in_progress` tasks.
**Step 4 — Present brief**
1. **Active workplans** for `financials` — title, task counts, blocking decisions
1. **Active workstreams** for `railiance` — title, task counts, blocking decisions
2. **Pending tasks** from `workplans/` + any `[repo:railiance-enablement]` hub tasks
3. **Goal guidance** — if `goal_guidance` in summary:
- `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"*
@ -52,42 +51,33 @@ For each file with `status: ready`, `active`, or `blocked`, note pending
4. **Suggested next action** — highest-priority open item
5. **SBOM status** — flag if `last_sbom_at` is unset for this repo
If no workplans: follow First Session Protocol (`first-session.md`).
If no workstreams: follow First Session Protocol (`first-session.md`).
**During work:** `record_decision()` · `add_progress_event()` · `resolve_decision()`
> State Hub is a *read model*. **Never register workplans or tasks by hand**
> (`create_workplan`, `create_task`, or the legacy `create_workstream`) — write
> the workplan file in `workplans/` and run `fix-consistency`; its C-06 check
> registers the workplan and its tasks in the hub and writes the IDs back into
> the file. Manual registration creates duplicates the moment fix-consistency
> runs. Work structure belongs in repo files (ADR-001).
>
> Terminology: "workstream" is the legacy name for workplan. Some API/frontmatter
> field names keep it for compatibility (`state_hub_workstream_id`,
> `workstream_id` params) — treat them as workplan IDs.
> State Hub is a *read model*. Bootstrap tools (`create_workstream`, `create_task`)
> are First Session Protocol only. Work structure belongs in repo files (ADR-001).
**Session close:**
With MCP tools:
```
add_progress_event(summary="...", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", workplan_id="<uuid>")
add_progress_event(summary="...", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", workstream_id="<uuid>")
```
Without MCP tools:
```bash
curl -s -X POST http://127.0.0.1:8000/progress/ \
-H "Content-Type: application/json" \
-d '{"topic_id":"ca369340-a64e-442e-98f1-a4fa7dc74a38","workplan_id":"<uuid>","event_type":"note","summary":"what changed","author":"codex"}'
-d '{"topic_id":"ca369340-a64e-442e-98f1-a4fa7dc74a38","workstream_id":"<uuid>","event_type":"note","summary":"what changed","author":"codex"}'
```
If workplan files were modified, ensure the local copy is up to date first,
then sync from the repo checkout:
If workplan files were modified, ensure the local copy is up to date first:
```bash
git pull --ff-only
statehub fix-consistency
git -C <repo_path> pull --ff-only
cd ~/state-hub && make fix-consistency REPO=railiance-enablement
```
For repos where implementation runs on a remote machine (e.g. CoulombCore),
use the pull-before-fix mode from any shell with the State Hub CLI:
use the combined target which pulls before fixing:
```bash
statehub fix-consistency --repo railiance-enablement --remote
cd ~/state-hub && make fix-consistency-remote REPO=railiance-enablement
```
**C-15** (DB task ahead of file) is normal in multi-machine workflows — writeback
will sync the file to match DB. **C-16** (repo behind remote) blocks all writes

View file

@ -1,13 +1,19 @@
## Stack
- **Language:** documentation and reusable CI/CD / platform templates (no application code yet)
- **Key deps:** none at present — S4 layer is largely unpopulated
<!-- TODO: Fill in language, frameworks, and key dependencies -->
- **Language:**
- **Key deps:**
## Dev Commands
```bash
make help # only target currently defined
```
# TODO: Fill in the standard commands for this repo
No build, test, or deploy commands exist yet. When S4 work starts (CI/CD
templates, SDKs, buildpacks), fill this file in the same change.
# Install dependencies
# Run tests
# Lint / type check
# Build / package (if applicable)
```

View file

@ -1,45 +1,28 @@
## Workplan Convention (ADR-001)
File location: `workplans/RAILIANCE-WP-NNNN-<slug>.md`
ID prefix: `RAILIANCE-WP-`
File location: `workplans/railiance-enablement-WP-NNNN-<slug>.md`
ID prefix: `RAILIANCE-WP`
Work items originate as files in this repo **before** being registered in the hub.
Canonical workplan frontmatter statuses are:
Canonical workplan/workstream frontmatter statuses are:
`proposed`, `ready`, `active`, `blocked`, `backlog`, `finished`, `archived`.
Use `proposed` for a newly drafted plan, `ready` after review against current
repo state, and `finished` when implementation is complete. `stalled` and
`needs_review` are derived health labels, not stored statuses.
Closed workplans may be moved to `workplans/archived/` with a completion-date
prefix: `YYMMDD-RAILIANCE-WP-NNNN-<slug>.md`. The frontmatter id remains
prefix: `YYMMDD-railiance-enablement-WP-NNNN-<slug>.md`. The frontmatter id remains
unchanged; the prefix is only for quick visual reference.
Small opportunistic tasks discovered during another session use **Ad Hoc Tasks**:
`workplans/ADHOC-YYYY-MM-DD.md`, workplan slug `adhoc-YYYY-MM-DD`, and task ids
`workplans/ADHOC-YYYY-MM-DD.md`, workstream slug `adhoc-YYYY-MM-DD`, and task ids
`ADHOC-YYYY-MM-DD-T01`, `T02`, etc. Use adhocs only for low-risk work completed
directly. Promote anything requiring analysis, design, approval, dependencies, or
multiple planned phases into a normal workplan.
Ecosystem todos from other agents arrive as `[repo:railiance-enablement]` hub tasks —
visible at session start. Pick one up by creating the workplan file, committing,
and running `statehub fix-consistency` — C-06 registers the workplan in the hub.
Never register by hand with `create_workplan`/`create_workstream`.
Task blocks use this shape:
```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 is `todo``progress``done`; use `wait` for waiting or
blocked work and `cancel` for stopped work.
Workplan frontmatter carries `state_hub_workstream_id` — a legacy field name
kept for compatibility ("workstream" is the old term for workplan); it holds
the hub workplan id and is written by fix-consistency. Do not edit or rename it.
visible at session start. Pick one up by creating the workplan file, then registering
the workstream.
<!-- Ralph Loop rules and HEUREKA sequence: ~/.claude/CLAUDE.md — do not duplicate here -->

View file

@ -1,29 +0,0 @@
# Canonical CI smoke template (tier 1 routing drill).
# Copy to: .forgejo/workflows/ci-smoke.yaml in consumer repos.
name: CI Smoke
on:
push:
branches:
- main
workflow_dispatch:
jobs:
host-smoke:
runs-on: self-hosted
steps:
- name: Routing probe (host runner)
run: |
set -eu
echo "repository=${GITHUB_REPOSITORY:-unknown}"
echo "sha=${GITHUB_SHA:-unknown}"
echo "runner=${RUNNER_NAME:-unknown}"
uname -a
container-smoke:
runs-on: ubuntu-latest
steps:
- name: Routing probe (container label)
run: |
set -eu
echo "container-smoke ok for ${GITHUB_REPOSITORY:-unknown}"

View file

@ -1,17 +0,0 @@
repo_classification:
standard: Repo Classification Standard
version: '1.0'
classified_at: '2026-06-22'
classified_by: agent
category: project
domain: financials
secondary_domains: []
capability_tags:
- platform
- operations
business_stake:
- technology
- operations
business_mechanics:
- coordination
- operation

View file

@ -4,7 +4,7 @@
**Purpose:** OAS S4 Developer Enablement — CI/CD pipelines, developer portal, platform templates
**Domain:** financials
**Domain:** railiance
**Repo slug:** railiance-enablement
**Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38`
**Workplan prefix:** `RAILIANCE-WP-`
@ -20,12 +20,6 @@ there is no MCP server for Codex agents.
|---------|-----|
| 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/replay after connectivity returns.
### Orient at session start
@ -33,8 +27,8 @@ statehub outbox status/replay after connectivity returns.
# Offline brief — works without hub connection
cat .custodian-brief.md
# Active workplans for this domain
curl -s "http://127.0.0.1:8000/workplans/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
# Active workstreams for this domain
curl -s "http://127.0.0.1:8000/workstreams/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
| python3 -m json.tool
# Check inbox
@ -57,20 +51,20 @@ curl -s -X POST http://127.0.0.1:8000/progress/ \
"summary": "what was done",
"event_type": "note",
"author": "codex",
"workplan_id": "<uuid>",
"workstream_id": "<uuid>",
"task_id": "<uuid>"
}'
```
Omit `workplan_id` / `task_id` when not applicable.
Omit `workstream_id` / `task_id` when not applicable.
### Update task status
```bash
curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
-H "Content-Type: application/json" \
-d '{"status": "progress"}'
# values: wait | todo | progress | done | cancel
-d '{"status": "in_progress"}'
# values: todo | in_progress | done | blocked
```
### Flag a task for human review
@ -86,10 +80,10 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
## Session Protocol
**Start:**
1. `cat .custodian-brief.md` — domain goal and open workplans (offline-safe)
1. `cat .custodian-brief.md` — domain goal and open workstreams (offline-safe)
2. Check inbox: `GET /messages/?to_agent=railiance-enablement&unread_only=true`; mark read
3. Scan workplans: `ls workplans/` — note `status: ready`, `active`, or `blocked` files and open tasks
4. Check human-needed tasks: `GET /tasks/?needs_human=true`
4. Check blocked tasks: `GET /tasks/?needs_human=true`
**During work:**
- Update task statuses in workplan files as tasks progress
@ -98,69 +92,12 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
**Close:**
1. Update workplan file task statuses to reflect progress
2. Log: `POST /progress/` with a summary of what changed
3. After workplan file changes, run:
3. Note for the custodian operator: after workplan file changes, run from
`~/state-hub`:
```bash
statehub fix-consistency
make fix-consistency REPO=railiance-enablement
```
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 (do this first)
```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`).
| Agent runtime | How to orient |
| --- | --- |
| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=railiance-enablement` is for coordination, not secret vending |
| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workplans; **still** use `warden route` for credential ownership |
| **llm-connect** (inference service) | Never put secret retrieval in prompts; route custody to OpenBao/operator paths surfaced by `warden route` |
### 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 |
| activity-core → issue-core emission | activity-core + issue-core | No — `warden route show activity-core-issue-sink` |
| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only |
### Anti-patterns (do not do these)
- `POST /messages/` to `ops-warden` asking for `ISSUE_CORE_API_KEY`, `OPENROUTER_API_KEY`, etc.
- Inventing `warden secret`, `warden login`, `warden bao`, `warden tunnel` — they do not exist
- Pasting secrets into Git, State Hub, workplans, logs, or chat
### Other capabilities (reuse-surface)
Non-credential capabilities are usually discovered through **reuse-surface** federation
(`reuse-surface` registry / `capability.*` indexes). Credential routing is inlined in
every repo's agent instructions because it is high-frequency, high-risk, and easy to
get wrong.
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`
<!-- REPO-AGENTS-EXTENSIONS -->
<!-- Append repo-specific agent instructions below this marker.
The state-hub template sync preserves content after this line. -->
This syncs task status from files into the hub DB.
---
@ -187,7 +124,7 @@ anything needing analysis, design, approval, dependencies, or multiple phases.
id: RAILIANCE-WP-NNNN
type: workplan
title: "..."
domain: financials
domain: railiance
repo: railiance-enablement
status: proposed | ready | active | blocked | backlog | finished | archived
owner: codex
@ -209,7 +146,7 @@ derived health labels, not frontmatter statuses.
` ` `task
id: RAILIANCE-WP-NNNN-T01
status: wait | todo | progress | done | cancel
status: todo | in_progress | done | blocked
priority: high | medium | low
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
` ` `
@ -217,7 +154,7 @@ state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
Task description text.
```
Status progression: `todo``progress` → `done`; use `wait` for waiting/blocked work and `cancel` for stopped work.
Status progression: `todo``in_progress` → `done` (or `blocked`)
To create a new workplan:
1. Write the file following the format above

View file

@ -8,5 +8,4 @@
@.claude/rules/stack-and-commands.md
@.claude/rules/architecture.md
@.claude/rules/repo-boundary.md
@.claude/rules/credential-routing.md
@.claude/rules/agents.md

150
INTENT.md
View file

@ -1,150 +0,0 @@
# 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 developer enablement layer - turning Railiance platform capabilities into paved paths for building, testing, packaging, and promoting workloads.**
---
## Why This Exists
A healthy platform does not automatically make delivery easy.
Developers and operators still need repeatable ways to build workloads, test
them, package them, route them through review, and hand them to application
release surfaces without inventing those paths from scratch each time.
Without a disciplined enablement layer:
* every workload invents a different pipeline,
* build and deployment templates drift,
* platform capabilities are hard to consume correctly,
* and application releases depend on undocumented operator memory.
This layer exists to provide **paved delivery paths**: shared automation,
templates, SDKs, build conventions, and self-service workflows that let
Railiance evolve faster without dissolving its layer boundaries.
---
## The Mission
> *Where we are going.*
To become the **canonical home for developer and delivery enablement** -
CI/CD pipelines, GitOps workflows, workload templates, SDKs, buildpacks,
developer portal surfaces, and promotion conventions that help source repos
move safely toward S5 application releases while consuming forge-provided
runners, registries, and artifact evidence.
This means:
* Common delivery paths are **automated and reusable**
* Build and deployment templates encode **Railiance platform expectations**
* Developers get fast feedback through **standard checks and pipelines**
* S5 can consume release artifacts through **clear handoff contracts**
* Forge runtime and runner substrate remain owned by **railiance-forge**
* Enablement improves delivery without taking ownership of app runtime
operation
---
## Core Principles
### 1. Paved Paths, Not One-Off Pipelines
The default way to build, test, package, and promote a workload should be
shared, documented, and easy to reuse.
### 2. Enablement, Not Applications
This layer helps applications reach production; it does not own their source
code, runtime configuration, or user-facing operations.
### 3. Platform-Aware Templates
Templates, SDKs, and buildpacks should encode the contracts exposed by S1-S3 so
consumers do not need to rediscover platform assumptions.
### 4. Clear Handoff to S5
CI/CD and promotion flows should produce artifacts, metadata, and evidence that
the application layer can deploy and verify without guessing.
### 5. Clear Handoff to Forge
Reusable workflows should state the forge capabilities they require: repository
events, runner labels, package credentials, registry endpoints, and artifact
evidence. This layer defines the reusable workflow shape; `railiance-forge`
owns the runtime and credentials behind it.
### 6. Fast Feedback
Developers should learn about broken builds, missing declarations, incompatible
interfaces, and release-readiness gaps before those problems reach live
application deployments.
### 7. Boundaries Preserve Velocity
Enablement should make the layered architecture easier to use, not become a
shortcut for mutating infrastructure, cluster, platform, or application
responsibilities.
---
## What This Is (Conceptually)
This layer is:
* a **developer enablement** layer
* a home for **CI/CD and GitOps workflow patterns**
* a source of **workload templates, SDKs, and buildpacks**
* a **promotion handoff** surface between source repos and S5 deployments
* a future **developer portal** and self-service entry point
* a place to codify delivery knowledge into **repeatable automation**
---
## What This Is Not
This layer is not:
* the infrastructure substrate
* the Kubernetes runtime
* the shared platform-services layer
* the application deployment and operations layer
* the source forge, package/container registry, or runner substrate layer
* the source-code home for business workloads
* a replacement for repo-owned workplans, ADRs, or implementation decisions
It is the **delivery machinery** that helps the rest of Railiance change
safely and repeatedly.
---
## Direction of Evolution
This layer is expected to evolve toward:
* Standard **pipeline templates** for Railiance workloads
* Reusable **build and image promotion** conventions
* GitOps workflows with clear **review and rollback** expectations
* Handoff contracts with `railiance-forge` for **runner labels, package
credentials, registry endpoints, and artifact evidence**
* Reusable templates that cite the forge-owned **runner/GitOps ownership
contract** before depending on privileged labels or credentials
* Developer-facing **self-service templates** and portal entry points
* SDKs and examples that make platform capabilities easy to consume correctly
* Release evidence that S5 can use for **deployment readiness**
---
## Guiding Question
> **How can Railiance make the correct delivery path the easiest path, so workloads can move from source to production with speed, evidence, and clear ownership?**

View file

@ -8,33 +8,23 @@
## One-liner
S4 Developer Enablement layer of the Railiance OAS Stack — owns reusable CI/CD
templates, developer portal paths, platform templates, SDKs, and buildpacks;
uses forge capabilities without owning forge runtime or runner substrate.
S4 Developer Enablement layer of the Railiance OAS Stack — owns CI/CD pipelines, developer portal, platform templates, SDKs, and buildpacks.
---
## Core Idea
Railiance is structured as independent repos per OAS Stack layer. This repo is
S4: the reusable tools and paved paths that allow the system to evolve. S4
depends on the platform (S3) being operational before tooling can use platform
services. S5 applications consume S4 templates and conventions, while
`railiance-forge` provides source hosting, registries, and runner substrate.
Railiance is structured as five independent repos per OAS Stack layer. This repo is S4 — the tools that allow the system to evolve. S4 depends on the platform (S3) being operational before any tooling can use platform services, and in turn S5 (applications) uses S4's CI/CD pipelines and deployment templates.
---
## In Scope
- Reusable CI/CD workflow templates and automation patterns
- CI/CD pipelines and automation tooling
- Developer portal (self-service deployment interface)
- Platform deployment templates for workloads
- SDKs and libraries for platform consumers
- Buildpacks and image builders
- Handoff contracts to `railiance-forge` for runner labels, artifact evidence,
and registry consumption
- Template references to forge-provided runner labels and credentials documented
in `/home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md`
---
@ -43,10 +33,7 @@ services. S5 applications consume S4 templates and conventions, while
- OS-level concerns → railiance-infra (S1)
- Kubernetes runtime → railiance-cluster (S2)
- Platform services → railiance-platform (S3)
- Source forge runtime, container/package registries, runner deployment,
runner labels, and runner credentials → railiance-forge
- Application deployments → railiance-apps (S5)
- App-specific workflows, release charts, and source code → app/source repos
- No re-configuration of lower layers from this repo
---
@ -55,8 +42,6 @@ services. S5 applications consume S4 templates and conventions, while
- Setting up CI/CD for the Railiance stack
- Creating or modifying developer tools and deployment templates
- Defining reusable workflow templates that run on forge-provided runners
- Defining promotion conventions and evidence formats consumed by S5
- S3 is operational and tooling layer can now be built
---
@ -65,53 +50,35 @@ services. S5 applications consume S4 templates and conventions, while
- S3 (platform services) is not yet operational (pre-condition not met)
- Infrastructure, cluster, or platform work needed (wrong layer)
- The work is Gitea/Forgejo runtime, registry endpoint, package retention,
runner deployment, or runner secret access (use `railiance-forge`)
- The work is a concrete app release or app-specific runbook (use
`railiance-apps` or the source app repo)
---
## Current State
- Status: emerging (ArgoCD deployed; no S4 workplans yet)
- Implementation: ArgoCD is deployed in the `argocd` namespace on COULOMBCORE
as a cluster addon managed from S2 for now; no S4-owned workplans yet
- Implementation: ArgoCD is deployed in the `argocd` namespace on COULOMBCORE — installed as a cluster addon (managed from S2 for now); no S4-owned workplans yet
- Stability: n/a for S4-owned content; ArgoCD itself is operational
- Usage: ArgoCD available for GitOps deployments; formal S4 tooling work begins
after S3 baseline and should consume runner/registry capabilities from
`railiance-forge`
- Usage: ArgoCD available for GitOps deployments; formal S4 tooling work begins after S3 baseline
---
## How It Fits
- Upstream dependencies: railiance-platform (S3) must be operational
- Adjacent forge provider: railiance-forge owns source hosting, registries, and
runner substrate used by S4 workflows
- Downstream consumers: railiance-apps (S5) uses CI/CD and templates from this
layer
- Often used with: railiance-platform (S3), railiance-forge, railiance-apps (S5)
- Downstream consumers: railiance-apps (S5) uses CI/CD and templates from this layer
- Often used with: railiance-platform (S3), railiance-apps (S5)
---
## Terminology
- Preferred terms: OAS Stack Level S4, developer enablement, paved path,
workflow template, promotion convention, boundary rule
- Distinguish "workflow template" from "runner substrate": templates live here;
runner deployment, labels, credentials, and health live in
`railiance-forge`.
- Preferred terms: OAS Stack Level S4, developer enablement, boundary rule
---
## Related / Overlapping
- `railiance-platform` (S3) — pre-condition; provides services that S4 tooling depends on
- `railiance-forge` — provides source forge runtime, artifact registries, and
runner substrate consumed by S4 workflows; its runner label and GitOps
boundary contract is
`/home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md`
- `railiance-apps` (S5) — consumer of S4 CI/CD and templates
---
@ -122,13 +89,13 @@ services. S5 applications consume S4 templates and conventions, while
type: infrastructure
title: CI/CD pipeline automation
description: Automated build, test, and deployment pipelines for Railiance workloads — planned for when railiance-platform (S3) is operational.
keywords: [ci, cd, pipeline, automation, template, build, deploy, gitops]
keywords: [ci, cd, pipeline, automation, build, deploy, gitops]
```
```capability
type: documentation
title: Platform deployment templates and SDKs
description: Standardised deployment templates, Helm chart patterns, SDKs, and promotion conventions enabling consistent application deployments across the Railiance stack while consuming forge-owned runners and registries.
description: Standardised deployment templates, Helm charts, and SDKs enabling consistent application deployments across the Railiance stack.
keywords: [template, sdk, helm, deployment, developer, buildpack]
```

View file

@ -1,66 +0,0 @@
# Forgejo Actions Workflow Templates
Date: 2026-07-04
Owner: `railiance-enablement` (S4)
Workplans: `RAIL-HO-WP-0005-T08`, `CUST-WP-0054-T04`
## Purpose
Canonical, copy-ready Forgejo Actions workflows for the railiance01 runner
substrate (`railiance01-build-01`, ADR-004). Forgejo/Gitea Actions on our
runners do **not** support `actions/checkout@v4` on the non-root host runner;
use **archive checkout** via `wget` instead.
Templates live in `workflows/` at repo root. Consumer repos copy into
`.forgejo/workflows/` and adjust `IMAGE_NAME` / `EXTRA_REPOS` as needed.
## Runner labels
| Label | Use |
| --- | --- |
| `self-hosted` | Host runner routing smoke, lightweight probes |
| `ubuntu-latest` | Container-isolated smoke (label routing) |
| `container-build` | DinD image build + registry push |
Org secrets (set on `coulomb` org): `REGISTRY_USER`, `REGISTRY_TOKEN`.
## Templates
| File | Tier | When to use |
| --- | ---: | --- |
| `workflows/ci-smoke.yaml` | 1 | Git+CI routing drill; infra/docs repos |
| `workflows/container-build-push.yaml` | 2 | Single-repo `Dockerfile` image publish |
| `workflows/container-build-push-multirepo.yaml` | 3 prep | Docker build with named contexts (e.g. `state-hub` + `hub-core`) |
## Adoption
```bash
mkdir -p .forgejo/workflows
cp /path/to/railiance-enablement/workflows/ci-smoke.yaml .forgejo/workflows/
# For images:
cp /path/to/railiance-enablement/workflows/container-build-push.yaml .forgejo/workflows/image.yaml
# Edit IMAGE_NAME=coulomb/<repo>
git add .forgejo/workflows && git commit -m "Add Forgejo CI from enablement templates"
git push origin main
```
## Proven consumers
| Repo | Template | Evidence |
| --- | --- | --- |
| `coulomb/glas-harness` | `ci-smoke` (in-repo) | Tier 1 pilot |
| `coulomb/key-cape` | `container-build-push` (in-repo) | Tier 2 pilot |
| `coulomb/railiance-*` | `ci-smoke` | Tier 2.5 promotion (2026-07-04) |
## Constraints
- Do not use `actions/checkout@v4` on `self-hosted` / `container-build` runners.
- Static `docker` binary via wget; runner image is non-root and cannot `apk add`.
- Reusable `workflow_call` across repos is not relied on; copy templates instead.
- Runner substrate and labels: `railiance-forge/docs/ci-runner-actions-gitops-ownership.md`.
## References
- `the-custodian/docs/forgejo-repo-migration-pilot-glas-harness.md`
- `railiance-apps/docs/forgejo-on-railiance01.md`
- `docs/adr/ADR-004-forgejo-in-cluster-actions-runner.md` (in `railiance-infra`)

View file

@ -1,12 +0,0 @@
# Capability Registry
Markdown-first capability index for federation and reuse planning.
## Authoring
1. Copy a capability entry template (see reuse-surface `templates/capability-entry.template.md`).
2. Add the row to `indexes/capabilities.yaml`.
3. Run `reuse-surface validate` from a checkout with the CLI installed.
4. Merge to `main` and verify publish with `reuse-surface establish --publish-check`.
Federation contract: reuse-surface `docs/RegistryFederation.md`.

View file

@ -1,4 +0,0 @@
version: 1
updated: '2026-06-16'
domain: helix_forge
capabilities: []

View file

@ -1,51 +0,0 @@
#!/usr/bin/env bash
# Promote a coulomb repo to Forgejo (tier 2.5): mirror, flip remotes, add ci-smoke.
set -euo pipefail
REPO="${1:?usage: promote-repo-to-forgejo.sh <repo-name> [repo-path]}"
REPO_PATH="${2:-$HOME/${REPO}}"
ORG=coulomb
FORGEJO_API="${FORGEJO_API:-https://forgejo.coulomb.social/api/v1}"
TOKEN_FILE="${FORGEJO_TOKEN_FILE:-/tmp/forgejo-tegwick-api-token}"
TEMPLATE="${PROMOTE_CI_TEMPLATE:-$HOME/railiance-enablement/workflows/ci-smoke.yaml}"
if [[ ! -f "${TOKEN_FILE}" ]]; then
echo "Missing API token at ${TOKEN_FILE}" >&2
exit 1
fi
TOKEN=$(cat "${TOKEN_FILE}")
AUTH=(-H "Authorization: token ${TOKEN}")
code=$(curl -sS -o /dev/null -w '%{http_code}' "${AUTH[@]}" "${FORGEJO_API}/repos/${ORG}/${REPO}")
if [[ "${code}" == "404" ]]; then
echo "==> Creating ${ORG}/${REPO} on Forgejo"
curl -fsS -X POST "${FORGEJO_API}/orgs/${ORG}/repos" "${AUTH[@]}" \
-H "Content-Type: application/json" \
-d "{\"name\":\"${REPO}\",\"private\":false,\"auto_init\":false}" >/dev/null
elif [[ "${code}" == "200" ]]; then
echo "==> ${ORG}/${REPO} already exists on Forgejo"
else
echo "Unexpected API status ${code} for ${ORG}/${REPO}" >&2
exit 1
fi
cd "${REPO_PATH}"
mkdir -p .forgejo/workflows
if [[ ! -f .forgejo/workflows/ci-smoke.yaml ]]; then
cp "${TEMPLATE}" .forgejo/workflows/ci-smoke.yaml
git add .forgejo/workflows/ci-smoke.yaml
git commit -m "Add Forgejo CI smoke workflow (enablement template)"
fi
if git remote get-url origin 2>/dev/null | grep -q forgejo-remote; then
echo "==> Remotes already on Forgejo"
else
git remote rename origin gitea
git remote add origin "forgejo-remote:${ORG}/${REPO}.git"
echo "==> Remotes: origin=forgejo-remote, gitea=legacy"
fi
echo "==> Pushing ${REPO_PATH} to Forgejo"
git push -u origin main
echo "==> Promoted ${REPO}"

View file

@ -1,29 +0,0 @@
# Canonical CI smoke template (tier 1 routing drill).
# Copy to: .forgejo/workflows/ci-smoke.yaml in consumer repos.
name: CI Smoke
on:
push:
branches:
- main
workflow_dispatch:
jobs:
host-smoke:
runs-on: self-hosted
steps:
- name: Routing probe (host runner)
run: |
set -eu
echo "repository=${GITHUB_REPOSITORY:-unknown}"
echo "sha=${GITHUB_SHA:-unknown}"
echo "runner=${RUNNER_NAME:-unknown}"
uname -a
container-smoke:
runs-on: ubuntu-latest
steps:
- name: Routing probe (container label)
run: |
set -eu
echo "container-smoke ok for ${GITHUB_REPOSITORY:-unknown}"

View file

@ -1,61 +0,0 @@
# Multi-repo Docker build template for tier-3 prep (e.g. state-hub + hub-core).
# Copy to: .forgejo/workflows/image.yaml and set PRIMARY_REPO + EXTRA_REPOS.
# Uses archive checkout (no actions/checkout; non-root runner has no git).
# Dockerfile must reference named contexts, e.g.:
# COPY --from=hub_core_src pyproject.toml /tmp/hub-core/pyproject.toml
name: Build and Publish Multi-Context Image
on:
push:
branches:
- main
paths:
- ".forgejo/workflows/image.yaml"
- "Dockerfile"
workflow_dispatch:
env:
REGISTRY: forgejo.coulomb.social
IMAGE_NAME: coulomb/REPLACE_ME
DOCKER_HOST: tcp://127.0.0.1:2375
# Space-separated coulomb/repo@context_name entries for extra build contexts.
# Example: "coulomb/hub-core@hub_core_src"
EXTRA_REPOS: "coulomb/hub-core@hub_core_src"
jobs:
build-and-push:
runs-on: container-build
steps:
- name: Build and push image
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
set -eu
REF="${GITHUB_SHA:-main}"
mkdir -p buildctx "${HOME}/bin"
wget -qO /tmp/primary.tar.gz \
"https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz"
tar xzf /tmp/primary.tar.gz -C buildctx --strip-components=1
BUILD_ARGS=()
for spec in ${EXTRA_REPOS}; do
repo="${spec%@*}"
ctx="${spec#*@}"
extra_ref="${REF}"
wget -qO "/tmp/${ctx}.tar.gz" \
"https://forgejo.coulomb.social/${repo}/archive/${extra_ref}.tar.gz"
mkdir -p "/tmp/ctx-${ctx}"
tar xzf "/tmp/${ctx}.tar.gz" -C "/tmp/ctx-${ctx}" --strip-components=1
BUILD_ARGS+=(--build-context "${ctx}=/tmp/ctx-${ctx}")
done
wget -qO- https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \
| tar xz --strip-components=1 -C "${HOME}/bin" docker/docker
export PATH="${HOME}/bin:${PATH}"
echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" -u "${REGISTRY_USER}" --password-stdin
SHORT="${REF:0:7}"
IMAGE="${REGISTRY}/${IMAGE_NAME}"
docker build "${BUILD_ARGS[@]}" \
-t "${IMAGE}:latest" -t "${IMAGE}:main-${SHORT}" buildctx
docker push "${IMAGE}:latest"
docker push "${IMAGE}:main-${SHORT}"
echo "pushed ${IMAGE}:latest and ${IMAGE}:main-${SHORT}"

View file

@ -1,48 +0,0 @@
# Canonical single-repo image build template (tier 2).
# Copy to: .forgejo/workflows/image.yaml and set IMAGE_NAME.
# Requires org secrets: REGISTRY_USER, REGISTRY_TOKEN
# Runner label: container-build (DinD sidecar on railiance01-build-01)
name: Build and Publish Container Image
on:
push:
branches:
- main
paths:
- ".forgejo/workflows/image.yaml"
- "Dockerfile"
- "src/**"
workflow_dispatch:
env:
REGISTRY: forgejo.coulomb.social
# Set per repo, e.g. coulomb/key-cape
IMAGE_NAME: coulomb/REPLACE_ME
DOCKER_HOST: tcp://127.0.0.1:2375
jobs:
build-and-push:
runs-on: container-build
steps:
- name: Build and push image
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
set -eu
REF="${GITHUB_SHA:-main}"
mkdir -p buildctx "${HOME}/bin"
wget -qO /tmp/repo.tar.gz \
"https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz"
tar xzf /tmp/repo.tar.gz -C buildctx --strip-components=1
wget -qO- https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \
| tar xz --strip-components=1 -C "${HOME}/bin" docker/docker
export PATH="${HOME}/bin:${PATH}"
docker version
echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" -u "${REGISTRY_USER}" --password-stdin
SHORT="${REF:0:7}"
IMAGE="${REGISTRY}/${IMAGE_NAME}"
docker build -t "${IMAGE}:latest" -t "${IMAGE}:main-${SHORT}" buildctx
docker push "${IMAGE}:latest"
docker push "${IMAGE}:main-${SHORT}"
echo "pushed ${IMAGE}:latest and ${IMAGE}:main-${SHORT}"