Compare commits

...

142 Commits

Author SHA1 Message Date
20316c533f Recorded decision 2026-07-04 00:31:34 +02:00
58a2cfac5c Regenerate agent instructions: workstream -> workplan terminology
Registration guidance now prescribes file-first + fix-consistency (C-06)
instead of manual create_workplan/create_workstream calls; progress-event
examples use workplan_id; legacy field names annotated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 01:47:46 +02:00
7312ed3767 Archive closed workplans to workplans/archived/ (ADR-001)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 00:25:41 +02:00
f9e661ec69 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-07-02:
  - update .custodian-brief.md for railiance-fabric
2026-07-02 00:24:01 +02:00
f57a5c1dce Repo hygiene: fill stack-and-commands, normalize workplan statuses
- Fill .claude/rules/stack-and-commands.md (was an empty TODO template)
- Normalize workplan frontmatter statuses to canonical vocabulary
  (completed/done -> finished) per ADR-001

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 00:21:49 +02:00
757770b42f Record whynot-design publish lane decisions 2026-07-01 20:07:20 +02:00
635521406f Normalize agent instructions and workplan frontmatter (STATE-WP-0067)
- Align agent files with on-disk workplan prefixes (infer from workplan ids)
- Set workplan domain to registered domain_slug; add topic_slug where applicable
- Repair frontmatter delimiter formatting; migrate legacy task status literals
- Regenerate AGENTS.md, CLAUDE.md, and .claude/rules from State Hub templates
2026-06-22 23:16:28 +02:00
2afeb86ed2 Add .repo-classification.yaml (CUST-WP-0050 T11 agent first-pass) 2026-06-22 17:47:41 +02:00
caa1e4100d Add credential routing instructions for all agent runtimes
Propagate shared credential-routing section (Codex, Claude, Grok, llm-connect)
from state-hub template via scripts/propagate_credential_routing.py.
2026-06-18 22:48:39 +02:00
dae9e3409a Add capability registry index scaffold (REUSE-WP-0014-T07 B05) 2026-06-16 01:59:28 +02:00
e23ed0c06b Document semantic attractors concept 2026-06-06 00:52:21 +02:00
fe2e98e2a4 Track generated State Hub decision log 2026-06-05 22:23:38 +02:00
7cb943ed41 Finish zone drag verification workplan 2026-06-05 21:38:03 +02:00
31841d0f1c chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-06-05:
  - update .custodian-brief.md for railiance-fabric
2026-06-05 21:36:10 +02:00
40b409cd92 Sync fabric workplan IDs 2026-06-05 17:12:48 +02:00
0b5d295800 Declare forge graph contracts 2026-06-05 17:10:31 +02:00
5dff7f14da chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-06-05:
  - update .custodian-brief.md for railiance-fabric
2026-06-05 17:07:16 +02:00
5e89f6a075 chore: add graph explorer make target 2026-06-03 17:24:58 +02:00
f09f110e77 feat: add zone layout selector 2026-05-25 03:17:23 +02:00
558e0dc157 feat: stabilize graph zone containers 2026-05-25 02:08:45 +02:00
0f7b7d1fed feat: add draggable graph zones 2026-05-25 01:09:05 +02:00
9b612447ca docs: finish zone entity workplan 2026-05-25 00:43:34 +02:00
a7a22a673f feat: prototype graph zone collapse 2026-05-25 00:40:13 +02:00
296ac051a7 feat: persist graph explorer zone state 2026-05-25 00:27:10 +02:00
1ad432270b feat: show zone resolver diagnostics 2026-05-25 00:09:18 +02:00
f1cd74dc7b feat: resolve graph explorer zones from definitions 2026-05-25 00:00:28 +02:00
d060b1c896 feat: add zone visualization resolver 2026-05-24 18:10:30 +02:00
fdee0b0855 chore: activate zone visualization workplan 2026-05-24 17:59:18 +02:00
f41d0da831 docs: define zone visualization engine workplan 2026-05-24 17:56:40 +02:00
5a2d987b6a feat: render graph explorer zone boundaries 2026-05-24 17:02:12 +02:00
ea81533172 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 17:00:39 +02:00
c26a725f92 docs: add zone boundary overlay workplan 2026-05-24 16:24:00 +02:00
8176d88926 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 16:22:31 +02:00
ff1c4ce05b feat: add deployment zone overlays 2026-05-24 15:55:05 +02:00
62236f6453 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 15:50:37 +02:00
d9f1f3f71a feat: canonicalize duplicate repo identities 2026-05-24 14:08:40 +02:00
5c9c2f281e chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 14:07:24 +02:00
ea2fa1203b docs: define deployment zone overlays 2026-05-24 12:58:18 +02:00
e60e8d5bb4 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 12:56:36 +02:00
735867392e feat: bootstrap accountability-root fabric snapshot 2026-05-24 10:41:29 +02:00
7956415924 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 10:39:46 +02:00
355b7be66a feat: compare accountability update deltas 2026-05-24 10:05:39 +02:00
071a4c49e3 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 10:01:39 +02:00
a55f1a45d6 feat: resolve accountability ownership reviews 2026-05-24 09:53:44 +02:00
c27d71a511 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 09:52:16 +02:00
ab7e0ccab1 feat: persist accountability evidence identities 2026-05-24 09:38:57 +02:00
26f1913d51 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 09:37:26 +02:00
999f90dcbe feat: collect accountability root evidence 2026-05-24 03:11:47 +02:00
43d3866b18 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 03:10:45 +02:00
a1bd9df8e4 feat: define accountability root manifest 2026-05-24 03:00:29 +02:00
455362153d chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 02:59:03 +02:00
f4aa4aa996 docs: finish financial fabric reset guidance 2026-05-24 01:37:05 +02:00
9717b18b02 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 01:35:01 +02:00
13188a6ae1 feat: seed railiance financial baseline 2026-05-24 01:20:07 +02:00
7d9b49764b chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 01:18:25 +02:00
63379ca329 feat: version state hub fabric export contract 2026-05-24 01:06:49 +02:00
be0299e528 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 01:05:49 +02:00
3a47a92729 feat: validate financial fabric graph exports 2026-05-24 00:57:14 +02:00
3318d2c1b9 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 00:56:00 +02:00
39762551c0 docs: audit financial fabric vnext contract 2026-05-24 00:42:39 +02:00
0874446994 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 00:38:19 +02:00
7db9c3cbf2 docs: define financial fabric architecture 2026-05-24 00:25:59 +02:00
a1e99d9b34 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-24:
  - update .custodian-brief.md for railiance-fabric
2026-05-24 00:05:05 +02:00
b70e74fde5 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-23:
  - update .custodian-brief.md for railiance-fabric
2026-05-23 21:53:28 +02:00
d3fe1e3ed3 Finish WP-0016 after State Hub graph ingest 2026-05-23 21:52:47 +02:00
fd859998c4 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-23:
  - update .custodian-brief.md for railiance-fabric
2026-05-23 16:05:52 +02:00
3e181e58ff Record WP-0016 reset reingest outcome 2026-05-23 16:05:18 +02:00
f6dbf31db1 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-23:
  - update .custodian-brief.md for railiance-fabric
2026-05-23 14:54:24 +02:00
9c22d3e0df Add canon reset and reingest guardrails 2026-05-23 14:52:57 +02:00
653411ffb8 refactoring for canon conformity 2026-05-23 14:00:59 +02:00
0193c97094 Register canon-aligned graph reset workplan 2026-05-23 07:34:13 +02:00
01bc4f3efe Refine runtime entity taxonomy 2026-05-21 21:28:34 +02:00
072fa8f7a7 Collapse duplicate repository graph nodes 2026-05-21 01:04:22 +02:00
a8e67db9e9 Discover runtime topology facts 2026-05-21 00:25:45 +02:00
af4132c182 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-21:
  - update .custodian-brief.md for railiance-fabric
2026-05-21 00:24:14 +02:00
78e8d381c2 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-21:
  - update .custodian-brief.md for railiance-fabric
2026-05-21 00:05:40 +02:00
e3440df163 Close path-scoped duplicate identity workplan 2026-05-20 23:45:51 +02:00
36d4b895f9 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-20:
  - update .custodian-brief.md for railiance-fabric
2026-05-20 23:44:21 +02:00
5e0ffea585 Fix path-scoped duplicate detection 2026-05-20 23:42:21 +02:00
56b73dbab0 Plan path-scoped duplicate identity fix 2026-05-20 23:38:36 +02:00
c73815a115 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-20:
  - update .custodian-brief.md for railiance-fabric
2026-05-20 23:37:40 +02:00
9ad2750965 Add baseline rollout workplan 2026-05-20 23:16:08 +02:00
0db4292db5 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-20:
  - update .custodian-brief.md for railiance-fabric
2026-05-20 23:15:01 +02:00
4fdf552f73 Implement operational discovery rescan loops 2026-05-20 22:52:26 +02:00
50810ffd54 new workplan rescan 2026-05-20 00:57:26 +02:00
6746943c0b chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 20:52:53 +02:00
babbe88a46 Close repo reality scanner rollout 2026-05-19 18:36:48 +02:00
be7252019f Add multi-repo discovery scan orchestration 2026-05-19 18:29:04 +02:00
68cf01aa39 Add discovery registry review flow 2026-05-19 15:40:57 +02:00
0b093741e2 Add discovery connector follow-up 2026-05-19 14:55:08 +02:00
239ad11547 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 04:51:37 +02:00
17356a41d6 Add discovery reconciliation engine 2026-05-19 04:49:08 +02:00
73f7cdbdb5 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 04:36:48 +02:00
a76c6a4aea Add llm-assisted discovery extraction 2026-05-19 04:35:35 +02:00
bc25eb6871 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 03:56:48 +02:00
afd8b3d608 Add deterministic repo scanner 2026-05-19 03:55:50 +02:00
17bd23e79b chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 03:38:32 +02:00
1c0995004e Add discovery snapshot contract 2026-05-19 03:37:05 +02:00
e150270511 Register repo reality scanner workplan 2026-05-19 02:29:33 +02:00
5523b8f493 Add repo reality scanner workplan 2026-05-19 02:26:02 +02:00
edf2062a7a chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 02:12:52 +02:00
9f4d8a3958 Close graph explorer refinement workplan 2026-05-19 02:12:00 +02:00
0e2adcbe84 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 01:47:53 +02:00
93593a5b56 Polish graph explorer orientation workflows 2026-05-19 01:46:23 +02:00
33f0a52068 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 01:29:11 +02:00
5777c283f7 Document graph explorer adapter boundary 2026-05-19 01:27:53 +02:00
6fa1d1d824 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 01:17:59 +02:00
28511db909 Add graph explorer filter rules 2026-05-19 01:16:18 +02:00
99993c7cb2 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 00:53:18 +02:00
4f4f28a6d5 Add graph explorer bubble help 2026-05-19 00:51:38 +02:00
98a747dd5a Add graph label density controls 2026-05-19 00:27:09 +02:00
d9c5bf1bd4 Add graph selection anchors 2026-05-19 00:16:57 +02:00
88ccc973e4 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-19:
  - update .custodian-brief.md for railiance-fabric
2026-05-19 00:00:19 +02:00
035381a9df Refine graph explorer controls 2026-05-18 23:58:58 +02:00
2a2616653f Refine graph explorer UI workplan 2026-05-18 23:25:24 +02:00
95901feb0d chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 23:22:29 +02:00
e6a74fb474 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 22:40:09 +02:00
5b6e4faf68 Tune graph layout affinities 2026-05-18 22:39:12 +02:00
b2165b5a2a Register Fabric registry service 2026-05-18 20:57:58 +02:00
dc3051aa8e Sync UI refinement workplan ids 2026-05-18 20:43:54 +02:00
29fe6a941f chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 20:42:16 +02:00
aa42b6f84c Plan graph explorer UI refinement 2026-05-18 20:41:22 +02:00
49dc23f919 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 20:19:34 +02:00
229191c802 Document graph explorer operations 2026-05-18 20:18:56 +02:00
004e3cb976 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 20:15:01 +02:00
55db37b1ca Complete graph orientation workflows 2026-05-18 20:14:07 +02:00
43ed6e69e0 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 18:36:52 +02:00
01840d848f Add graph orientation details 2026-05-18 18:36:15 +02:00
8a31258785 Harden graph explorer controls 2026-05-18 18:31:25 +02:00
eea1156fd6 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 18:20:49 +02:00
d31b1376c8 Add graph explorer UI shell 2026-05-18 17:11:36 +02:00
d2056c9046 Complete graph explorer projection 2026-05-18 17:04:17 +02:00
91f329f878 Refresh agent instruction files 2026-05-18 16:55:51 +02:00
eec7e2a9f6 Start graph explorer contract 2026-05-18 14:08:01 +02:00
ae4f567a2b Refine interactive Fabric map workplan 2026-05-18 13:49:09 +02:00
251637c1b4 chore(consistency): sync task status from DB [auto]
Updated by fix-consistency on 2026-05-18:
  - update .custodian-brief.md for railiance-fabric
2026-05-18 13:46:28 +02:00
9f1f93217e Propose interactive Fabric map workplan 2026-05-18 12:50:59 +02:00
2f06d2a277 Onboard all local repos to Fabric registry 2026-05-18 12:15:15 +02:00
3ddf76252b Add multi-repo registry onboarding 2026-05-17 23:22:55 +02:00
f372d5f0e4 Establish multi-repo registry onboarding workplan 2026-05-17 22:47:31 +02:00
bc73b05566 Harden registry API and schema validation 2026-05-17 22:33:21 +02:00
5c20f62fbb Link registry workplans to State Hub 2026-05-17 21:55:57 +02:00
173 changed files with 40692 additions and 240 deletions

20
.claude/rules/agents.md Normal file
View File

@@ -0,0 +1,20 @@
## Kaizen Agents
Specialized agent personas available on demand via the state-hub MCP.
**Discover:** `list_kaizen_agents()` — returns all agents with name, description, category
**Load:** `get_kaizen_agent("tdd-workflow")` — returns full instructions; read and follow them
Common agents:
| Agent | Category | When to use |
|-------|----------|-------------|
| `tdd-workflow` | testing | Step-by-step TDD8 workflow for any feature |
| `code-refactoring` | quality | Code quality analysis and safe refactoring |
| `test-maintenance` | testing | Diagnose and fix failing tests |
| `requirements-engineering` | process | Prevent interface/mock mismatches upfront |
| `keepaTodofile` | process | Maintain TODO.md during work |
| `project-management` | process | Track status, determine next steps |
| `datamodel-optimization` | quality | Optimize dataclasses and data structures |
All 17 agents: call `list_kaizen_agents()` for the full list.

View File

@@ -0,0 +1,8 @@
## Architecture
<!-- TODO: Describe the key design decisions and component structure.
Key modules, data flows, external integrations, state machines, etc. -->
## Quick Reference
`~/state-hub/mcp_server/TOOLS.md` — MCP tool reference

View File

@@ -0,0 +1,50 @@
# 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-fabric` 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

@@ -0,0 +1,42 @@
## First Session Protocol
Triggered when `get_domain_summary("financials")` shows **no workplans**.
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
- 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
roadmap phase. **Wait for approval before creating.**
**Step 4 — Write the workplan file; fix-consistency registers it (ADR-001)**
```
workplans/RAILIANCE-WP-NNNN-<slug>.md ← write this, commit it
```
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-fabric
```
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",
event_type="milestone",
topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38",
detail={"workplans": [...], "tasks_created": M}
)
```
<!-- Delete or archive this file once past first session -->

View File

@@ -0,0 +1,8 @@
## Repo boundary
This repo owns **railiance-fabric** only. It does not own:
<!-- TODO: List what belongs in adjacent repos, e.g.:
- SSH key management → railiance-infra/
- State hub code → state-hub/
-->

View File

@@ -0,0 +1,5 @@
**Purpose:** railiance-fabric - (fill in purpose)
**Domain:** financials
**Repo slug:** railiance-fabric
**Topic ID:** ca369340-a64e-442e-98f1-a4fa7dc74a38

View File

@@ -0,0 +1,94 @@
## Session Protocol
Dev Hub (State Hub API): http://127.0.0.1:8000
MCP server name in `~/.claude.json`: `dev-hub`
**Step 1 — Orient**
Read the offline-safe brief first — it works without a live hub connection:
```bash
cat .custodian-brief.md
```
Then call the MCP tool for richer cross-domain context when MCP tools are exposed:
```
get_domain_summary("financials")
```
If MCP tools are unavailable in the current agent session, use the REST API:
```bash
curl -s "http://127.0.0.1:8000/state/summary" | python3 -m json.tool
```
If the hub is offline: `cd ~/state-hub && make api`
**Step 2 — Check inbox**
With MCP tools:
```
get_messages(to_agent="railiance-fabric", unread_only=True)
```
Mark read with `mark_message_read(message_id)`. Reply or act on coordination
requests before proceeding.
Without MCP tools:
```bash
curl -s "http://127.0.0.1:8000/messages/?to_agent=railiance-fabric&unread_only=true" \
| python3 -m json.tool
curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
-H "Content-Type: application/json" -d '{}'
```
**Step 3 — Scan workplans**
```bash
ls workplans/
```
For each file with `status: ready`, `active`, or `blocked`, note pending
`wait`/`todo`/`progress` tasks.
**Step 4 — Present brief**
1. **Active workplans** for `financials` — title, task counts, blocking decisions
2. **Pending tasks** from `workplans/` + any `[repo:railiance-fabric]` hub tasks
3. **Goal guidance** — if `goal_guidance` in summary:
- `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"*
- `alignment_warnings`: flag if active work is not aligned with current goal
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`).
**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.
**Session close:**
With MCP tools:
```
add_progress_event(summary="...", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", workplan_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"}'
```
If workplan files were modified, ensure the local copy is up to date first,
then sync from the repo checkout:
```bash
git pull --ff-only
statehub fix-consistency
```
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:
```bash
statehub fix-consistency --repo railiance-fabric --remote
```
**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
until you pull — intentional to prevent clobbering remote progress.

View File

@@ -0,0 +1,14 @@
## Stack
- **Language:** Python ≥3.12 (`railiance_fabric` package)
- **Key deps:** jsonschema, PyYAML; SQLite registry at `.railiance-fabric/registry.sqlite3`
## Dev Commands
```bash
python3 -m pytest tests/ # run the test suite
make graph-explorer # registry-backed graph explorer (HOST/PORT/REGISTRY_DB overridable)
python3 -m railiance_fabric.server --db .railiance-fabric/registry.sqlite3
```
Local-only tooling — no production deploy surface in this repo.

View File

@@ -0,0 +1,45 @@
## Workplan Convention (ADR-001)
File location: `workplans/RAILIANCE-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:
`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
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
`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-fabric]` 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.
<!-- Ralph Loop rules and HEUREKA sequence: ~/.claude/CLAUDE.md — do not duplicate here -->

View File

@@ -1,40 +1,18 @@
# Railiance Fabric Brief
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — railiance-fabric
Domain: railiance
Repo slug: railiance-fabric
State Hub topic ID: ca369340-a64e-442e-98f1-a4fa7dc74a38
State Hub workstream ID: bd190990-8e68-49a3-9ce4-0ba89103ea54
**Domain:** financials
**Last synced:** 2026-07-01 22:24 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Purpose
## Active Workstreams
Railiance Fabric defines the repo-owned declaration model for the Railiance
ecosystem graph: services, capabilities, interfaces, dependencies, bindings,
validation, discovery queries, and State Hub export contracts.
*(none — repo may need first-session setup)*
## Current Work
---
## MCP Orientation (when available)
- `RAIL-FAB-WP-0001` is active and establishes the first ecosystem graph model.
- `T01` is done: `INTENT.md` defines the vocabulary and source-of-truth
boundary.
- `T02` is done: `docs/declaration-schema.md`, `schemas/`, and
`examples/declarations/` define the first declaration schema baseline.
- `T03` is done: `catalog/` and `docs/type-catalog.md` define the first
capability/interface type catalog.
- `T04` is done: `fabric/` contains seed declarations for the first Railiance
ecosystem provider/consumer graph.
- `T05` is done: `railiance-fabric validate` loads and validates schema,
catalog, reference, provider, source-link, and cycle checks.
- `T06` is done: discovery queries and JSON/Mermaid exports are available from
the CLI.
- `T07` is done: `docs/state-hub-integration.md` defines the graph export and
proposed hub read-model ingestion path.
- `T08` is done: `docs/adoption-guide.md` and `docs/first-rollout.md` define
how other repos should adopt and promote the seed declarations.
- All tasks in `RAIL-FAB-WP-0001` are done.
## State Hub
- Local API: `http://127.0.0.1:8000`
- Remote tunnel: `http://127.0.0.1:18000`
- After changing workplan files, sync from `~/the-custodian/state-hub` with:
`make fix-consistency REPO=railiance-fabric`
If the state-hub MCP server is reachable, call:
`get_domain_summary("financials")`
This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source.

5
.gitignore vendored
View File

@@ -52,6 +52,10 @@ coverage.xml
.pytest_cache/
cover/
# Railiance Fabric local runtime state
.railiance-fabric/
.fabric-discovery/
# Translations
*.mo
*.pot
@@ -173,4 +177,3 @@ cython_debug/
# PyPI configuration file
.pypirc

17
.repo-classification.yaml Normal file
View File

@@ -0,0 +1,17 @@
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

117
AGENTS.md
View File

@@ -2,12 +2,12 @@
## Repo Identity
**Purpose:** Railiance Fabric defines the repo-owned declaration model, validation tooling, graph queries, and State Hub export contract for the Railiance ecosystem graph.
**Purpose:** railiance-fabric - (fill in purpose)
**Domain:** railiance
**Domain:** financials
**Repo slug:** railiance-fabric
**Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38`
**Workplan prefix:** `RAIL-FAB-WP-`
**Workplan prefix:** `RAILIANCE-WP-`
---
@@ -20,6 +20,12 @@ 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
@@ -27,8 +33,8 @@ there is no MCP server for Codex agents.
# Offline brief — works without hub connection
cat .custodian-brief.md
# Active workstreams for this domain
curl -s "http://127.0.0.1:8000/workstreams/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
# Active workplans for this domain
curl -s "http://127.0.0.1:8000/workplans/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
| python3 -m json.tool
# Check inbox
@@ -51,20 +57,20 @@ curl -s -X POST http://127.0.0.1:8000/progress/ \
"summary": "what was done",
"event_type": "note",
"author": "codex",
"workstream_id": "<uuid>",
"workplan_id": "<uuid>",
"task_id": "<uuid>"
}'
```
Omit `workstream_id` / `task_id` when not applicable.
Omit `workplan_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": "in_progress"}'
# values: todo | in_progress | done | blocked
-d '{"status": "progress"}'
# values: wait | todo | progress | done | cancel
```
### Flag a task for human review
@@ -80,10 +86,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 workstreams (offline-safe)
1. `cat .custodian-brief.md` — domain goal and open workplans (offline-safe)
2. Check inbox: `GET /messages/?to_agent=railiance-fabric&unread_only=true`; mark read
3. Scan workplans: `ls workplans/` — note `status: active` files and open tasks
4. Check blocked tasks: `GET /tasks/?needs_human=true`
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`
**During work:**
- Update task statuses in workplan files as tasks progress
@@ -92,12 +98,69 @@ 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. Note for the custodian operator: after workplan file changes, run from
`~/the-custodian/state-hub`:
3. After workplan file changes, run:
```bash
make fix-consistency REPO=railiance-fabric
statehub fix-consistency
```
This syncs task status from files into the hub DB.
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-fabric` 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. -->
---
@@ -106,10 +169,10 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
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/RAIL-FAB-WP-NNNN-<slug>.md`
**File location:** `workplans/RAILIANCE-WP-NNNN-<slug>.md`
**Archived location:** completed workplans may move to
`workplans/archived/YYMMDD-RAIL-FAB-WP-NNNN-<slug>.md`. The `YYMMDD` prefix is
**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
@@ -121,12 +184,12 @@ anything needing analysis, design, approval, dependencies, or multiple phases.
```yaml
---
id: RAIL-FAB-WP-NNNN
id: RAILIANCE-WP-NNNN
type: workplan
title: "..."
domain: railiance
domain: financials
repo: railiance-fabric
status: active | done
status: proposed | ready | active | blocked | backlog | finished | archived
owner: codex
topic_slug: ...
created: "YYYY-MM-DD"
@@ -135,14 +198,18 @@ 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 Title
` ` `task
id: RAIL-FAB-WP-NNNN-T01
status: todo | in_progress | done | blocked
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
` ` `
@@ -150,7 +217,7 @@ state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
Task description text.
```
Status progression: `todo` → `in_progress` → `done` (or `blocked`)
Status progression: `todo` → `progress` → `done`; use `wait` for waiting/blocked work and `cancel` for stopped work.
To create a new workplan:
1. Write the file following the format above

12
CLAUDE.md Normal file
View File

@@ -0,0 +1,12 @@
# railiance-fabric — Claude Code Instructions
@SCOPE.md
@.claude/rules/repo-identity.md
@.claude/rules/session-protocol.md
@.claude/rules/first-session.md
@.claude/rules/workplan-convention.md
@.claude/rules/stack-and-commands.md
@.claude/rules/architecture.md
@.claude/rules/repo-boundary.md
@.claude/rules/credential-routing.md
@.claude/rules/agents.md

93
DECISIONS.md Normal file
View File

@@ -0,0 +1,93 @@
# Decision Log
_Auto-generated by the Custodian State Hub._
## State Hub workstation Postgres migration approval
**Date:** 2026-06-03
**Decided by:** codex
Superseded by WP-0004 T09 cancellation and CUST-WP-0038 ownership of State Hub HA migration, including hostname, registry, exposure model, HA database/storage, restore drills, and production data migration approval.
---
## activity-core deployment architecture
**Date:** 2026-06-03
**Decided by:** codex
Superseded by completed WP-0004 outcome: activity-core was deployed as a K3s production service on railiance01 on 2026-05-22; the packaging architecture question is no longer blocking this workplan.
---
## Review CCR-2026-0001 whynot-design npm publish token lane
**Date:** 2026-06-27
**Decided by:** human
APPROVE: scoped path and confirmed binding are acceptable
---
## Review CCR-2026-0001 corrected whynot-design npm publish token lane
**Date:** 2026-06-27
**Decided by:** human
APPROVE: We fixed the path using coulomb as the org/tenant.
---
## Forgejo hostname and exposure model
**Date:** 2026-07-02
**Decided by:** human
the hostname shall be forgejo.coulomb.social. The exposure model is private repos by default. We will use the transition from gitea to forgejo for closing down public access and establishing credential handling to have convenience when working with the repos. Gitea can and should remain reachable during transition.
---
## Forgejo SMTP and sender identity
**Date:** 2026-07-02
**Decided by:** human
We will use forgejo@coulomb.social
---
## Forgejo package registry scope
**Date:** 2026-07-02
**Decided by:** human
We should support the full range from the start.
---
## Forgejo Actions runner isolation model
**Date:** 2026-07-02
**Decided by:** human
we will try to go with isolated host runners, with least-privilege credential boundaries.
---
## Forgejo backup target and restore cadence
**Date:** 2026-07-02
**Decided by:** human
We will need to figure out the details, but i want to use backup.coulomb.social as the hostname with a backend we need to figure out yet.
---
## Forgejo cutover and rollback strategy
**Date:** 2026-07-02
**Decided by:** human
We will do a staged migration and lock the gitea repos of transitioned repos but keep gitea until everything has been transfered and just then start a 14day trial phase and after that retire gitea to the backup.
---

21
Makefile Normal file
View File

@@ -0,0 +1,21 @@
PYTHON ?= python3
REGISTRY_DB ?= .railiance-fabric/registry.sqlite3
HOST ?= 127.0.0.1
PORT ?= 8765
.DEFAULT_GOAL := help
.PHONY: help graph-explorer registry
help:
@printf "Available targets:\n"
@printf " make graph-explorer Start the registry-backed graph explorer on HOST:PORT.\n"
@printf " Defaults: HOST=$(HOST), PORT=$(PORT), REGISTRY_DB=$(REGISTRY_DB)\n"
@printf " make registry Alias for graph-explorer.\n"
graph-explorer:
@mkdir -p $(dir $(REGISTRY_DB))
@echo "Starting Railiance Fabric graph explorer at http://$(HOST):$(PORT)/ui/graph-explorer"
$(PYTHON) -m railiance_fabric.server --db "$(REGISTRY_DB)" --host "$(HOST)" --port "$(PORT)"
registry: graph-explorer

View File

@@ -1,11 +1,20 @@
# Railiance Fabric
Railiance Fabric defines the repo-owned declaration model for the Railiance
ecosystem graph.
Railiance Fabric models the durable infrastructure-responsibility graph of the
Railiance netkingdom.
It will hold schemas, seed declarations, validation tools, graph queries, and
State Hub export contracts for services, capabilities, interfaces,
dependencies, and bindings across Railiance repositories.
Fabric is bounded by financial and operational accountability: who pays for the
infrastructure, who is accountable for keeping it alive, and which durable
interfaces create value across fabric and subfabric boundaries.
It holds schemas, discovery tools, registry services, graph queries, and State
Hub export contracts for services, machines, repositories, deployables,
endpoints, ownership, dependencies, and bindings across Railiance deployment
realities.
See `docs/FabricDiscoveryAndUpdate.md` for the current architecture direction
for fabric boundaries, king/lord/tenant ownership, discovery, rebuilds, and
update loops.
## Validate Declarations
@@ -35,22 +44,59 @@ railiance-fabric unresolved
railiance-fabric blast-radius openbao-kv-v2-mount
railiance-fabric export --format json
railiance-fabric export --format mermaid
railiance-fabric export --format graph-explorer
railiance-fabric export --format financial
```
See `docs/discovery-queries.md` for command details.
## Financial Fabric Baseline
The current financial Fabric model starts from
`fabric/financial/railiance-netkingdom.yaml`. It defines the Railiance
netkingdom, the king, the current lord, the one active Railiance fabric, and
the default ownership rules used while Railiance still has one effective payer.
`railiance-fabric export --format financial` projects the current accepted
legacy graph into the `railiance.fabric/v1alpha2` / `financial-fabric-v1`
contract. Repo-local `fabric/` declarations remain useful evidence and
bootstrap data; they are not the long-term authority for external deployment,
ownership, tenant, or utility relations.
See `docs/financial-fabric-operator-guide.md` for the reset/rebuild refresh
loop and State Hub handoff.
## Adopt In Another Repo
See `docs/adoption-guide.md` for the declaration workflow and
`docs/first-rollout.md` for the initial Railiance repo rollout.
See `docs/adoption-guide.md` for the legacy declaration workflow and
`docs/first-rollout.md` for the initial Railiance repo rollout. Treat
repo-local declarations as self-description and discovery evidence. Financial
fabric membership, ownership, and cross-boundary utility relations are owned by
the accountability-root discovery model described in
`docs/FabricDiscoveryAndUpdate.md`.
## Next: Ecosystem Registry Service
See `docs/ecosystem-registry-service.md` for the standards comparison and
service direction for registering repos and interacting with the combined
ecosystem model.
ecosystem model. See `docs/registry-api.md` for the current registry HTTP API.
Start the first registry service slice with:
List available Make targets from the repo root:
```bash
make
```
Start the first registry service slice and graph explorer explicitly:
```bash
make graph-explorer
```
The target serves `http://127.0.0.1:8765/ui/graph-explorer` by default. Override
`PORT`, `HOST`, or `REGISTRY_DB` if the local port or database path differs.
Equivalent raw command:
```bash
railiance-fabric-registry --db .railiance-fabric/registry.sqlite3 --port 8765
@@ -67,6 +113,20 @@ Feed the running service from this checkout:
railiance-fabric registry sync --repo-slug railiance-fabric .
```
Or register and sync the known local Railiance ecosystem repos from the
onboarding manifest:
```bash
railiance-fabric registry sync-manifest registry/railiance-repos.yaml
```
To onboard every active State Hub repo with an available local checkout on this
host:
```bash
railiance-fabric registry sync-manifest registry/local-repos.yaml
```
Ingest a CycloneDX SBOM as queryable library inventory:
```bash
@@ -80,4 +140,17 @@ GET /repositories/{repo_slug}/inventory
GET /repositories/{repo_slug}/snapshots
GET /repositories/{repo_slug}/snapshots/diff
GET /search?q=jsonschema
GET /ui/graph-explorer
GET /exports/graph-explorer/manifest
GET /exports/graph-explorer
```
See `docs/registry-onboarding.md` for the multi-repo manifest and operating
loop.
The graph explorer export is the first executable slice of the interactive
Fabric map. See `docs/graph-explorer-transfer-review.md` for the repo-scoping
transfer review, `docs/graph-explorer-contract.md` for the shared manifest and
payload contract, `docs/semantic-attractors.md` for the attractor-based layout
orientation concept, and `docs/graph-explorer-operations.md` for launch,
refresh, verification, and extraction guidance.

View File

@@ -87,6 +87,80 @@ spec:
- sts-token
tags: [storage, credentials, security]
- id: kubernetes-runtime
name: Kubernetes runtime
lifecycle: active
description: Provides the Kubernetes API, namespaces, workloads, Services, Ingresses, and runtime primitives consumed by Railiance services.
default_criticality: critical
default_data_classification: restricted
expected_interface_types:
- kubernetes-api
- kubernetes-crd
tags: [kubernetes, cluster, runtime]
- id: ci-cd-template-catalog
name: CI/CD template catalog
lifecycle: planned
description: Provides reusable workflow templates, release gates, and delivery conventions for Railiance workloads.
default_criticality: medium
default_data_classification: internal
expected_interface_types:
- workflow-template-contract
- cli
tags: [ci, cd, gitops, enablement]
- id: source-hosting
name: Source hosting
lifecycle: active
description: Hosts Git repositories, repository metadata, review surfaces, and source-forge web/API access.
default_criticality: high
default_data_classification: confidential
expected_interface_types:
- web-ui
- http-api
- git-ssh
tags: [forge, git, source]
- id: container-registry
name: Container registry
lifecycle: active
description: Publishes and serves OCI container images for Railiance workloads.
default_criticality: high
default_data_classification: confidential
expected_interface_types:
- oci-registry
tags: [forge, registry, container-image]
- id: python-package-registry
name: Python package registry
lifecycle: active
description: Publishes and serves Python package artifacts for Railiance source and app builds.
default_criticality: high
default_data_classification: confidential
expected_interface_types:
- python-package-index
tags: [forge, registry, python, package]
- id: workflow-runner-substrate
name: Workflow runner substrate
lifecycle: planned
description: Provides forge-backed runner infrastructure, labels, placement, and credential boundaries for workflows.
default_criticality: high
default_data_classification: restricted
expected_interface_types:
- workflow-runner-label-contract
tags: [forge, runner, actions, automation]
- id: artifact-promotion-evidence
name: Artifact promotion evidence
lifecycle: active
description: Provides release artifact identity, provenance, publish, restore, and readiness evidence for consumers.
default_criticality: high
default_data_classification: internal
expected_interface_types:
- evidence-contract
tags: [forge, evidence, provenance, release]
- id: audit-event-sink
name: Audit/event sink
lifecycle: planned
@@ -117,5 +191,17 @@ spec:
default_data_classification: internal
expected_interface_types:
- http-api
- mcp-api
- event-stream
tags: [coordination, state-hub, planning]
- id: ecosystem-registry
name: Ecosystem registry
lifecycle: active
description: Registers repositories and exposes graph, inventory, and visualization projections over the ecosystem model.
default_criticality: high
default_data_classification: internal
expected_interface_types:
- http-api
- web-ui
tags: [registry, discovery, graph, visualization]

View File

@@ -17,6 +17,22 @@ spec:
typical_auth_methods: [none, oidc, jwt, mtls, api_key]
versioning: path, header, media-type, or documented semantic version.
- id: web-ui
name: Web UI
lifecycle: active
description: Browser-based user interface for humans and agents operating through a visual surface.
category: ui
typical_auth_methods: [none, oidc, jwt, mtls, api_key]
versioning: URL path, static asset version, and documented user-facing workflow compatibility.
- id: mcp-api
name: MCP API
lifecycle: active
description: Model Context Protocol interface consumed by agents or agent runtimes.
category: api
typical_auth_methods: [none, oidc, jwt, mtls, api_key]
versioning: MCP protocol version, tool schema version, and documented capability compatibility.
- id: oidc-discovery
name: OIDC discovery
lifecycle: active
@@ -41,6 +57,14 @@ spec:
typical_auth_methods: [kubernetes_service_account]
versioning: group, version, and kind.
- id: kubernetes-api
name: Kubernetes API
lifecycle: active
description: Kubernetes API server surface consumed by operators, controllers, and automation.
category: kubernetes
typical_auth_methods: [kubernetes_service_account, oidc, static_secret]
versioning: Kubernetes version, API groups, RBAC contract, and kubeconfig delivery path.
- id: helm-release
name: Helm release
lifecycle: active
@@ -65,6 +89,54 @@ spec:
typical_auth_methods: [database_role, static_secret, openbao_token]
versioning: engine version, connection contract, and migration compatibility.
- id: git-ssh
name: Git SSH
lifecycle: active
description: Git-over-SSH repository access endpoint.
category: source-control
typical_auth_methods: [static_secret, unknown]
versioning: hostname, port, SSH host key, authorized key scope, and Git server compatibility.
- id: oci-registry
name: OCI registry
lifecycle: active
description: OCI distribution-compatible container image registry endpoint.
category: registry
typical_auth_methods: [api_key, static_secret, none]
versioning: registry host, API behavior, package visibility, and tag/digest semantics.
- id: python-package-index
name: Python package index
lifecycle: active
description: Python package index endpoint compatible with pip/uv simple API consumption.
category: registry
typical_auth_methods: [api_key, static_secret, none]
versioning: package index URL, package visibility, token scope, and package version semantics.
- id: workflow-runner-label-contract
name: Workflow runner label contract
lifecycle: planned
description: Published runner label, placement, and trust contract consumed by CI/CD workflows.
category: automation
typical_auth_methods: [none, kubernetes_service_account, static_secret]
versioning: semantic label names, trust level, credential purpose, and runner replacement rules.
- id: workflow-template-contract
name: Workflow template contract
lifecycle: planned
description: Reusable CI/CD workflow template or template catalog contract.
category: automation
typical_auth_methods: [none]
versioning: template id, input schema, runner labels, and release gate semantics.
- id: evidence-contract
name: Evidence contract
lifecycle: active
description: Documented evidence bundle or machine-readable evidence contract for release, restore, or readiness decisions.
category: evidence
typical_auth_methods: [none, api_key]
versioning: evidence schema version, required fields, source links, and retention policy.
- id: object-storage-bucket
name: Object-storage bucket
lifecycle: planned

View File

@@ -0,0 +1,367 @@
# Fabric Discovery And Update
## Intent
`railiance-fabric` models the durable infrastructure-responsibility graph of the
Railiance netkingdom.
A fabric is not a repository, environment, cluster, deployment scenario, or
security zone. A fabric is the financial and operational responsibility boundary
around infrastructure: who pays for it, who is accountable for it, and who has
the authority to keep it alive.
The graph exists to answer:
- what infrastructure, services, repositories, deployables, endpoints, and
machines exist;
- who owns or pays for each node;
- which fabrics and subfabrics contain those nodes;
- which durable interfaces cross ownership boundaries;
- which cross-boundary interfaces provide utility that may carry business value.
Fabric intentionally stays out of live operational telemetry. It may represent
that a service, host, endpoint, or deployment exists because durable automation
or configuration proves it. It should not represent whether that thing is
currently healthy, loaded, failing, or profitable in the accounting sense.
## Financial Boundary Terms
Fabric uses financial responsibility terms for fabric boundaries.
### King
The king is responsible for the whole netkingdom.
The king has the key to the netkingdom. Literally, this means the master key or
at least a relevant key component for secrets, backups, and recovery paths across
the infrastructure under the netkingdom.
The king also holds the legal and contractual relationship with all lords and
tenants. Even when responsibility is delegated, the king remains the actor that
can ultimately restore, recover, govern, or terminate the netkingdom.
### Lord
A lord pays for a fabric.
A lord is accountable for a durable infrastructure-responsibility boundary. In
the current Railiance setup there is one effective fabric because one actor pays
for all infrastructure. Additional fabrics appear when the responsibility to pay
for a coherent infrastructure boundary changes.
### Tenant
A tenant pays for restricted use of a subfabric.
A tenant is not the root payer for the whole fabric. A tenant receives bounded
access to utility inside a subfabric and may consume services or interfaces
provided by a lord, by the king, or by another tenant-facing utility.
## Fabrics, Subfabrics, And Views
### Fabric
A fabric is a durable responsibility boundary. Membership changes when financial
or operational responsibility changes, not when a service is redeployed, a repo
is refactored, a host is replaced, or an environment name changes.
Criteria for establishing a fabric:
- there is a lord who pays for the infrastructure in that boundary;
- the boundary can be discovered from durable infrastructure, deployment, or
contractual evidence;
- the boundary remains stable across ordinary deployment and development churn;
- ownership changes imply a meaningful change to who is accountable for cost,
continuity, recovery, and utility delivery.
### Subfabric
A subfabric is a delegated responsibility or tenancy partition within a fabric.
Subfabrics are useful when a tenant receives restricted access to infrastructure
or utility while the parent fabric remains under a lord or king. A subfabric may
eventually become a separate fabric if payment, control, recovery, and legal
responsibility move to another lord.
### View
A view is a diagnostic or informational slice through the graph.
Views can filter by repository, service, environment, machine, endpoint, tenant,
workstream, deployment stack, or business capability. Views do not define fabric
membership and should not mutate fabric boundaries.
Zone views are a special kind of view. They group the subgraph by deployment
environment, deployment scenario, routing authority, or access zone. They are
useful for questions such as:
- which services are currently visible in private dev, shared test, or
production;
- which control surfaces appear in user-facing zones;
- which production surfaces still have unrestricted developer access;
- which routes exist in production but not in test;
- which early-access interfaces lack an explicit policy authority.
### Environment
An environment such as local, dev, staging, production, or lab is a deployment
classification inside a fabric. It is not a fabric by itself.
Railiance uses these baseline environment terms:
| Environment | Meaning |
|-------------|---------|
| `dev` | Private developer-local execution. Useful for debugging and discovery, but not shared truth for other developers unless explicitly published. |
| `test` | Shared central test stage for collaborators and friendly early-access users. |
| `prod` | Production execution. Alpha-stage developer access may exist now, but production must be able to move toward restricted operator access and applicable security and data-privacy controls. |
### Deployment Scenario
A deployment scenario is a realized or planned arrangement of services,
machines, endpoints, automation, and configuration. It belongs inside a fabric
or subfabric but does not define the financial boundary.
Current Railiance scenario names:
| Scenario | Environment | Meaning |
|----------|-------------|---------|
| `bernd-laptop` | `dev` | Private local workstation scenario. It may discover useful loopback services and ports, but it is not a shared developer environment. |
| `coulombcore` | `test` | Central shared test-stage server for developers and friendly early-access users. |
| `railiance01` | `prod` | Production host. It is still alpha-accessible to developers, but the intended direction is restricted production access. |
### Routing Authority
A routing authority is the deployment component that maps an external name,
local URL, ingress host, or port to a backend service. Fabric discovers routing
authority output; it does not allocate ports or author routes.
Examples:
- local loopback process launch configuration for developer tools;
- Makefile or script defaults for local-only bootstrap surfaces;
- Docker Compose published ports;
- Kubernetes `Service`, `Ingress`, or controller-specific route manifests;
- Traefik, nginx, Caddy, HAProxy, or other reverse-proxy configuration;
- DNS records and TLS/certificate automation when they prove reachable names.
### Access Zone
An access zone is a visualization and discovery overlay that describes who a
surface is intended to be reachable by in a deployment scenario. It is not a
fabric boundary and does not define the policy itself.
Useful initial access zones:
| Access zone | Intended reach |
|-------------|----------------|
| `private-dev` | One developer's local machine. |
| `collaborator-test` | Collaborating developers in the shared test stage. |
| `early-access` | Friendly users participating in early access. |
| `production-public` | Production user-facing surfaces. |
| `production-admin` | Production administrative or control surfaces. |
### Policy Authority
A policy authority is the system expected to enforce access rules for a surface.
Fabric may record which authority is in play, such as NetKingdom IAM, an ingress
policy, network policy, or local-only loopback binding, but Fabric does not
define or enforce those rules.
These terms let the graph say: "this service belongs to the Railiance primary
fabric, runs in the `coulombcore` test scenario, is routed by Traefik, and is
intended for the `early-access` zone." That is a deployment and access overlay,
not a change to fabric membership.
## Ownership Rule
Every node in the Fabric graph must carry owner information.
Ownership may be explicit on the node or inherited from the containing fabric or
subfabric, but it must be resolvable. Nodes without resolvable ownership are
incomplete because Fabric cannot explain who is accountable for their cost,
continuity, recovery, or utility.
Ownership should identify the relevant king, lord, tenant, or delegated operator
where applicable. Operators and maintainers may be represented as supporting
actors, but they do not replace the financial boundary terms unless they also
pay for or legally own the responsibility boundary.
## Cross-Boundary Edges
Edges may cross fabric and subfabric boundaries.
These edges are especially important. They are where one owned boundary consumes
utility from another owned boundary. They are also where business value can
appear: paid access, cost recovery, shared platform utility, tenant-facing
interfaces, or contractual service delivery.
Fabric should treat cross-boundary interfaces as first-class graph facts. A
cross-boundary utility edge should be able to identify:
- provider owner;
- consumer owner;
- provider fabric or subfabric;
- consumer fabric or subfabric;
- exposed endpoint, contract, service, or utility;
- durable evidence for the relationship;
- expected payment or business model when known;
- metering basis when known.
The existence of a cross-boundary interface belongs in Fabric. Live usage,
current health, latency, revenue events, and incident state belong to telemetry,
accounting, or operational systems outside the Fabric core.
## Cost And Profit Center Attribution
Cost centers and profit centers are accounting attributions. They are not fabric
boundaries by themselves.
A cost center may be evidence that a responsibility boundary exists, especially
when it corresponds to a lord who pays for infrastructure. However, the fabric
boundary is still established by financial and operational accountability, not
by the accounting label alone.
Cost and profit center attribution may overlap with fabrics and subfabrics:
- one fabric may contain many cost centers;
- one tenant may span several cost centers;
- one cost center may include nodes from multiple subfabrics;
- one shared service may allocate cost across several tenants or cost centers;
- one cross-boundary utility may be cost-bearing for one actor and
profit-bearing for another.
Fabric should therefore support optional accounting attribution on nodes and
edges without allowing that attribution to redefine containment:
- node cost center;
- node profit center;
- edge cost allocation model;
- edge profit attribution;
- payment schema;
- metering or allocation basis when known;
- attribution validity period when known.
This lets Fabric build cost-center and profit-center views while preserving the
durability of fabric membership. A node moving from one cost center to another
does not necessarily move fabrics. A node moves fabrics only when financial or
operational responsibility for the infrastructure boundary changes.
Useful accounting views include:
- all infrastructure attributed to a cost center;
- all cross-boundary utility edges attributed to a profit center;
- tenant-facing utilities without a payment schema;
- shared services with unresolved allocation;
- owned nodes without cost-center attribution;
- expensive or critical infrastructure with no visible value interface.
## Discovery Approach
Fabric discovery should start from accountability roots, not from arbitrary repo
ownership declarations.
Useful roots include:
- the king and current netkingdom inventory;
- lords and their fabrics;
- tenants and their subfabrics;
- State Hub attached repositories and known host paths;
- Gitea organizations and repository URLs;
- deployment automation repositories;
- Docker, Compose, Kubernetes, systemd, reverse proxy, and infrastructure
manifests;
- backup, recovery, and secret-management evidence;
- service endpoint and API specifications;
- CI/CD and release automation that proves deployables and deployment targets.
The scanner follows these roots outward to discover durable evidence of nodes
and edges. Repository-local facts can still help identify deployables, APIs, and
artifacts, but repository-owned declarations should not be the default source of
truth for external fabric relations.
## Rebuild From Scratch
A full rebuild should be deterministic enough to repeat and provenance-rich
enough to review.
Recommended phases:
1. Establish the netkingdom root and current king.
2. Register known lords, fabrics, tenants, and subfabrics.
3. Register durable discovery roots for each fabric and subfabric.
4. Crawl deployment automation, infrastructure manifests, repo inventories,
service configs, and endpoint contracts.
5. Store raw evidence with source paths, URLs, timestamps, scanner versions, and
content hashes.
6. Normalize identities across host paths, repository URLs, image names, service
names, endpoint names, and deployment names.
7. Build candidate graph nodes and edges.
8. Resolve or flag ownership for every node.
9. Promote accepted candidates into a versioned fabric snapshot.
10. Export the accepted snapshot to State Hub as a read model.
## Keeping The Model Up To Date
Fabric freshness should be based on durable configuration and automation changes,
with scheduled rescans as a safety net.
Rescan triggers include:
- deployment automation changes;
- infrastructure manifest changes;
- State Hub attached repository inventory changes;
- repository changes that affect deployables, APIs, images, service names,
endpoint contracts, ports, or deployment configuration;
- tenant or lord changes;
- backup, recovery, or secret-root changes;
- manual operator requests;
- scheduled periodic rebuilds.
Normal source-code edits do not necessarily change the Fabric graph. Fabric
should focus on changes that alter durable topology, ownership, deployment,
interfaces, or cross-boundary utility.
Each update should compare new discovery output with the previous accepted
snapshot and produce a delta. The delta should distinguish:
- added, changed, and removed nodes;
- added, changed, and removed edges;
- changed ownership;
- changed fabric or subfabric membership;
- new or removed cross-boundary utility interfaces;
- ambiguous identity merges that need review;
- discovered nodes without resolvable ownership.
## Boundary With Security Terms
Fabric should avoid using security-zone language for its core concepts.
Terms such as realm, domain, tenant realm, identity realm, and security domain
are useful in systems such as Microsoft environments or Keycloak, but they carry
security and identity-management semantics. Fabric may later relate to those
systems as discovered evidence, but the core Fabric concept is financial and
operational responsibility, not identity or access-control topology.
For now, use:
- king, lord, and tenant for financial responsibility actors;
- fabric and subfabric for durable responsibility boundaries;
- view for diagnostic graph slices;
- environment for deployment classification;
- deployment scenario for a concrete place where services run;
- routing authority for the component that maps names or ports to services;
- access zone for the visualization overlay that groups intended reachability;
- policy authority for the external system expected to enforce access rules.
Access zones may be security-relevant, but they are not Fabric security policy.
They are discovered and visualized evidence that helps operators spot misplaced
surfaces, missing policy authorities, or accidental exposure.
## State Hub Role
State Hub coordinates work and stores a readable projection of the Fabric graph.
It should not be the primary author of Fabric topology.
`railiance-fabric` discovers, normalizes, versions, and exports Fabric snapshots.
State Hub imports those snapshots so agents and operators can ask practical
questions about work, ownership, dependencies, and cross-boundary utility.

View File

@@ -0,0 +1,337 @@
# Zone Entity Visualization
## Intent
The graph explorer currently treats zones as visual overlays derived from node
metadata. That is useful for first orientation, but it keeps zones as a
decoration around an already-laid-out graph. The next step is to make a zone a
first-class visualization entity beside nodes and edges.
A zone is a bounded drawing surface for a subgraph. It is similar to a sheet of
paper or a layer in a graphics application: it decides which graph elements are
drawn inside it, how those elements are laid out, how it stacks with other
zones, and whether it can be collapsed into a representative node.
Zones are view entities. They help the operator inspect the fabric without
changing the underlying fabric graph. A zone can be based on deployment
environment, ownership, tenant boundaries, cost center, access zone, or any
other declared view rule, but those concepts remain distinct from the zone
mechanism itself.
## Core Model
A graph view contains three visible entity classes:
- nodes: fabric entities such as services, hosts, repos, scenarios, or owners
- edges: fabric relationships such as deployment, routing, ownership, policy,
dependency, or evidence links
- zones: visual drawing surfaces that contain a selected subgraph
A zone definition describes how to derive and render one zone. A zone instance
is the result of applying a definition to the current graph, filter state, and
view profile.
Zone definitions should be serializable so they can later live in saved graph
profiles, operator presets, or a dedicated view registry.
## Zone Definition
A zone definition should contain at least these fields:
```yaml
id: prod
label: Production
enabled: true
membership:
mode: include
rules:
- field: deploymentEnvironment
op: equals
value: prod
attraction:
rules:
- edge_type: fabric:serves
direction: both
depth: 1
node_filter:
field: kind
op: in
value: [service, endpoint]
layout:
algorithm: cose
options: {}
presentation:
height: 30
color: "#0f766e"
opacity: 0.16
blur_below: true
collapse:
enabled: true
label: Production Zone
```
The exact schema can evolve, but the responsibilities should stay separate:
- membership chooses seed nodes
- attraction optionally expands the zone from those seeds through selected edge
types and depths
- layout chooses how the zone subgraph is arranged
- presentation chooses how the zone itself is drawn and stacked
- collapse chooses how the zone can become a representative node
## Membership Rules
Membership rules decide which nodes initially belong to a zone. They should be
declarative and inspect node data rather than hard-code UI concepts.
Useful operators:
- `equals`
- `not_equals`
- `in`
- `not_in`
- `exists`
- `missing`
- `matches`
Useful rule composition:
- `all`: every nested rule must match
- `any`: at least one nested rule must match
- `none`: no nested rule may match
The first implementation can support a small subset such as `equals`, `in`,
`exists`, `all`, and `any`, then widen the rule language once saved zone
profiles need it.
## Attraction Rules
Attraction rules allow a zone to pull in additional nodes connected to the seed
set. This is useful when the operator wants a zone to include the services,
routes, machines, or contracts that make the zone understandable, even when
those nodes do not carry the seed attribute themselves.
An attraction rule should define:
- edge type or edge-type pattern
- direction: `out`, `in`, or `both`
- maximum depth
- optional node filter
- optional edge filter
Attraction must be deterministic. Given the same graph and zone definitions, the
same node should land in the same zone every time.
Attraction also needs a conflict policy because a node must not belong to more
than one zone. The recommended first policy is priority by zone height and then
definition order:
1. Seed membership wins over attracted membership.
2. If two zones seed the same node, the conflict is reported and the node is
assigned to the higher zone.
3. If two zones attract the same node, the node is assigned to the higher zone.
4. If height ties, the earlier definition wins.
5. Every conflict is recorded as a view diagnostic.
This keeps the single-zone invariant while making ambiguous rules visible.
## Single-Zone Invariant
A visible node must be assigned to zero or one zone in a given graph view. A node
that belongs to no zone remains on the base canvas.
The invariant is important because zones are meant to behave like drawing
surfaces, not like arbitrary tags. Allowing the same node to appear in multiple
zones would make edge routing, selection, collapse behavior, and interaction
state ambiguous.
The model can still support analytical overlap by reporting diagnostics and by
offering alternative view presets. It should not solve overlap by duplicating
nodes in the same rendered view.
## Zone Layout
Each zone may choose its own layout algorithm for its subgraph. For example:
- deployment zones may use force-directed layout
- ownership zones may use concentric layout
- stage zones may use grid layout
- collapsed or nearly empty zones may use compact deterministic placement
The outer graph layout and the zone subgraph layouts are separate concerns. A
first implementation can keep the current Cytoscape layout for all nodes and
only render zone surfaces around assigned nodes. A later implementation should
introduce a two-phase layout:
1. Place zones and unzoned nodes on the main canvas.
2. Place each zone's assigned subgraph inside that zone using the zone's layout.
This will likely require an internal view model that separates fabric graph data
from rendered graph coordinates.
### Per-Zone Layout Preparation
The current graph explorer should not immediately run independent Cytoscape
layouts inside each zone rectangle. Cytoscape layouts operate on collections in
one coordinate space, while the current zone overlay is a view layer drawn over
the already-laid-out graph. Running nested layouts directly against visible
nodes would make pan/zoom, filters, collapse state, and edge routing fragile.
The safer path is a two-phase view layout:
1. Resolve zones from the current graph and view filters.
2. Place zone containers and unzoned nodes in the global canvas.
3. For each zone, compute local coordinates for its assigned nodes using the
zone's configured layout algorithm.
4. Project local zone coordinates into global graph coordinates.
5. Route internal edges inside the zone and boundary edges through the zone
perimeter or collapsed zone node.
The implementation needs these pieces before per-zone layouts become safe:
- a resolved zone view model that survives filtering and saved profiles;
- a stable assignment invariant so a visible node belongs to no more than one
zone;
- a zone container model with size, position, padding, and height;
- a local coordinate projection layer from zone space to Cytoscape space;
- explicit boundary-edge routing rules;
- collapse state that can replace a zone subgraph with a representative node;
- diagnostics when a configured zone layout cannot be applied.
The present implementation already establishes the first, second, and sixth
pieces. A follow-up should introduce a zone container placement phase before
attempting per-zone node layout. That follow-up can keep Cytoscape as the final
renderer while moving layout decisions into a Fabric-owned view model.
### Stable Zone Containers
The first container implementation keeps zone surfaces as view state keyed by
stable zone id. When a zone first appears, the global graph layout supplies its
initial center. Once created, the container owns the zone surface position while
the global layout continues to arrange the base canvas and unzoned nodes.
Dragging a zone moves the container and its currently assigned visible member
nodes together. Rerunning layout or switching the layout algorithm should keep
the container in its stored graph coordinates and then project the zone's
visible subgraph back into that container.
Container state belongs in saved or copied graph view state, not in the Fabric
payload. It is an operator workspace preference, similar to manual visibility
overrides.
Zone-local layout is also view state. The first selectable algorithms are a
compact grid and a circle layout. Switching between them should rearrange the
assigned nodes inside each stable container without moving the container itself
or changing the underlying Fabric relationships.
### Context Edges
Display-only context edges are not zone connectivity. Repository `declares`
edges, for example, show which repository declared a node, but they should not
create boundary diagnostics, attraction paths, or collapsed-zone boundary
edges. A host can still show them as explanatory evidence in details, but a
zone boundary should only react to canonical or host-promoted graph
relationships.
## Layer Height And Overlap
Zone presentation includes a height. Height is a visual stacking concept, not a
security or ownership concept.
When zones overlap:
- higher zones should draw above lower zones
- lower zones may be desaturated when covered
- lower zones may be blurred or dimmed when covered
- labels should remain readable where practical
- pointer interaction should prefer the highest visible zone
The implementation should avoid implying that a higher zone is more important.
Height is about rendering order and view ergonomics only.
## Collapse To Zone Node
A zone can optionally collapse into a representative node. Collapsing is a view
operation that preserves graph connectivity:
- nodes inside the zone become hidden from the current view
- the zone node represents the collapsed zone
- edges between inside and outside nodes are reconnected to the zone node
- edges fully inside the zone are hidden or summarized
- expanding restores the original nodes and edges
The collapsed zone node should expose useful summary data:
- contained node count
- contained edge count
- dominant node kinds
- inbound and outbound boundary edge counts
- diagnostics such as membership conflicts
This enables drill-down exploration without destroying the operator's context.
## Hierarchical Zones
The collapse model naturally leads to hierarchical zones. A tenant subfabric may
sit inside a landlord fabric, an access zone may sit inside a deployment
environment, and a cost-center view may cut across both as an alternate profile.
Hierarchy should be introduced carefully:
- parent-child containment must be explicit in the zone definition or derived
from a deterministic rule
- a node still belongs to exactly one visible leaf zone
- collapsing a parent collapses all visible descendants
- cross-boundary edges must remain visible at the collapsed boundary
The first implementation should support flat zones. The data model should avoid
choices that would make hierarchy impossible later.
## Diagnostics
Zones should produce diagnostics because rule-based view construction can hide
important ambiguity.
Useful diagnostics:
- node matched by more than one membership rule
- node attracted by more than one zone
- edge crosses zone boundaries
- zone has no seed nodes
- attraction depth reached limit
- collapsed zone has hidden internal boundary evidence
Diagnostics belong to the visualization layer. They should not mutate the
fabric graph.
## Relationship To Fabric Concepts
Zones are not fabrics, subfabrics, realms, domains, environments, cost centers,
or tenants. A zone is a view mechanism that can visualize those concepts.
Examples:
- a deployment-environment zone groups nodes by `dev-tegwick`, `test`, or `prod`
- a financial fabric zone groups nodes by lord or tenant responsibility
- a cost-center zone groups nodes for accounting analysis
- an access-zone view groups nodes by operational access policy once that
metadata exists
This keeps the graph explorer flexible while preserving the stricter meaning of
fabric boundaries: who pays for, owns, and is responsible for infrastructure.
## Implementation Direction
The recommended path is incremental:
1. Introduce a pure zone resolver that converts graph data and zone definitions
into zone instances, node assignments, edge summaries, and diagnostics.
2. Replace the current hard-coded environment/access overlay derivation with
resolver-backed default zone definitions.
3. Add zone-aware rendering state to the graph explorer UI.
4. Add saved zone profiles once the model is stable.
5. Add collapse-to-zone-node behavior.
6. Add per-zone layout only after the resolver and rendering model are stable.
This order keeps the current useful overlay behavior while moving the engine
toward zones as first-class view entities.

View File

@@ -0,0 +1,172 @@
# Accountability Root Manifest
The accountability root manifest is the handoff between the financial Fabric
model and the discovery/update loop.
It answers where discovery starts. A manifest names the netkingdom, actors,
fabric boundaries, and durable roots that can prove repositories, deployment
realities, service configuration, endpoint contracts, backup/recovery evidence,
and secret-root metadata. It does not collect live telemetry and it does not
make State Hub the authoring surface for topology.
Schema:
```text
schemas/accountability-root-manifest.schema.yaml
```
Current Railiance manifest:
```text
fabric/discovery/railiance-accountability-roots.yaml
```
Tenant/subfabric example:
```text
examples/discovery/accountability-root-manifest.yaml
```
Raw evidence run schema:
```text
schemas/accountability-root-evidence.schema.yaml
```
Identity projection schema:
```text
schemas/accountability-identity-projection.schema.yaml
```
Ownership review schema:
```text
schemas/accountability-ownership-review.schema.yaml
```
Update delta schema:
```text
schemas/accountability-update-delta.schema.yaml
```
## Required Sections
- `netkingdom`: root id, name, and king actor.
- `actors`: king, lord, tenant, operator, or steward actors.
- `fabrics`: fabric and subfabric boundaries.
- `discovery_roots`: durable roots such as State Hub repo inventory, Gitea
organizations, registry manifests, host paths, repo checkouts, deployment
automation, endpoint contracts, backup/recovery evidence, and secret-root
metadata.
- `refresh`: cadence and trigger hints for the future update loop.
## Boundary Rules
The current Railiance manifest has one active fabric:
`fabric.railiance.primary`. Future tenant subfabrics are added under that
fabric by adding a tenant actor, a `Subfabric`, and subfabric-scoped discovery
roots. This does not change the root fabric criterion: the fabric boundary
still rests on financial and operational accountability.
`owner_actor_id` on a discovery root describes the default owner to attach to
identity candidates discovered through that root. For ordinary repositories,
deployment files, and host-path evidence this should be the lord who pays for
the fabric. King authority remains modeled on the netkingdom and on roots that
represent recovery, secret, backup, or termination authority.
Discovery roots should state `safe_discovery` explicitly. Secret and backup
roots should use `metadata_only` or `explicit_review`; adapters must never read
secret values or operational telemetry while building Fabric graph evidence.
## Collecting Root Evidence
The first adapter slice emits raw evidence without promoting it into accepted
graph snapshots:
```bash
railiance-fabric discover-roots \
--manifest fabric/discovery/railiance-accountability-roots.yaml \
--max-items-per-root 200
```
The command covers manifest-backed repository inventory, repository checkout
identity, host-path evidence, deployment automation and infrastructure files,
State Hub/Gitea metadata roots, endpoint/service-config roots, and safe
metadata-only backup or secret roots. Remote HTTP reads are disabled by default;
pass `--include-remote` only when the operator intentionally wants configured
remote roots such as State Hub inventory endpoints to be fetched.
The output is an `AccountabilityRootEvidenceRun`. Every evidence item carries
provenance, source, fingerprint, `durable: true`, and
`live_telemetry: false`, preserving the boundary between Fabric evidence and
operational telemetry.
To normalize raw evidence into reviewable identity candidates:
```bash
railiance-fabric discover-roots \
--identity-projection \
--max-items-per-root 200
```
To persist raw evidence and identity candidates in a local SQLite store:
```bash
railiance-fabric discover-roots \
--store-db .railiance-fabric/accountability-evidence.sqlite3 \
--identity-projection
```
The store is intentionally separate from accepted registry graph snapshots. It
keeps raw evidence runs, evidence items, and identity candidates available for
inspection before any candidate is promoted.
## Ownership Review
To resolve ownership and containment from the normalized identities:
```bash
railiance-fabric discover-roots \
--ownership-review \
--store-db .railiance-fabric/accountability-evidence.sqlite3
```
The ownership review inherits owners from fabric/subfabric containment when
possible, applies explicit owner evidence from discovery roots, and marks
unresolved or ambiguous candidates as `needs_review`. Accepted candidates must
have a resolved owner and containment unless they are actors or the netkingdom
root.
To persist a reviewer decision for a stable identity candidate:
```bash
railiance-fabric review-identity identity:repository:example-repo \
--store-db .railiance-fabric/accountability-evidence.sqlite3 \
--decision accept \
--owner-actor-id actor.railiance.primary-lord \
--fabric-id fabric.railiance.primary \
--reviewer operator \
--note "accepted from reviewed checkout evidence"
```
Reviewer decisions are keyed by stable identity key. Later rescans apply the
latest decision for that key, so ordinary evidence refreshes do not lose
reviewed ownership choices.
## Update Deltas
To compare the current run with previous identity and ownership-review outputs:
```bash
railiance-fabric discover-roots \
--delta \
--previous-identity-projection previous-identities.json \
--previous-ownership-review previous-ownership.json
```
The delta separates candidate graph node changes, candidate graph edge changes,
ownership changes, containment changes, review-state changes, and blocker
changes. When `summary.promotion_needed` is `false`, the update loop can skip
promotion because the durable evidence produced no meaningful Fabric change.

View File

@@ -0,0 +1,140 @@
# Canon Alignment Review For RAIL-FAB-WP-0016
Date: 2026-05-23
## Review Packet
This review follows the InfoTechCanon consumer alignment workflow for
`railiance-fabric`.
Reviewed Fabric sources:
- `INTENT.md`, `SCOPE.md`, and `README.md`
- `railiance_fabric/graph.py`, `scanner.py`, `registry.py`, and `graph_explorer.py`
- `schemas/discovery-snapshot.schema.yaml` and `schemas/state-hub-export.schema.yaml`
- workplans `RAIL-FAB-WP-0010` through `RAIL-FAB-WP-0016`
Reviewed canon sources:
- `infospace/agent/review-kit/review-kit.yaml`
- `infospace/agent/review-kit/review-workflow.yaml`
- `infospace/evaluations/railiance-fabric/conformance-pack.yaml`
- `infospace/evaluations/railiance-fabric/entity-edge-capture-criteria.yaml`
- `infospace/evaluations/railiance-fabric/mapping-expectations.yaml`
- `infospace/evaluations/railiance-fabric/visualization-examples.yaml`
The workplan's `review-kit/alignment` reference is the canon artifact id; the
physical files are under `infospace/agent/review-kit/`.
## Repository Context
Producer intent: Railiance Fabric owns repo-authored graph declarations,
scanner output, registry projection, validation, query tooling, and State Hub
export contracts for the Railiance ecosystem graph.
Current scope: source-controlled declarations model services, capabilities,
interfaces, dependencies, and binding assertions. Deterministic scanning adds
candidate repositories, libraries, manifests, runtime endpoints, domains,
ports, and source evidence. The graph explorer adds visual projection edges and
inferred runtime views for usability.
Consumer purposes:
- make cross-repo dependencies reviewable,
- make provider/consumer and blast-radius queries reliable,
- provide State Hub with a read model rather than an authoring surface,
- support reingest after a canon-aligned model reset,
- prevent visualization metadata from becoming graph truth.
## Selected Canon Surfaces
| Surface | Why selected |
| --- | --- |
| `model/landscape` | Services, software systems, runtime resources, environments, ownership, and dependency claims. |
| `model/devsecops` | Source repositories, packages, lockfiles, pipelines, artifacts, deployments, and attestations. |
| `model/network` | Endpoints, ports, DNS, routes, reachability, and future flow nodes. |
| `model/data` | Datastore and reads/writes relationships are expected gaps in current Fabric capture. |
| `model/observability` | Evidence, telemetry signals, scanner provenance, and validation support. |
| `model/governance` | Policies, reviews, decisions, exceptions, and reset guardrails. |
| `model/security` | Controls and findings that should not be flattened into generic dependency edges. |
| `model/task` | Review and remediation work created from graph gaps. |
| `model/purpose-demand-extension` | Consumer purpose, scope pressure, and canon evolution feedback. |
| `standard/tagging` | Non-relationship classification without using display edges as semantics. |
## Target Node Taxonomy
| Canon category | Current Fabric source | Fit | Target action |
| --- | --- | --- | --- |
| source-repository | `Repository` candidates and registered repos | direct | Keep as source evidence for repo-local declarations and scans. |
| service | `ServiceDeclaration` | direct | Keep as logical/deployable service boundary. |
| software-system | `CapabilityDeclaration`, `Library`, `ExternalLibrary` | partial | Keep as transitional mapping; later split capability semantics from system/component boundaries. |
| endpoint | `InterfaceDeclaration`, `ApplicationEndpoint`, `NetworkPort`, `DomainName` | partial/direct | Prefer explicit endpoint nodes for network reachability; preserve interface contract attributes. |
| deployment | `DeploymentService`, `ScoreWorkload`, `ContainerBuild` | partial/direct | Add deployment nodes for actual release/deploy evidence before destructive reset. |
| runtime-resource | `RuntimeService`, `Server`, `Kubernetes*` candidates | partial/direct | Capture workload, service DNS, namespace, VM/server, and cluster objects as runtime reality. |
| datastore | none first-class | gap | Add explicit datastore extraction from declarations, manifests, and config before reingest acceptance. |
| flow | route/resolve/port edges only | gap | Add first-class Flow nodes when observed traffic or declared communication needs protocol/evidence context. |
| policy | none first-class | gap | Add policy nodes for governing declarations, reset gates, and validation controls. |
| control | none first-class | gap | Add control nodes only when preventive/detective/corrective controls have evidence. |
| evidence | `BindingAssertion`, `Lockfile`, `ServiceConfig`, contracts, source anchors | partial | Make evidence explicit instead of hiding it only in attributes. |
| task | workplans and review gaps | gap | Capture review/remediation tasks after State Hub readiness work is agreed. |
| consumer-purpose | interface card and purpose-fit review | gap | Keep in docs now; model as graph nodes only if State Hub needs purpose-driven filtering. |
| telemetry-signal | none first-class | gap | Add metrics/logs/alerts/dashboards as observed signals when connectors exist. |
## Target Edge Taxonomy
| Current Fabric edge | Canon relationship | Fit | Notes |
| --- | --- | --- | --- |
| `exposes`, `exposes_port`, `listens_on` | `exposes` | direct/partial | Good first canonical family for service/endpoint reachability. |
| `consumes`, `depends_on_library`, `binds:*`, `uses_interface` | `depends_on` | partial | Preserve helper nodes until a reingest can project direct service relationships safely. |
| `provides` | `implements` | partial | Service-to-capability is a Fabric helper relation; needs stronger canon treatment or collapse. |
| `available_via`, `names_endpoint` | `exposes` | partial | Useful transitional mappings from capability/interface/domain to endpoint. |
| `defines_deployment`, `builds_container`, `declares_package` | `built_from` | partial | Direction and artifact semantics need cleanup before being canonical claims. |
| `defines_runtime_object`, `defines_workload`, `runs_on`, `deployed_as` | `deploys` | partial | Current scanner/UI edges mix source definitions and deployment reality. |
| `routes_to_port`, `routes_to_service`, `resolves_to` | `flows_to` | partial | These are reachability hints, not logical dependencies. |
| `uses_lockfile`, `uses_config`, `documents_interface`, `cataloged_as` | `evidenced_by` | partial | Evidence should become first-class where it supports a specific claim. |
| `declares`, `owns_deployment`, canon display examples | display-only | direct | These are view/cluster edges and must not be conformance claims. |
## Mapping Findings
Direct mappings are strong for repositories, services, runtime resources,
application endpoints, network ports, and explicit `exposes` relationships.
Partial mappings are expected for capability, interface, dependency, binding,
package, manifest, and route concepts. They should keep legacy names during the
transition but carry `canon_category`, `canonical_type`, `mapping_fit`, and
`evidence_state` metadata.
Conflicts: network flow must not be treated as logical dependency, and
graph-explorer layout edges must not be treated as canonical ownership,
dependency, reachability, policy, or evidence.
Gaps: datastores, flows, policy, control, telemetry signals, tasks, and
consumer-purpose nodes are not first-class scanner outputs yet. These should be
implemented as explicit gaps or candidate mappings, not forced into nearby
legacy Fabric semantics.
## Execution Direction
The first implementation slice adds canon metadata beside existing node and
edge names. That keeps registry and graph explorer behavior stable while making
the renewed model inspectable and testable.
The destructive reset phase remains blocked until the following exist:
- export and archive command for current registry graph data,
- reset command that requires an explicit operator flag,
- rollback note that explains restore limits,
- validation that the new scanner/projection can reingest registered repos,
- before/after counts and sample graph review.
No destructive reset was executed during this T01/T02 start.
## Canon Feedback
- Capability and dependency helper nodes are useful Fabric authoring concepts
but do not map cleanly to canonical graph entity categories.
- Edge direction needs explicit treatment for source repo to package/deployment
evidence, because canon `built_from` points from deployment/artifact context
back to source.
- Evidence state should remain independent from review state: accepted inferred
claims and candidate declared claims are different situations.

View File

@@ -0,0 +1,100 @@
schema: info-tech-canon.interface-card.v1
id: railiance-fabric/interface-card
title: Railiance Fabric Canon Interface Card
consumer:
repo: railiance-fabric
domain: railiance
owner: codex
intent: Make the Railiance ecosystem understandable, discoverable, and evolvable through accepted Fabric snapshots, accountability-root discovery, and repo-local evidence.
scope: Shared schemas, validation, graph construction, registry projections, scanner output, and State Hub export contracts for repository, service, capability, interface, dependency, binding, and runtime discovery data.
purposes:
- id: purpose/graph-refactor
use_case: Canon-aligned graph model reset and reingest.
consumer_need: Separate canonical graph semantics from registry, scanner, and visualization convenience edges before broad adoption.
demand_signals:
- RAIL-FAB-WP-0016
- Registry graph explorer needs clearer canonical/display boundary.
- Scanner output needs evidence state and canon mapping metadata.
canon_surfaces:
implemented_profiles: []
consumed_artifacts:
- model/landscape
- model/network
- model/data
- model/devsecops
- model/observability
- model/governance
- model/security
- model/task
- model/purpose-demand-extension
- standard/tagging
- conformance/railiance-fabric
owned_concepts:
- FabricGraphExport
- FabricDiscoverySnapshot
- GraphExplorerPayload
- RegistryOnboardingManifest
produced_concepts:
- FabricEntity
- FabricEdge
- CaptureSource
- DisplayEdge
- CanonicalEdgeCandidate
- VisualizationView
consumed_concepts:
- Repository
- Service
- SoftwareSystem
- RuntimeResource
- Endpoint
- Deployment
- Flow
- Evidence
- Task
mappings:
- source: Repository
target: source-repository
fit: direct
- source: ServiceDeclaration
target: service
fit: direct
- source: InterfaceDeclaration
target: endpoint
fit: partial
- source: CapabilityDeclaration
target: software-system
fit: partial
- source: DependencyDeclaration
target: depends_on edge
fit: gap
validation_expectations:
commands:
- python3 -m pytest
evidence_required:
- Nodes carry canon_category, canon_anchor, mapping_fit, and evidence_state.
- Edges carry canonical_type, display_only, mapping_fit, and evidence_state.
- Display-only edges do not act as conformance claims.
- Reset commands are guarded and documented before graph data is dropped.
known_gaps:
- Datastore, flow, policy, control, telemetry-signal, task, and consumer-purpose are not first-class scanner outputs yet.
- Legacy declaration nodes still preserve capability/dependency/binding helper nodes until reingest rules collapse or replace them safely.
purpose_fit:
state: partial-fit
matched_capabilities:
- entity and edge capture criteria
- mapping expectations
- visualization boundary examples
scope_pressure: Fabric needs a stable edge vocabulary and evidence-state vocabulary for mixed declared, observed, inferred, and proposed graph claims.
recommended_disposition: Continue consumer-side refactor; record canon gaps as explicit feedback rather than silently extending Fabric semantics.
consumer_needs:
current:
- Canon-aligned graph metadata in scanner, registry, export, and graph explorer payloads.
- Safe destructive reset guardrails before dropping previous graph snapshots.
- Reingest validation across registered and local repositories.
requested_extensions:
- Stable relationship vocabulary for graph capture.
- Evidence-state vocabulary for captured edges.
- Visualization boundary guidance for display-only edges.
feedback:
- CapabilityDeclaration and DependencyDeclaration are useful Fabric authoring helpers but do not map cleanly to canon node categories.
- Network flow and logical dependency must remain separate even when both are inferred from the same source artifact.

View File

@@ -1,12 +1,18 @@
# Declaration Schema
Railiance Fabric declarations are small YAML documents owned by the repository
that provides or consumes the declared thing. The first schema version is
Railiance Fabric declarations are small YAML documents that capture repo-local
self-description evidence. The first schema version is
`railiance.fabric/v1alpha1`.
These declarations are still supported for bootstrap and compatibility, but
they are not the long-term authority for external deployment realities,
financial fabric boundaries, tenant subfabrics, or cross-boundary utility
relations. The financial Fabric model starts from accountability roots as
described in `docs/FabricDiscoveryAndUpdate.md`.
## File Layout
Participating repositories should use this layout:
Participating repositories that publish local evidence should use this layout:
```text
fabric/
@@ -56,7 +62,7 @@ begin with the owning repo slug when possible:
| `kind` | Declaration kind: service, capability, interface, dependency, or binding assertion. |
| `metadata.id` | Stable graph identifier used for references and bindings. |
| `metadata.name` | Human-readable display name. |
| `metadata.owner` | Owning team, repo, or domain owner. |
| `metadata.owner` | Local evidence owner for the declaration; financial Fabric ownership is resolved separately. |
| `metadata.repo` | Repo slug that owns the declaration. |
| `metadata.domain` | Domain slug, such as `railiance` or `custodian`. |
| `metadata.source_links` | Optional source pointers to docs, code, manifests, ADRs, or workplans. |

View File

@@ -1,7 +1,7 @@
# Discovery Queries And Exports
Railiance Fabric includes a first CLI surface for inspecting local declaration
graphs.
graphs and projecting them into the current financial Fabric baseline.
All commands accept a repo root, `fabric/` directory, or declaration files. When
paths are omitted, commands read `./fabric`.
@@ -78,8 +78,36 @@ Export the graph as Mermaid:
railiance-fabric export --format mermaid
```
Export the graph as the manifest-compatible graph explorer payload:
```bash
railiance-fabric export --format graph-explorer
```
Export the graph as the financial Fabric baseline projection:
```bash
railiance-fabric export --format financial
```
The JSON export has two top-level arrays:
- `nodes`: service, capability, interface, dependency, and binding nodes
- `edges`: graph relationships such as `provides`, `exposes`,
`available_via`, `consumes`, `binds:<status>`, and `uses_interface`
Canon-aligned exports also carry mapping metadata beside the existing Fabric
terms: nodes include `canon_category`, `canon_anchor`, `mapping_fit`, and
`evidence_state`; edges include `canonical_type`, `display_only`,
`mapping_fit`, and `evidence_state`.
The graph explorer payload wraps those nodes and edges as Cytoscape-compatible
elements with stable keys, layers, display state, visual facets, source
references, and deep links. The registry service exposes the same projection at
`GET /exports/graph-explorer`.
The financial export emits `railiance.fabric/v1alpha2` /
`financial-fabric-v1`. It combines the current legacy graph evidence with
`fabric/financial/railiance-netkingdom.yaml`, assigning inherited ownership and
fabric containment for the current single Railiance fabric. Use it as the reset
contract and State Hub vNext handoff artifact.

View File

@@ -7,12 +7,16 @@ services, capabilities, interfaces, and dependencies.
## Recommendation
Build a small Railiance Ecosystem Registry service as the API and indexed read
model over repo-owned Fabric declarations.
model over accepted Fabric graph snapshots, discovery evidence, and supporting
inventory.
The registry should not replace the `fabric/` files in each repo. Repositories
remain the source of truth. The service validates, snapshots, queries, and
projects that model so agents, humans, and State Hub can interact with the
ecosystem graph without cloning every repo or rerunning the local CLI.
The registry should not become the authoring surface for Fabric ownership or
boundaries. Repo-local `fabric/` files remain useful evidence, while financial
fabric membership, tenant boundaries, ownership, and cross-boundary utility
relations are resolved from accountability roots and accepted snapshots. The
service validates, snapshots, queries, and projects that model so agents,
humans, and State Hub can interact with the ecosystem graph without cloning
every repo or rerunning the local CLI.
The closest external model to compare against is CNCF xRegistry. xRegistry is
specifically about metadata registries, with both file/document and API views.

View File

@@ -0,0 +1,421 @@
# Financial Fabric Model Audit
Date: 2026-05-24
Workplan: `RAIL-FAB-WP-0017`
## Purpose
This audit identifies the current `railiance-fabric` assumptions that must
change to implement the financial Fabric architecture in
`docs/FabricDiscoveryAndUpdate.md`.
The current implementation is still centered on repo-owned declarations:
```text
repo -> service -> capability -> interface -> dependency -> binding
```
That model remains useful as legacy evidence and as a self-description layer,
but it is no longer the correct top-level source of truth for external fabric
relations. The vNext model must start from accountability roots: netkingdom,
king, lords, tenants, fabrics, subfabrics, deployment automation, durable
infrastructure evidence, and cross-boundary utility interfaces.
## Current Model Assumptions
### Repo-Owned Declarations Are The Primary Graph Source
Affected files:
- `INTENT.md`
- `SCOPE.md`
- `docs/declaration-schema.md`
- `docs/adoption-guide.md`
- `docs/first-rollout.md`
- `docs/repo-reality-scanner.md`
- `fabric/README.md`
- `examples/declarations/**`
- `fabric/services/**`
- `fabric/capabilities/**`
- `fabric/interfaces/**`
- `fabric/dependencies/**`
- `fabric/bindings/**`
Current behavior:
- Repositories are expected to own declarations for services, capabilities,
interfaces, dependencies, and binding assertions.
- The scanner treats repo-owned Fabric declarations as the highest-trust source
for accepted graph data.
- Existing examples and docs teach adoption by adding `fabric/` files to
participating repositories.
Required change:
- Repo-owned declarations should become one evidence source, mostly useful for
self-description, not the default authority for external relations.
- External relations, tenancy, deployment membership, and cross-boundary utility
edges should come from fabric-scoped discovery roots and deployment evidence.
### Declaration Kinds Encode The Graph Shape
Affected files:
- `schemas/service.schema.yaml`
- `schemas/capability.schema.yaml`
- `schemas/interface.schema.yaml`
- `schemas/dependency.schema.yaml`
- `schemas/binding.schema.yaml`
- `schemas/common.schema.yaml`
- `railiance_fabric/model.py`
- `railiance_fabric/loader.py`
- `railiance_fabric/validation.py`
- `railiance_fabric/graph.py`
- `railiance_fabric/canon.py`
- `tests/test_canon.py`
- `tests/test_registry.py`
- `tests/test_scanner.py`
- `tests/test_discovery.py`
- `tests/test_discovery_registry.py`
- `tests/test_reconciliation.py`
Current behavior:
- `loader.py` hardcodes declaration directories:
`services`, `capabilities`, `interfaces`, `dependencies`, and `bindings`.
- `validation.py` only accepts the legacy declaration kinds through
`SCHEMA_BY_KIND`.
- `graph.py` builds provider/consumer/binding behavior directly from those
declaration kinds.
- `canon.py` maps those declaration kinds into canonical categories, with
several partial or gap mappings.
- Tests assert the legacy kinds and edge types as the normal graph shape.
Required change:
- Add vNext semantic graph concepts for netkingdom, actor, fabric, subfabric,
owned node, utility interface, accounting attribution, and provenance.
- Keep legacy declaration kinds as a compatibility/evidence layer until they
can be migrated or intentionally retired.
- Stop treating environment tags as possible fabric boundaries.
### Metadata Owner Is Not Financial Ownership
Affected files:
- `schemas/common.schema.yaml`
- `railiance_fabric/graph.py`
- `railiance_fabric/scanner.py`
- `railiance_fabric/registry.py`
- `schemas/state-hub-export.schema.yaml`
- existing declaration files under `fabric/**`
Current behavior:
- `metadata.owner` is required for declarations, but it is just a string.
- Graph exports place owner inside node `attributes.owner`, not as a first-class
field.
- Discovery candidates can carry owner-like attributes, but there is no
enforced owner actor, role, inheritance rule, or unresolved-owner state.
- State Hub export nodes require `repo`, `domain`, and `lifecycle`, but not
financial owner, fabric, or subfabric.
Required change:
- Introduce actor identity and role: king, lord, tenant, and supporting
operator/steward where needed.
- Every accepted node must resolve to an owner actor, either explicit or
inherited from containing fabric/subfabric.
- Missing or ambiguous ownership must be represented as review state before
promotion.
### Fabric Membership Is Missing
Affected files:
- `schemas/state-hub-export.schema.yaml`
- `schemas/discovery-snapshot.schema.yaml`
- `railiance_fabric/scanner.py`
- `railiance_fabric/registry.py`
- `railiance_fabric/graph_explorer.py`
- `railiance_fabric/graph_explorer_ui.py`
- `docs/graph-explorer-contract.md`
- `docs/state-hub-integration.md`
Current behavior:
- Accepted graph nodes have repo/domain/lifecycle fields, but no `fabric_id`,
`subfabric_id`, containment path, or owning lord/tenant relation.
- Discovery snapshots are scoped to one `repo_slug`, one commit, and one scan
profile.
- Registry snapshots are stored per repository and combined by merging the
latest snapshot for each repo.
Required change:
- Add first-class fabric/subfabric identity and containment.
- Preserve repo scoping for repository evidence, but do not let repo scope
define fabric membership.
- Add a root netkingdom/fabric baseline for the current one-fabric Railiance
setup.
### Cross-Boundary Utility Is Flattened Into Dependency Edges
Affected files:
- `schemas/dependency.schema.yaml`
- `schemas/binding.schema.yaml`
- `railiance_fabric/graph.py`
- `railiance_fabric/registry.py`
- `railiance_fabric/canon.py`
- `railiance_fabric/graph_explorer.py`
- `railiance_fabric/graph_explorer_ui.py`
- `tests/test_registry.py`
- `tests/test_graph_explorer.py`
Current behavior:
- Consumers and providers are expressed as dependencies and binding assertions.
- Edges such as `consumes`, `binds:*`, and `uses_interface` map mostly to
canonical `depends_on`.
- There is no explicit provider-owner/consumer-owner boundary, payment schema,
metering basis, or business model on the edge.
Required change:
- Add a first-class cross-boundary utility edge concept.
- Preserve technical dependency edges, but distinguish them from economic or
tenancy value interfaces.
- Allow cross-boundary edges across fabric and subfabric boundaries without
treating the boundary crossing as an error.
### Cost/Profit Centers Are Not Represented
Affected files:
- all current graph schemas and exports
- `railiance_fabric/registry.py`
- `railiance_fabric/graph_explorer.py`
- `railiance_fabric/graph_explorer_ui.py`
- State Hub import contract in `schemas/state-hub-export.schema.yaml`
Current behavior:
- There are no node or edge fields for cost center, profit center, allocation
model, payment schema, metering basis, or attribution validity.
Required change:
- Add optional accounting attribution on nodes and edges.
- Ensure accounting attribution can drive views without changing fabric or
subfabric membership.
### Discovery Has Good Mechanics But Wrong Roots
Affected files:
- `railiance_fabric/scanner.py`
- `railiance_fabric/discovery.py`
- `railiance_fabric/reconciliation.py`
- `railiance_fabric/connectors.py`
- `schemas/discovery-snapshot.schema.yaml`
- `docs/repo-reality-scanner.md`
- `docs/operational-rescan-loops.md`
- `docs/registry-onboarding.md`
Current behavior:
- Discovery snapshots are provenance-rich and already separate candidates from
accepted graph state.
- Replacement scopes, stable keys, tombstones, review states, reconciliation
diffs, and connector runs are already present.
- Discovery is still repo-scoped and gives `repo_declaration` precedence.
- `local-fabric-registry` reads repository onboarding manifests, not
accountability roots or deployment responsibility boundaries.
Required change:
- Reuse the raw-evidence/candidate/accepted mechanics.
- Add accountability-root manifests and adapters for deployment automation,
infrastructure evidence, recovery/secrets/backup evidence, and ownership
boundaries.
- Change precedence so repo declarations can be strong self-description
evidence without overriding fabric-scoped deployment evidence.
### State Hub Export Is Too Thin For The New Model
Affected files:
- `schemas/state-hub-export.schema.yaml`
- `railiance_fabric/graph.py`
- `railiance_fabric/registry.py`
- `railiance_fabric/server.py`
- `docs/state-hub-integration.md`
- `docs/registry-api.md`
Current behavior:
- `/exports/state-hub` returns a `FabricGraphExport` with nodes and edges.
- Nodes require `id`, `kind`, `name`, `repo`, `domain`, and `lifecycle`.
- Edges require `from`, `to`, and `type`.
- Canon metadata and evidence state are present, but ownership, containment,
accounting, and utility metadata are not first-class.
Required change:
- Version the export contract.
- Add fabric/subfabric containment, owner actor identity, owner role,
cross-boundary utility metadata, and optional cost/profit attribution.
- Keep enough compatibility metadata for State Hub to support old imports until
`STATE-WP-0051` replaces or migrates the read model.
## Affected APIs And Commands
HTTP surfaces:
- `GET /exports/state-hub`
- `GET /exports/graph-explorer`
- `GET /exports/backstage`
- `GET /exports/xregistry`
- `GET /graph/providers`
- `GET /graph/consumers`
- `GET /graph/unresolved`
- `GET /graph/blast-radius`
- `GET /graph/dependency-path`
- `POST /repositories/{repo_slug}/snapshots`
- `POST /repositories/{repo_slug}/discovery-snapshots`
- `POST /repositories/{repo_slug}/discovery-snapshots/{id}/accept`
- `GET /repositories/{repo_slug}/inventory`
CLI surfaces:
- `railiance-fabric validate`
- `railiance-fabric export`
- `railiance-fabric providers`
- `railiance-fabric consumers`
- `railiance-fabric dependency-path`
- `railiance-fabric unresolved`
- `railiance-fabric blast-radius`
- `railiance-fabric scan`
- `railiance-fabric registry sync`
- `railiance-fabric registry sync-manifest`
- `railiance-fabric registry scan-manifest`
- `railiance-fabric registry ingest-discovery`
- `railiance-fabric registry accept-discovery`
- `railiance-fabric registry rescan-status`
Projection surfaces:
- Graph Explorer payload and manifest.
- Backstage projection.
- xRegistry projection.
- State Hub Fabric read-model import.
## Compatibility Risks
1. State Hub import compatibility:
`STATE-WP-0050` expects the current `FabricGraphExport` shape. Adding
required fields or changing node/edge semantics can break ingest unless the
export is versioned or State Hub is updated in lockstep.
2. Graph Explorer compatibility:
Graph Explorer filters and detail panes use current node kinds, layers,
dependency chains, unresolved states, and canon metadata. New actor/fabric
nodes and utility edges need UI mapping before the explorer remains useful.
3. Query command compatibility:
Provider/consumer/dependency-path commands are built on capability and
dependency declarations. They may remain useful as legacy views, but should
not be presented as the whole Fabric model.
4. Registry storage compatibility:
The registry stores snapshots as JSON, so schema migration is flexible, but
combined graph behavior currently deduplicates by node id across latest
per-repo snapshots. Fabric-scoped snapshots may need a root snapshot or
scenario/fabric identity instead of only repo latest snapshots.
5. Test fixture blast radius:
Most tests assert legacy declaration kinds, repo-scoped discovery keys, and
current export payload shape. The migration should add vNext tests before
replacing old assertions.
6. Canon mapping ambiguity:
Current canonical categories do not include financial actors, fabrics,
subfabrics, accounting attributions, or utility value interfaces. These
either need canonical mappings or explicit `mapping_fit: gap` handling.
7. Existing accepted graph baseline:
The current accepted graph contains 49 nodes and 58 edges from the
post-`RAIL-FAB-WP-0016` reset. It should be treated as a legacy baseline
and re-exported or archived before a controlled vNext reset.
## Migration Approach
1. Preserve legacy declarations as `v1alpha1` evidence.
Do not delete `fabric/` declarations or examples immediately. Reclassify
them as self-description and bootstrap evidence.
2. Introduce a vNext contract alongside the current export.
Add schema version metadata before making breaking changes. Prefer either
`railiance.fabric/v1alpha2` or an explicit export `schema_version`.
3. Add first-class model concepts before changing scanner roots.
Implement netkingdom, actor, fabric, subfabric, ownership, utility edge, and
accounting attribution semantics in schemas/tests first.
4. Extend discovery rather than replacing it.
Reuse `FabricDiscoverySnapshot`, replacement scopes, candidates,
provenance, reconciliation, and acceptance. Add accountability-root
manifest evidence and deployment automation adapters.
5. Seed the current one-fabric baseline.
Create the Railiance netkingdom root, current king, current lord/fabric, and
inherited ownership defaults. This lets existing nodes resolve ownership
before tenant subfabrics exist.
6. Version State Hub import.
Coordinate with `STATE-WP-0051` so State Hub can ingest both the old and
vNext export during the transition, or explicitly perform a read-model reset.
7. Rebuild and compare.
Produce a vNext export from the current baseline, compare it against the
legacy 49-node/58-edge export, and document intentional semantic changes.
## Follow-On Implementation Notes
For `RAIL-FAB-WP-0017-T02`:
- Define schema names and versioning for vNext graph exports.
- Decide whether netkingdom/fabric/actor are node kinds, top-level export
sections, or both.
- Define ownership inheritance and unresolved-owner representation.
- Define utility edge fields:
provider owner, consumer owner, provider boundary, consumer boundary,
payment schema, metering basis, and evidence.
- Define accounting fields:
cost center, profit center, allocation model, attribution validity.
For `RAIL-FAB-WP-0017-T03`:
- Add model classes or typed helpers beyond the generic `Declaration` wrapper.
- Extend validation to enforce resolvable ownership on accepted nodes.
- Update registry projection to preserve ownership, containment, accounting,
and utility metadata.
- Keep old declaration graph validation available as a legacy command or
compatibility path.
For `RAIL-FAB-WP-0017-T04`:
- Update `schemas/state-hub-export.schema.yaml`.
- Add sample vNext export payloads and tests.
- Coordinate the import fields with `STATE-WP-0051`.
For `RAIL-FAB-WP-0018`:
- Build an accountability-root manifest instead of extending
`registry/local-repos.yaml` into too many meanings.
- Treat State Hub attached repos as one discovery root, not as the Fabric
boundary itself.
- Add deployment automation and infrastructure evidence adapters before trying
to infer cross-boundary value edges.

View File

@@ -0,0 +1,226 @@
# Financial Fabric Operator Guide
This guide is the operator path for the financial Fabric reset described in
`docs/FabricDiscoveryAndUpdate.md`.
## Current Baseline
Railiance currently has one effective fabric because one actor pays for the
infrastructure. The accepted baseline lives at:
```text
fabric/financial/railiance-netkingdom.yaml
```
It defines:
- `railiance.netkingdom` as the netkingdom root;
- `actor.railiance.king` as the king with recovery, secrets, backup, and
termination authority;
- `actor.railiance.primary-lord` as the lord who pays for the current fabric;
- `fabric.railiance.primary` as the current active fabric;
- inherited ownership for accepted nodes until a more specific owner is
discovered or approved;
- a future subfabric template for tenant modeling.
The baseline is not a security-zone model. Do not introduce realm, domain, or
identity-zone language into the Fabric core when updating it.
## Deployment Overlay Baseline
Fabric membership is not the same as deployment environment. Use these current
Railiance deployment overlays when interpreting discovery evidence:
| Scenario | Environment | Access zone baseline | Notes |
|----------|-------------|----------------------|-------|
| `bernd-laptop` | `dev` | `private-dev` | Local machine used by one developer. Its loopback ports and local tools are useful evidence for debugging, but are not shared truth for other developers. |
| `coulombcore` | `test` | `collaborator-test`, `early-access` | Central test-stage server for collaborating developers and friendly early-access users. |
| `railiance01` | `prod` | `production-public`, `production-admin` | Production host. Developer access exists during alpha, but production should be able to move toward restricted operator access and applicable security and data-privacy controls. |
The routing authority is the source that maps names or ports to services in a
scenario. For local dev this may be a Makefile, script, process launcher, or
loopback binding. For test and production this should usually come from
Kubernetes `Service` and `Ingress`, Traefik/nginx/Caddy/HAProxy configuration,
DNS, and TLS automation.
Fabric should discover those routes and visualize the resulting zones. It
should not allocate ports, author reverse-proxy config, or define the access
policy. The policy authority is external evidence, such as NetKingdom IAM,
ingress policy, network policy, or local-only loopback binding.
## Refresh Loop
Run these checks from the `railiance-fabric` repo after changing declarations,
baseline ownership, discovery inputs, or export code:
```bash
railiance-fabric validate .
railiance-fabric export --format json
railiance-fabric export --format financial
python3 -m pytest tests/test_registry.py -q
```
Use the legacy JSON export for compatibility with existing `STATE-WP-0050`
State Hub behavior. Use the financial export to verify the vNext contract and
the ownership/fabric projection.
For accountability-root discovery, start from the current root manifest:
```text
fabric/discovery/railiance-accountability-roots.yaml
```
The manifest schema is documented in `docs/accountability-root-manifest.md`.
To collect raw evidence from those roots without promoting graph state:
```bash
railiance-fabric discover-roots --max-items-per-root 200
```
To inspect normalized identity candidates or persist a local evidence run:
```bash
railiance-fabric discover-roots --identity-projection
railiance-fabric discover-roots --store-db .railiance-fabric/accountability-evidence.sqlite3
```
To inspect ownership blockers and apply review decisions:
```bash
railiance-fabric discover-roots --ownership-review \
--store-db .railiance-fabric/accountability-evidence.sqlite3
railiance-fabric review-identity <stable-key> \
--store-db .railiance-fabric/accountability-evidence.sqlite3 \
--decision accept \
--owner-actor-id actor.railiance.primary-lord \
--fabric-id fabric.railiance.primary
```
To compare a new run with saved review outputs:
```bash
railiance-fabric discover-roots --delta \
--previous-identity-projection previous-identities.json \
--previous-ownership-review previous-ownership.json
```
The current bootstrap artifacts live at:
```text
fabric/discovery/snapshots/2026-05-24-railiance-bootstrap-identities.json
fabric/discovery/snapshots/2026-05-24-railiance-bootstrap-ownership-review.json
fabric/discovery/snapshots/2026-05-24-railiance-bootstrap-update-delta.json
exports/state-hub/2026-05-24-railiance-financial-fabric-v1.json
```
To refresh the same artifact set:
```bash
railiance-fabric discover-roots --include-remote --max-items-per-root 200 \
--identity-projection > fabric/discovery/snapshots/YYYY-MM-DD-railiance-bootstrap-identities.json
railiance-fabric discover-roots --include-remote --max-items-per-root 200 \
--ownership-review > fabric/discovery/snapshots/YYYY-MM-DD-railiance-bootstrap-ownership-review.json
railiance-fabric discover-roots --include-remote --max-items-per-root 200 \
--delta > fabric/discovery/snapshots/YYYY-MM-DD-railiance-bootstrap-update-delta.json
railiance-fabric export --format financial . \
> exports/state-hub/YYYY-MM-DD-railiance-financial-fabric-v1.json
```
The financial export must satisfy these invariants:
- every accepted node has resolvable ownership;
- every accepted node has fabric containment;
- cost/profit center fields are optional accounting attribution, not fabric
boundaries;
- cross-boundary utility edges carry provider and consumer owner context when
known;
- unresolved ownership or containment remains explicit rather than invented by
State Hub.
## Registry Reset Rebuild
After a guarded registry reset, rebuild from durable roots in this order:
1. Confirm the baseline still reflects who pays for the infrastructure.
2. Validate the repo evidence with `railiance-fabric validate .`.
3. Emit `railiance-fabric export --format financial` and review the ownership
projection.
4. Start the registry and sync this repo:
```bash
railiance-fabric-registry --db .railiance-fabric/registry.sqlite3 --port 8765
railiance-fabric registry sync --repo-slug railiance-fabric .
```
5. Sync broader known repos with `registry/local-repos.yaml` or
`registry/railiance-repos.yaml` when their local checkouts exist.
6. Compare snapshot diffs before promoting new discovery output.
Repo-local `fabric/` declarations are evidence during this rebuild. The
replacement discovery loop should start from the netkingdom, king, lords,
tenants, deployment automation, service manifests, endpoints, backups, and
secret roots rather than asking each repo to own all external relations.
## State Hub Handoff
State Hub is a read model for Fabric topology. It should ingest Fabric exports,
link them to repos/workstreams/tasks, and expose dashboard/search views. It
should not author ownership, fabric membership, or utility boundaries.
Until `STATE-WP-0051` is implemented:
- continue importing or syncing the legacy `v1alpha1` graph for existing State
Hub graph views;
- keep the `v1alpha2` financial export as the contract artifact for State Hub
implementation and review;
- update file-backed workplan state through State Hub consistency after
workplan edits:
```bash
cd ~/state-hub
make fix-consistency REPO=railiance-fabric
```
After `STATE-WP-0051`, the financial export should become the preferred State
Hub graph import. The importer must preserve netkingdom, actors, fabrics,
containment, ownership, accounting attribution, cross-boundary utility context,
and unresolved gaps.
To import a saved financial export into State Hub:
```bash
curl -s -X POST \
"http://127.0.0.1:8000/fabric/graph-exports?source_repo_slug=railiance-fabric" \
-H "Content-Type: application/json" \
--data-binary @exports/state-hub/2026-05-24-railiance-financial-fabric-v1.json
```
If the `/fabric/graph-exports` endpoints return `500` while ordinary State Hub
routes work, run the State Hub migrations and retry:
```bash
cd ~/state-hub
make migrate
# or, when uv is not on PATH:
.venv/bin/alembic upgrade head
```
## Discovery Work Handoff
The next discovery/update-loop work should replace the baseline projection with
durable evidence collection:
- discover repos from State Hub and Gitea;
- discover deployment realities from automation and infrastructure manifests;
- discover services, machines, endpoints, backup roots, and secret roots;
- normalize identities across repo URLs, host paths, image names, service
names, and endpoint contracts;
- resolve owner and containment from the baseline, explicit evidence, or
review decisions;
- emit deltas for ownership, containment, nodes, edges, and cross-boundary
utility changes.
The baseline projection is therefore a safe bridge, not the final discovery
engine.

View File

@@ -0,0 +1,493 @@
# Financial Fabric VNext Contract
Date: 2026-05-24
Workplan: `RAIL-FAB-WP-0017`
Status: contract draft for implementation
## Intent
The vNext Fabric contract models the Railiance netkingdom as a durable
infrastructure-responsibility graph.
The contract separates:
- financial responsibility boundaries from environments and views;
- ownership from repository metadata;
- cross-boundary utility interfaces from ordinary technical dependencies;
- accounting attribution from fabric membership;
- durable topology from live telemetry.
The contract should be implemented as a versioned export shape before replacing
the existing `railiance.fabric/v1alpha1` declaration-centered graph.
## Versioning
Recommended contract identity:
```yaml
apiVersion: railiance.fabric/v1alpha2
kind: FabricGraphExport
schema_version: financial-fabric-v1
```
`v1alpha1` remains the compatibility layer for legacy declarations and the
current State Hub import. `v1alpha2` introduces first-class netkingdom,
actor, fabric, subfabric, ownership, utility, and accounting semantics.
## Top-Level Export Shape
```yaml
apiVersion: railiance.fabric/v1alpha2
kind: FabricGraphExport
schema_version: financial-fabric-v1
generated_at: "2026-05-24T00:00:00Z"
source:
producer: railiance-fabric
registry: registry
commit: ""
generation_reason: rebuild | rescan | operator_refresh
compatibility:
legacy_v1alpha1_supported: true
breaking_reset: false
netkingdom:
id: railiance.netkingdom
name: Railiance Netkingdom
king_actor_id: actor.railiance.king
actors: []
fabrics: []
nodes: []
edges: []
unresolved: []
```
The top-level sections are intentionally explicit. `nodes` and `edges` remain
the primary graph payload for State Hub and visualizers, but `netkingdom`,
`actors`, and `fabrics` define the responsibility boundary context used to
resolve ownership and containment.
## Actors
Actors are accountable parties. They are graph addressable and may also be
materialized as nodes when a consumer needs a pure node/edge projection.
```yaml
id: actor.railiance.king
kind: FabricActor
role: king
name: Railiance King
legal_name: ""
description: Responsible for the Railiance netkingdom.
authority:
recovery_authority: true
secrets_authority: true
backup_authority: true
termination_authority: true
relationships:
contracts_with:
- actor.railiance.primary-lord
```
Actor roles:
- `king`: responsible for the netkingdom and relevant recovery/secrets/backup
authority.
- `lord`: pays for a fabric.
- `tenant`: pays for restricted use of a subfabric.
- `operator`: operates infrastructure on behalf of a king, lord, or tenant.
- `steward`: maintains a repo, service, or capability but does not necessarily
pay for it.
Only king, lord, and tenant define financial boundary semantics. Operator and
steward roles are supporting roles.
## Fabrics And Subfabrics
Fabrics and subfabrics are responsibility boundaries.
```yaml
id: fabric.railiance.primary
kind: Fabric
name: Railiance Primary Fabric
netkingdom_id: railiance.netkingdom
lord_actor_id: actor.railiance.primary-lord
parent_fabric_id: null
boundary:
boundary_type: fabric
criterion: financial_and_operational_accountability
payment_responsibility: actor.railiance.primary-lord
operational_responsibility: actor.railiance.king
recovery_responsibility: actor.railiance.king
status: active
evidence_refs: []
```
```yaml
id: subfabric.railiance.tenant.coulomb
kind: Subfabric
name: Coulomb Tenant Subfabric
netkingdom_id: railiance.netkingdom
parent_fabric_id: fabric.railiance.primary
tenant_actor_id: actor.coulomb.tenant
boundary:
boundary_type: subfabric
criterion: restricted_paid_tenant_utility
payment_responsibility: actor.coulomb.tenant
operational_responsibility: actor.railiance.primary-lord
recovery_responsibility: actor.railiance.king
status: planned
evidence_refs: []
```
Fabric membership changes when payment, operational responsibility, recovery
responsibility, or legal accountability changes. It does not change because a
service moves environments, a host is replaced, a repo is refactored, or a
diagnostic view changes.
## Nodes
Every accepted node must resolve ownership and containment.
```yaml
id: state-hub.api
kind: Service
name: State Hub API
repo: state-hub
domain: custodian
lifecycle: active
containment:
netkingdom_id: railiance.netkingdom
fabric_id: fabric.railiance.primary
subfabric_id: null
environment: local
deployment_scenario_id: null
ownership:
owner_actor_id: actor.railiance.primary-lord
owner_role: lord
resolution: inherited
inherited_from: fabric.railiance.primary
supporting_actor_ids:
- actor.state-hub.steward
accounting:
cost_center_id: null
profit_center_id: null
allocation_model: null
evidence:
state: observed
review_state: accepted
confidence: 0.95
refs: []
attributes: {}
```
Required accepted-node semantics:
- `containment.netkingdom_id`
- `containment.fabric_id`
- `ownership.owner_actor_id`
- `ownership.owner_role`
- `ownership.resolution`
- `evidence.state`
- `evidence.review_state`
Recommended compatibility fields:
- `repo`
- `domain`
- `lifecycle`
- `canon_category`
- `canon_anchor`
- `mapping_fit`
- `attributes`
## Ownership Resolution
Ownership resolution values:
- `explicit`: evidence directly names the owner actor.
- `inherited`: ownership is inherited from containing fabric or subfabric.
- `unresolved`: no acceptable owner could be resolved.
- `ambiguous`: multiple plausible owners exist and review is needed.
Unresolved or ambiguous nodes may appear as candidates or importable read-model
gaps, but they must not silently become accepted graph truth.
```yaml
id: unresolved:node:fixture
target_id: fixture.unknown-service
kind: unresolved_ownership
severity: needs_review
message: Node has no explicit owner and no resolvable fabric/subfabric owner.
evidence_refs: []
```
## Edges
Edges keep technical topology while adding boundary and value semantics.
```yaml
id: edge:state-hub.api:exposes:state-hub.http
from: state-hub.api
to: state-hub.http
type: exposes
relationship_category: technical
canonical_type: exposes
boundary:
crosses_fabric_boundary: false
crosses_subfabric_boundary: false
evidence:
state: observed
review_state: accepted
confidence: 0.95
refs: []
attributes: {}
```
Relationship categories:
- `containment`: netkingdom, fabric, subfabric, actor, or node containment.
- `ownership`: owner/steward/operator relationships.
- `technical`: deployment, exposure, dependency, flow, build, or evidence edge.
- `utility`: value-bearing interface from provider to consumer.
- `accounting`: cost/profit attribution or allocation edge.
- `evidence`: source artifact or provenance relationship.
## Cross-Boundary Utility Edges
Cross-boundary utility edges are first-class because they represent value moving
across financial responsibility boundaries.
```yaml
id: utility:state-hub-api:coulomb-tenant
from: state-hub.http
to: tenant.coulomb.automation-client
type: provides_utility_to
relationship_category: utility
canonical_type: depends_on
provider:
owner_actor_id: actor.railiance.primary-lord
fabric_id: fabric.railiance.primary
subfabric_id: null
consumer:
owner_actor_id: actor.coulomb.tenant
fabric_id: fabric.railiance.primary
subfabric_id: subfabric.railiance.tenant.coulomb
boundary:
crosses_fabric_boundary: false
crosses_subfabric_boundary: true
utility:
utility_type: coordination_api
contract_id: state-hub.http
payment_schema_id: payment.internal-tenant-access
metering_basis: request | seat | flat | allocation | unknown
business_model: tenant_utility
accounting:
provider_profit_center_id: null
consumer_cost_center_id: null
allocation_model: null
evidence:
state: declared
review_state: accepted
confidence: 0.8
refs: []
attributes: {}
```
The edge may cross a subfabric boundary without crossing the parent fabric
boundary. This is expected for tenant utility inside the current Railiance
fabric.
## Cost And Profit Center Attribution
Accounting attribution is optional and must not redefine containment.
Node-level attribution:
```yaml
accounting:
cost_center_id: cc.platform.shared
profit_center_id: null
allocation_model: direct
valid_from: "2026-05-24"
valid_until: null
```
Edge-level attribution:
```yaml
accounting:
provider_profit_center_id: pc.tenant-utilities
consumer_cost_center_id: cc.coulomb.automation
allocation_model: usage_weighted
payment_schema_id: payment.internal-tenant-access
metering_basis: request
valid_from: "2026-05-24"
valid_until: null
```
Cost/profit center changes should produce accounting deltas and views, not
fabric moves.
## Evidence And Provenance
Every discovered or accepted fact should carry evidence.
```yaml
evidence:
state: observed | declared | inferred | proposed | gap
review_state: accepted | candidate | needs_review | rejected
confidence: 0.0
refs:
- id: evidence:state-hub:compose:api
source_kind: deployment_manifest
source_path: compose.yaml
source_url: null
source_repo: state-hub
source_commit: abc123
scanner: compose
scanner_version: "0.1.0"
content_hash: sha256:...
observed_at: "2026-05-24T00:00:00Z"
```
The contract continues to distinguish durable discovered configuration from
live operational telemetry. Health, current running state, latency, incident
status, and usage volume are not Fabric core fields.
## Legacy Canon Mapping
Existing canonical metadata remains useful for compatibility, but some legacy
terms should be demoted to evidence.
| Existing kind/type | vNext disposition |
| --- | --- |
| `Repository` | Keep as source-repository node evidence. |
| `ServiceDeclaration` | Legacy self-description evidence for `Service`. |
| `CapabilityDeclaration` | Legacy self-description evidence for utility or service capability. |
| `InterfaceDeclaration` | Legacy self-description evidence for `Endpoint` or `Contract`. |
| `DependencyDeclaration` | Legacy consumer-purpose or dependency evidence; not sufficient for value edge alone. |
| `BindingAssertion` | Legacy binding evidence; may support utility edge when boundary actors are known. |
| `RuntimeService`, `DeploymentService`, `Kubernetes*`, `Server` | Durable deployment/runtime-resource evidence. |
| `provides`, `exposes`, `runs_on`, `deployed_as`, `flows_to` | Keep as technical/topology edges. |
| `consumes`, `binds:*`, `uses_interface` | Keep as technical dependency edges; promote to utility edges only when provider/consumer ownership and boundary context are known. |
| `declares` | Display/evidence edge only. |
New vNext node kinds to map:
| vNext kind | Suggested canonical category |
| --- | --- |
| `Netkingdom` | `software-system` until canon has a better category. |
| `FabricActor` | `consumer-purpose` or `control` depending role; likely canon gap. |
| `Fabric` | `software-system` or `control`; likely canon gap. |
| `Subfabric` | `software-system` or `control`; likely canon gap. |
| `UtilityInterface` | `endpoint` when technical, `software-system` when abstract. |
| `CostCenter` | `control`; likely canon gap. |
| `ProfitCenter` | `control`; likely canon gap. |
New vNext edge types to map:
| vNext edge type | Suggested canonical type |
| --- | --- |
| `contains` | `part_of` |
| `owned_by` | `governed_by` |
| `operated_by` | `governed_by` |
| `provides_utility_to` | `depends_on` with `relationship_category: utility` |
| `attributed_to_cost_center` | `governed_by` or canon gap |
| `attributed_to_profit_center` | `governed_by` or canon gap |
| `evidenced_by` | `evidenced_by` |
## Examples
### Current Single Railiance Fabric
```yaml
netkingdom:
id: railiance.netkingdom
name: Railiance Netkingdom
king_actor_id: actor.railiance.king
actors:
- id: actor.railiance.king
kind: FabricActor
role: king
name: Railiance King
- id: actor.railiance.primary-lord
kind: FabricActor
role: lord
name: Railiance Primary Lord
fabrics:
- id: fabric.railiance.primary
kind: Fabric
name: Railiance Primary Fabric
netkingdom_id: railiance.netkingdom
lord_actor_id: actor.railiance.primary-lord
parent_fabric_id: null
status: active
```
### Future Tenant Subfabric
```yaml
actors:
- id: actor.coulomb.tenant
kind: FabricActor
role: tenant
name: Coulomb Tenant
fabrics:
- id: subfabric.railiance.tenant.coulomb
kind: Subfabric
name: Coulomb Tenant Subfabric
netkingdom_id: railiance.netkingdom
parent_fabric_id: fabric.railiance.primary
tenant_actor_id: actor.coulomb.tenant
status: planned
```
### Cross-Subfabric Utility
```yaml
edges:
- id: utility:state-hub-http:coulomb-client
from: state-hub.http
to: coulomb.automation-client
type: provides_utility_to
relationship_category: utility
provider:
owner_actor_id: actor.railiance.primary-lord
fabric_id: fabric.railiance.primary
subfabric_id: null
consumer:
owner_actor_id: actor.coulomb.tenant
fabric_id: fabric.railiance.primary
subfabric_id: subfabric.railiance.tenant.coulomb
boundary:
crosses_fabric_boundary: false
crosses_subfabric_boundary: true
utility:
utility_type: coordination_api
contract_id: state-hub.http
payment_schema_id: payment.internal-tenant-access
metering_basis: unknown
business_model: tenant_utility
```
## State Hub Import Requirements
State Hub should materialize at least:
- export version and schema version;
- netkingdom id;
- fabric/subfabric ids and names;
- actor ids, roles, and names;
- node containment fields;
- node owner actor and owner role;
- ownership resolution state;
- edge relationship category;
- utility provider/consumer ownership context;
- boundary crossing booleans;
- cost/profit center attribution;
- unresolved ownership and containment gaps;
- retained canon metadata and evidence state.
State Hub must not invent missing ownership or redefine fabric membership. It
may display unresolved gaps and expose filters/views for operator review.

View File

@@ -2,8 +2,9 @@
The first rollout is represented by the seed declarations under `fabric/`.
Those files are intentionally centralized in Railiance Fabric for bootstrap;
the long-term target is for each owning repo to carry its own `fabric/`
declarations.
the long-term target is for each owning repo to contribute local evidence while
financial Fabric ownership and boundary decisions come from accountability-root
discovery.
## Seeded Repos
@@ -28,8 +29,9 @@ For each owning repo:
4. Validate the owning repo together with `railiance-fabric` and other
providers/consumers it depends on.
5. Export the multi-repo graph for State Hub ingestion.
6. Once repo-local declarations are authoritative, remove or mark the central
seed declarations as bootstrap-only.
6. Once accountability-root discovery can reproduce the graph, mark the
central seed declarations as bootstrap evidence and keep only the repo-local
facts that remain useful self-description.
## Suggested Order

View File

@@ -0,0 +1,292 @@
# Graph Explorer Contract
This note defines the first manifest and payload contract for the interactive
Fabric map and the possible reusable graph explorer engine.
The contract is intentionally host-neutral. Fabric and repo-scoping should be
able to use the same interaction shell by exposing a manifest and a graph
payload with stable fields.
## Files
- `schemas/graph-explorer-manifest.schema.yaml` validates a host manifest.
- `schemas/graph-explorer-payload.schema.yaml` validates graph payloads.
- `railiance_fabric.graph_explorer` provides the first Fabric registry
manifest and payload projection.
## Registry Endpoints
The registry service exposes the first Fabric projection:
```text
GET /ui/graph-explorer
GET /exports/graph-explorer/manifest
GET /exports/graph-explorer
```
The local CLI can emit the same payload for repo-local inspection:
```bash
railiance-fabric export --format graph-explorer
```
The manifest tells a graph shell where to load data, which fields are stable,
which layers exist, which filter fields are available, and which modes the host
supports.
Fabric currently declares `profile_persistence: local`. That means the shell
stores named map views in browser `localStorage`, supports duplicate/delete
inside that browser, and can copy a URL with the current query parameters and a
state blob. Local profile ids can be reopened in the same browser profile; the
copied state blob is the portable sharing path until a host-backed profile API
is added.
The payload is compatible with Cytoscape-style element arrays:
```json
{
"apiVersion": "railiance.fabric/v1alpha1",
"kind": "GraphExplorerPayload",
"manifest_id": "railiance-fabric.registry-map",
"mode": "full",
"elements": [
{
"data": {
"id": "repo:railiance-fabric",
"stableKey": "repo:railiance-fabric",
"kind": "Repository",
"layer": "repository",
"label": "Railiance Fabric",
"displayState": "show"
}
}
],
"hidden_elements": []
}
```
## Required Payload Semantics
Every element must include:
- `id`: the current element id used by the graph library.
- `stableKey`: the durable id used by profile rules, manual overrides, layout
state, and deep links.
- `kind`: host-specific entity kind.
- `layer`: host-declared layer used for layout, grouping, and color.
- `displayState`: one of `show`, `blur`, or `hide`.
Edges are ordinary elements whose data also includes:
- `source`
- `target`
- `edgeType`
- `strength`
- `sameLayer`
Hosts should also include useful optional fields when available: `label`,
`name`, `description`, `repo`, `domain`, `lifecycle`, `reviewState`,
`freshnessState`, `confidence`, `visualSize`, `ownership`, `unresolved`,
`sourceReferences`, and `deepLinks`.
Fabric hosts should also include deployment overlay fields when available:
`deploymentEnvironment`, `deploymentScenario`, `routingAuthority`,
`accessZone`, `policyAuthority`, `exposure`, and `host`. These fields describe
where an element runs or is reachable in a concrete deployment scenario. They
do not define fabric membership and must remain filter/grouping metadata unless
the host explicitly promotes a separate graph relationship with evidence.
Edges may include layout hints used by the client-side layout engine:
`sameRepo`, `sourceRepo`, `targetRepo`, `layoutAffinity`,
`layoutIdealLength`, and `layoutElasticity`. Fabric uses these hints to keep
same-repo entities closer than cross-repo dependencies. Deployment-to-server
edges are intentionally shortest and most elastic; deployment-to-repo edges are
longer and looser so infrastructure placement does not collapse into the repo
node.
## Semantic Attractor Modes
Semantic attractors are view-only topic poles that can pull graph entities
toward conceptual neighborhoods in spring-based layouts. For repository maps,
an operator might choose attractors such as `security`, `development`, and
`operations`; Fabric can then score each repository's semantic closeness to
those attractors from repo-owned `SCOPE.md` evidence and map the score to
layout strength.
Attractors are not domain edges and do not change Fabric graph data. They may
be materialized as synthetic display-only nodes and `semantic_attraction`
edges, or carried as top-level view metadata that the renderer turns into
layout forces. Attraction scores should remain inspectable, with source
references and confidence, so the operator can understand why a repository was
pulled toward a topic.
Unlike zones, attractors may overlap. A repository can be close to both
`development` and `operations`, and the layout should place it between those
poles. Zone resolvers, boundary diagnostics, dependency queries, blast-radius
queries, and collapsed-zone boundary edges should ignore semantic attraction
edges unless a host explicitly promotes an attractor relation into canonical
graph data.
See `docs/semantic-attractors.md` for the concept model, scoring semantics,
payload direction, and implementation path.
## Display State Ownership
The contract allows either the host service or the engine to evaluate display
state.
The precedence rule is fixed:
1. Default element state is `show`.
2. Rules are applied in list order; later matching rules override earlier
matching rules.
3. Manual overrides win last.
4. Edges connected to hidden nodes are hidden.
5. Edges connected to blurred nodes may carry a contextual muted class or data
hint.
Repo-scoping currently evaluates this host-side. A future extracted engine can
evaluate it client-side for static exports, but host-provided `displayState`
must remain valid input.
## Fabric Layers
The first Fabric manifest declares:
| Layer | Purpose |
|-------|---------|
| `repository` | Registered source repositories, including registered-only repos. |
| `server` | Endpoint hosts inferred from registered interface URLs. |
| `deployment` | Service deployment instances per declared environment. |
| `service` | Service declarations. |
| `capability` | Capability declarations. |
| `interface` | Interface declarations. |
| `dependency` | Dependency declarations, including unresolved dependency nodes. |
| `binding` | Binding assertions between consumer dependencies and providers. |
| `library` | Future library/SBOM inventory nodes. |
## Zone Overlay Modes
The graph explorer should support zone-oriented modes for Fabric payloads:
| Mode | Purpose |
|------|---------|
| `fabric` | Group by financial responsibility: fabric, subfabric, owner. |
| `environment` | Group by `dev`, `test`, `prod`, or other deployment environment. |
| `deployment-scenario` | Group by concrete scenario such as `bernd-laptop`, `coulombcore`, or `railiance01`. |
| `routing-authority` | Group by loopback launcher, Compose port mapping, ingress controller, reverse proxy, DNS, or equivalent route authority. |
| `access-zone` | Group by intended reachability such as `private-dev`, `collaborator-test`, `early-access`, `production-public`, or `production-admin`. |
Zone modes are diagnostic views. They answer "where does this run or who can
reach it here?" without mutating the underlying Fabric responsibility boundary.
Zone boundary overlays are a visual layer over the graph canvas. They should be
computed from visible node positions after layout/filtering rather than modeled
as graph parent nodes. The overlay should be backed by explicit zone definitions
and a resolver so visible nodes are assigned to at most one rendered zone. The
default boundary grouping is `deploymentEnvironment`:
| Overlay label | Matching nodes |
|---------------|----------------|
| `dev-tegwick` | visible nodes with `deploymentEnvironment: dev` in the private local development overlay |
| `test` | visible nodes with `deploymentEnvironment: test` or legacy `staging` |
| `prod` | visible nodes with `deploymentEnvironment: prod` |
Nodes without deployment overlay data are not enclosed. Edge-only deployment
overlay evidence may contribute to zone summaries and warnings, but it should
not create a boundary unless at least one visible node belongs to the same zone.
When access-zone grouping is selected, boundaries use `accessZone` values such
as `private-dev`, `collaborator-test`, `production-public`, or
`production-admin`.
Zone labels should be rendered as plain text in the upper-left corner of the
zone rectangle, without badge frames or white backgrounds. The label may still
act as the zone's focus/drag handle as long as it visually reads as text drawn
on the zone surface.
Useful warnings for the graph explorer include:
- control surfaces in user-facing access zones;
- production nodes with unrestricted developer access;
- early-access routes without a policy authority;
- services present in production but missing from test;
- local-only surfaces that appear in shared or production scenarios;
- conflicting port or host claims within the same deployment scenario.
Zone resolvers should also expose scoped diagnostics in zone detail panels. The
initial diagnostic set includes empty zone seed sets, visible nodes matched by
multiple zone definitions, and edges crossing zone boundaries. Attraction
diagnostics such as multiple attraction candidates or depth-limit stops belong
to the same resolver diagnostic channel when attraction rules are enabled.
Display-only context edges, such as repository `declares` edges, are evidence
for where declarations came from. They must not count as zone boundary
connectivity, attraction paths, or collapsed-zone boundary edges unless a host
explicitly promotes them to canonical graph relationships.
Saved graph profiles should persist zone view state as an explicit nested
`zone` object. The initial fields are `visible`, `grouping`, `definitionSet`,
`presentation`, and `containers`. URL parameters may continue to expose
compatibility aliases such as `zoneBoundaries`, `zoneGrouping`, and
`zoneDefinitionSet`, but saved profiles should prefer the nested object so
future zone definition sets, presentation preferences, and operator-placed zone
surfaces can be restored without another state migration.
Zone containers are view state, not fabric data. A container stores a stable
zone surface position and size in graph coordinates. Global graph layout may
place unzoned nodes and provide an initial center for new zones, but existing
zone containers should keep their operator-chosen positions when the layout
algorithm changes. After the global layout pass, each zone may project its
assigned visible nodes into local coordinates inside its container. The current
local layout choices are compact grid and circle. The selected zone-local
layout algorithm belongs in the nested `zone.layout.algorithm` view state so it
can be restored by saved or copied views without changing the Fabric payload.
Zone collapse is a view-only operation. A collapsed zone should hide its visible
member nodes, replace them with a synthetic zone node, and draw synthetic
boundary edges from that zone node to visible external neighbors. Internal edges
are summarized on the zone node rather than rendered. Expanding the zone removes
the synthetic elements and restores the original graph elements without
changing the underlying payload.
Zone dragging is also view-only. Dragging a zone handle should translate the
currently assigned visible member nodes by the same delta and then recompute the
overlay bounds from the new node positions. The operation updates Cytoscape view
coordinates only; it does not change Fabric graph data.
## Repo-Scoping Compatibility
Repo-scoping can adapt without a rewrite because its current graph payload
already exposes most required fields:
- `id`, `stableKey`, `kind`, `layer`, labels, and metadata-rich data objects.
- `displayState`, `visibilitySource`, and `visibilityReason`.
- edge `source`, `target`, `dependencyType`, `strength`, `sameLayer`, and
visual width.
- profile data, filter rules, manual overrides, hidden elements, and orphaned
overrides.
The main adapter work is manifest generation and small field aliases:
`dependencyType` can map to `edgeType`, repo-scoping layers become manifest
layers, and existing profile endpoints can be listed under manifest
`endpoints.profiles`.
## Extraction Boundary
The extracted `graph-explorer-engine` should own:
- graph rendering and layout controls
- filter and manual override UI
- hover popups and selection detail panels
- profile UI when the host declares profile endpoints
- browser-local profiles, URL state, and copied state blobs
- schema definitions and compatibility tests
Host repos should own:
- graph projection and metadata enrichment
- host-side profile persistence, when a repo needs shared/team profiles
- authentication and authorization
- domain-specific graph modes
- deep links back to source systems
- deployment overlay extraction from the route/proxy/deployment authority they
control

View File

@@ -0,0 +1,257 @@
# Graph Explorer Operations And Extraction
This note closes the operational side of the interactive Fabric map. It records
how to launch and refresh the current registry-backed explorer, what has been
verified, and how to extract the shared engine once the second adapter is ready.
## Launch
List available Make targets from the repo root:
```bash
make
```
Start the registry-backed graph explorer explicitly:
```bash
make graph-explorer
```
This serves the graph explorer at:
```text
http://127.0.0.1:8765/ui/graph-explorer
```
The target defaults to `.railiance-fabric/registry.sqlite3`, host
`127.0.0.1`, and port `8765`. Override those when needed:
```bash
make graph-explorer PORT=8876
make graph-explorer HOST=0.0.0.0 PORT=8765 REGISTRY_DB=/tmp/railiance-fabric.sqlite3
```
Equivalent raw command:
```bash
railiance-fabric-registry --db .railiance-fabric/registry.sqlite3 --port 8765
```
Useful supporting endpoints:
```text
GET /exports/graph-explorer/manifest
GET /exports/graph-explorer
GET /status
```
The Fabric manifest currently declares `profile_persistence: local`. Saved map
views are stored in browser `localStorage`, URL query parameters carry normal
filter state, and copied state URLs include a state blob so manual overrides can
be shared without a profile service.
The refined rule panel is also browser-local. Rules target either nodes or
edges, optionally narrow by type and by attributes present on the currently
available elements, and then apply one of five modifiers:
- `show`, `hide`, and `blur` are visibility states.
- `highlight` keeps an element visible and adds visual emphasis.
- `remove` hides matching elements and excludes them from the next layout run.
Rules are applied top to bottom. Later matching rules refine earlier matching
rules. Manual overrides win after rules except for `remove`, which is treated as
stronger because it changes the layout membership. Edges connected to hidden
nodes are hidden; edges connected to removed nodes are removed.
## Refresh
Refresh this checkout into the running registry:
```bash
railiance-fabric registry sync \
--registry-url http://127.0.0.1:8765 \
--repo-slug railiance-fabric \
.
```
Refresh the known local Railiance repos:
```bash
railiance-fabric registry sync-manifest \
registry/railiance-repos.yaml \
--registry-url http://127.0.0.1:8765
```
Refresh every locally available active State Hub repo:
```bash
railiance-fabric registry sync-manifest \
registry/local-repos.yaml \
--registry-url http://127.0.0.1:8765
```
Repos without Fabric declarations remain registered-only. The graph explorer
intentionally shows them as onboarding gaps instead of hiding them.
## Verification
The automated coverage for this slice lives in `tests/test_graph_explorer.py`:
- manifest and payload schema validation
- registered-only repo projection
- `railiance-fabric export --format graph-explorer`
- registry API routes for manifest, payload, and UI
- static UI wiring for profile controls, rule controls, orientation text, and
shared-state support
Manual smoke checks for a local registry:
```bash
python3 -m pytest
python3 -m railiance_fabric.cli validate .
```
Extract and syntax-check the embedded JavaScript when the UI changes:
```bash
python3 -c "from railiance_fabric.graph_explorer_ui import graph_explorer_page; from pathlib import Path; page=graph_explorer_page(); script=page.split(chr(60)+'script'+chr(62))[1].split(chr(60)+'/script'+chr(62))[0]; Path('/tmp/graph-ui-script.js').write_text(script, encoding='utf-8')"
node --check /tmp/graph-ui-script.js
```
With the registry running, confirm that the served manifest reports local
profiles:
```bash
curl -s http://127.0.0.1:8765/exports/graph-explorer/manifest
```
## Extraction Decision
Recommendation: keep the shell in `railiance-fabric` until the repo-scoping
adapter is implemented against the same manifest and payload schemas. Extract
after two hosts are proven:
- Fabric registry map
- repo-scoping dependency graph
Recommended repository name: `graph-explorer-engine`.
The extracted repository should own:
- `GraphExplorerManifest` and `GraphExplorerPayload` schemas
- static graph explorer assets and mount/bootstrap code
- display-state and rule evaluation helpers for hosts that want client-side
rules, including `show`, `hide`, `blur`, `highlight`, and `remove`
- browser-local profile handling, URL state, copied state blobs, and profile UI
- Cytoscape rendering, layouts, hover popups, detail panels, focus modes, and
manual override controls
- conformance fixtures proving Fabric and repo-scoping payloads both load
Host repositories should keep:
- graph projection and domain metadata enrichment
- host vocabulary and manifest labels for node types, edge types, rule fields,
modes, and orientation terms
- host-side profile persistence, when shared/team profiles are required
- authentication, authorization, and deployment
- domain-specific modes and deep links
- registry or analysis service APIs
## Adapter Readiness Notes
The refined shell is closer to extraction, but these Fabric-specific assumptions
should be made manifest-driven or host-adapted before `graph-explorer-engine`
becomes a separate repo:
- The shell still expects the internal element type field to be named `layer`.
User-facing text now says nodes and node types, but the shared contract should
either rename this to `nodeType` or declare the field through
`manifest.identity`.
- Node shapes are hardcoded against Fabric node type ids such as `repository`,
`service`, `deployment`, `server`, `capability`, `interface`, `dependency`,
`binding`, and `library`.
- Rule-builder attributes are derived from a fixed allowlist. Repo-scoping can
use the model, but the allowlist should move to manifest filter fields so a
host can expose facts, evidence, confidence, freshness, scope, ability, or
other domain attributes without changing engine code.
- Mode behavior is hardcoded for Fabric's `onboarding-gaps`, `unresolved`,
`selected-path`, and `neighborhood` semantics. The reusable engine should
either provide generic selectors or let hosts define mode predicates.
- The orientation panel still contains Fabric-specific renderers for
repositories, services, interfaces, dependencies, and capabilities. This
should stay host-owned or become a manifest-provided details adapter.
- The default detail rows know about `source`, `target`, `edgeType`, `strength`,
deep links, and source references. That is acceptable as a shared baseline,
but host-specific row ordering should be manifest-driven.
The current rule-panel data model is compatible with repo-scoping if repo-scoping
maps its graph elements into the same basic shape:
```json
{
"target": "node",
"type": "fact",
"attribute": "reviewState",
"value": "candidate",
"action": "blur"
}
```
For extraction, prefer repo-scoping adapter parity as the next workplan. One
more Fabric-side polish pass is still useful for orientation workflows, but it
does not need to block proving the second host.
Suggested public API:
```ts
type GraphExplorerManifest = unknown;
type GraphExplorerPayload = unknown;
mountGraphExplorer({
container,
manifestUrl,
graphUrl,
initialState,
}: {
container: HTMLElement;
manifestUrl: string;
graphUrl?: string;
initialState?: Record<string, unknown>;
}): Promise<{ destroy(): void }>;
```
Schema ownership should move to `graph-explorer-engine` at extraction time.
Fabric should then pin an engine schema version and keep its projection tests as
adapter conformance tests.
## Repo-Scoping Adapter Parity Checklist
Before extraction, repo-scoping should prove that the shared shell can consume
its RREG-WP-0010/RREG-WP-0011 behavior:
- expose a manifest with repo-scoping layers, filter fields, modes, and profile
endpoint capabilities
- preserve existing stable keys for facts, evidence, features, capabilities,
abilities, scopes, and edges
- map `dependencyType` to `edgeType`
- carry display states of `show`, `blur`, and `hide`
- retain confidence sizing, edge strength sizing, same-layer hints, and review
state
- preserve manual overrides and hidden/orphaned override recovery semantics
- support profile create, update, duplicate, delete, and latest-default loading
through host endpoints
- keep hover popups, selection details, selected-path, and neighborhood focus
- add adapter fixtures that validate against the shared schemas
## Migration Steps
1. Add a repo-scoping manifest endpoint or static manifest fixture.
2. Add shared conformance fixtures for one Fabric graph and one repo-scoping
graph.
3. Move the static UI shell and schemas into `graph-explorer-engine`.
4. Replace Fabric's local HTML generator with an engine asset route plus Fabric
manifest/payload URLs.
5. Replace repo-scoping's bespoke shell with the same engine mount.
6. Keep both host test suites validating their projections against the engine
schemas.

View File

@@ -0,0 +1,84 @@
# Graph Explorer Transfer Review
This note closes the first implementation step for `RAIL-FAB-WP-0008-T01`.
It reviews the repo-scoping dependency graph work from `RREG-WP-0010` and
`RREG-WP-0011` and turns the transferable parts into Fabric requirements.
## Source Implementation
Repo-scoping already has a useful graph explorer shape:
- `docs/adr-dependency-graph-visualization-framework.md` chooses Cytoscape.js
because the required interaction model is graph-native: pan, zoom, selection,
layouts, styling, filtering, and path exploration.
- `docs/dependency-visualization-exploration.md` defines layered graph data,
`show` / `blur` / `hide` display states, deterministic filters, manual
overrides, and saved view profiles.
- `src/repo_scoping/core/service.py` emits Cytoscape-compatible payloads with
stable keys, metadata-rich node and edge data, visibility state, hidden
elements, profile application, confidence sizing, and edge strength sizing.
- `src/repo_scoping/web_ui/views.py` provides the first UI shell: profile
controls, structured filters, manual overrides, focus depth, hover popups,
selection details, and a layered layout.
- `tests/test_web_api.py` verifies graph endpoints, ad hoc filters, profile
creation, duplicate profiles, latest-profile defaulting, and UI wiring.
## Reusable Behaviors
Fabric should carry these behaviors into the shared graph explorer contract:
- Cytoscape-compatible element arrays with `data` and optional `classes`.
- Stable element keys that survive refreshes, so layout state, profile rules,
and deep links do not churn.
- Metadata-rich nodes and edges rather than UI-only labels.
- Explicit `layer`, `kind`, `reviewState`, `freshnessState`, and
`displayState` fields.
- Visibility actions of `show`, `blur`, and `hide`, with later rules overriding
earlier rules and manual overrides winning last.
- Hidden element reporting, so over-filtered views are recoverable.
- Edge treatment for context-muted nodes.
- View profiles that can persist filter rules and manual overrides when a host
provides profile endpoints.
- Hover popups for compact inspection and selection panels for full detail.
- Layout modes for full graph, impact or filtered graph, selected path, and
neighborhood focus.
- Visual hints for confidence, strength, same-layer edges, stale or unresolved
state, and review state.
## Adapter-Owned Semantics
These repo-scoping concepts should remain in the repo-scoping adapter and not
be hard-coded into the engine:
- Layer names of `fact`, `evidence`, `feature`, `capability`, `ability`, and
`scope`.
- Candidate graph approval semantics.
- Dependency impact analysis over base and target analysis runs.
- Document fact normalization and README/SCOPE de-duplication.
- Scope curation recommendations.
Fabric has its own adapter semantics:
- Layer names of `repository`, `service`, `capability`, `interface`,
`dependency`, `binding`, and `library`.
- Registered-only repositories without accepted graph snapshots.
- State Hub repo ids, workplan links, and registry endpoints as deep links.
- Unresolved dependencies where provider bindings are missing or disputed.
- Blast-radius and provider-chain exploration across accepted Fabric
declarations.
## Extraction Recommendation
Start in `railiance-fabric` with a host-neutral manifest and payload contract,
plus a Fabric registry projection. The first UI shell can live locally while
the contract is still moving.
Extract into a separate repository only after two host adapters are proven:
1. Fabric registry map adapter.
2. Repo-scoping dependency graph adapter.
The likely extracted repository is `graph-explorer-engine`. It should own the
static interaction shell, schema definitions, layout/filter/profile client
logic, and adapter manifest contract. Host repos should keep graph projection,
profile persistence, authentication, and domain-specific deep links.

View File

@@ -0,0 +1,136 @@
# Operational Rescan Loops
`registry scan-manifest` is the operational entry point for repeated repo
reality scans. It can run safely as a dry-run, keep local baselines, reconcile
against registry-stored discovery snapshots, write a run report, and optionally
ingest or accept reviewed discovery output.
## Local Cache
By default, manifest scans use a local runtime directory beside the manifest:
```text
.fabric-discovery/
snapshots/
<repo-slug>-<profile>.discovery.json
reports/
<timestamp>-<profile>.rescan-report.json
rescan.lock
```
This directory is ignored by git. It is operator/runtime state, not source. Use
`--cache-dir` to place it elsewhere, `--output-dir` and `--previous-dir` for
explicit snapshot locations, or `--no-cache` when a run should only write
explicit outputs.
## Standard Dry-Run
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--repo-slug railiance-fabric \
--dry-run
```
The first run is a baseline. Later runs use the cached snapshot directory by
default and report `unchanged`, `changed`, or `review_required` per repo.
## Registry-Backed Rescan
Use the registry as the durable previous source:
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--repo-slug railiance-fabric \
--previous-from-registry \
--dry-run
```
When `--ingest` is enabled, unchanged snapshots are skipped by default to avoid
registry churn. Use `--ingest-unchanged` only when a full audit trail of every
run is required.
## Reports
Every cached scan writes a `FabricDiscoveryRescanReport`. The schema is
`schemas/rescan-run-report.schema.yaml`. Reports include:
- manifest, registry URL, profile, cache paths, and scanner version
- selected repos and LLM budget policy
- previous snapshot source/id/path per repo
- candidate counts, diff counts, review artifacts, connector runs, and errors
- discovery snapshot ids and accepted graph snapshot ids when registry writes
occur
Use `--report-output` for a specific path. Use `--json` to print the same report
shape to stdout.
## Acceptance Policy
`--accept` requires `--ingest`. The default `--accept-policy safe` only projects
candidates with `review_state: accepted` and blocks projection when the scan has
conflicts, tombstones, or low-confidence LLM artifacts. Use
`--accept-policy explicit` only for deliberate manual overrides, such as
selected keys or non-default review states.
## Automation Mode
For cron or automation, use:
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--previous-from-registry \
--dry-run \
--exit-code-mode operational
```
Operational exit codes:
- `0`: no changes and no review/failure
- `2`: baseline or changed repo reality detected
- `3`: review required
- `4`: one or more repo failures
- `5`: rescan lock already exists
The command creates a lock file under the cache directory by default. Use
`--lock-file` for an explicit lock path or `--no-lock` when an outer scheduler
already provides overlap protection.
## Rescan Status
The registry exposes latest discovery health in `/status` and per-repo
inventory. The CLI view is:
```bash
railiance-fabric registry rescan-status --review-only
```
Use `--stale-after-hours <n>` to show snapshots older than an operational
freshness window.
## First Rollout
The first controlled loop should stay small:
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--repo-slug repo-scoping \
--repo-slug llm-connect \
--repo-slug railiance-fabric \
--previous-from-registry \
--dry-run
```
If the report shows clean baselines or expected changes, rerun with `--ingest`
to store the baseline discovery snapshots. Broader all-local-repo rollout
should wait until the small loop is repeatable and the review queue is readable.
Initial implementation rollout on 2026-05-20:
- Registry-backed previous lookup correctly reported per-repo failures while
the local registry service on `127.0.0.1:8765` was offline.
- Local-cache dry-run completed for `repo-scoping`, `llm-connect`, and
`railiance-fabric`.
- Result: 3 scanned, 2 baseline, 1 changed, 7 conflicted, 1 review required,
0 errors.
- Follow-up: review `repo-scoping` conflicts before accepting or ingesting a
broad baseline.

126
docs/registry-api.md Normal file
View File

@@ -0,0 +1,126 @@
# Registry API
The Railiance Fabric registry is a small HTTP API over accepted Fabric graph
snapshots, discovery evidence, reset archives, and supporting inventory.
Legacy repo-local declarations can still produce snapshots, but they are
evidence for the graph rather than the long-term authority for external
deployment, ownership, tenant, or utility relations.
## Health And Status
```text
GET /health
GET /status
```
`/health` is intentionally tiny. `/status` includes database path, table counts,
and the latest accepted snapshot per repository.
## Repository Snapshots
```text
POST /repositories
GET /repositories
GET /repositories/{repo_slug}
GET /repositories/{repo_slug}/inventory
POST /repositories/{repo_slug}/snapshots
GET /repositories/{repo_slug}/snapshots
GET /repositories/{repo_slug}/snapshots/latest
GET /repositories/{repo_slug}/snapshots/diff
```
Snapshot ingestion accepts a `FabricGraphExport` under `graph` plus `commit`
and optional `generated_at`. The registry accepts both legacy
`railiance.fabric/v1alpha1` graph exports and the financial
`railiance.fabric/v1alpha2` / `financial-fabric-v1` export contract.
## Discovery Snapshots
```text
POST /repositories/{repo_slug}/discovery-snapshots
GET /repositories/{repo_slug}/discovery-snapshots
GET /repositories/{repo_slug}/discovery-snapshots/latest
GET /repositories/{repo_slug}/discovery-snapshots/diff
GET /repositories/{repo_slug}/discovery-snapshots/{snapshot_id}
POST /repositories/{repo_slug}/discovery-snapshots/{snapshot_id}/accept
```
Discovery ingestion accepts a `FabricDiscoverySnapshot`. Snapshots are stored by
repo, commit, and scan profile for dry-run review. Discovery diffs include
candidate additions, removals, changes, confidence changes, reconciliation
conflicts, and scoped retirements.
Acceptance projects only explicitly accepted discovery candidates into a normal
`FabricGraphExport` snapshot. Existing graph nodes are preserved, so repo-owned
declarations are not overwritten by discovery output. Projected nodes carry
discovery provenance, review state, confidence, and source anchors in their
attributes; graph explorer exports surface that metadata.
CLI helpers:
```bash
railiance-fabric registry ingest-discovery discovery.json \
--repo-slug railiance-fabric
railiance-fabric registry accept-discovery railiance-fabric 12 \
--accepted-key discovery:railiance-fabric:service-declaration:example
```
## Graph Queries
```text
GET /graph/nodes
GET /graph/nodes/{graph_id}
GET /graph/providers?capability_type=runtime-secrets
GET /graph/consumers?target=railiance-platform.openbao.kv-v2
GET /graph/unresolved
GET /graph/blast-radius?interface_id=openbao-kv-v2-mount
GET /graph/dependency-path?service_id=flex-auth.api
GET /search?q=jsonschema
```
## Artifacts And Libraries
```text
POST /artifacts
GET /artifacts
GET /artifacts/{artifact_id}
GET /libraries
GET /libraries/{library_id}
GET /repositories/{repo_slug}/libraries
POST /repositories/{repo_slug}/libraries/cyclonedx
```
CycloneDX ingestion replaces the repo's current library inventory with the
components and services in the submitted SBOM.
## Exports
```text
GET /exports/state-hub
GET /exports/backstage
GET /exports/xregistry
GET /exports/libraries/xregistry
GET /ui/graph-explorer
GET /exports/graph-explorer/manifest
GET /exports/graph-explorer
GET /exports/reset-archive
```
`GET /exports/state-hub` currently serves the accepted combined graph for the
State Hub read model. During the financial reset, keep using the legacy shape
for existing State Hub views until `STATE-WP-0051` materializes v1alpha2
fields. Use `railiance-fabric export --format financial` and
`examples/exports/financial-fabric-v1.json` as the vNext contract references.
## Guarded Reset
```text
POST /admin/reset-graph-data
```
The reset endpoint requires `confirm`,
`reason`, and `archive_sha256`. `confirm` must be
`RESET-RAILIANCE-FABRIC-GRAPH-DATA`. Operators should prefer the CLI wrapper
documented in `docs/registry-reset-operations.md`, because it exports the
archive and computes the checksum before calling the destructive endpoint.

View File

@@ -0,0 +1,90 @@
# Registry Onboarding
Multi-repo onboarding uses an operator-owned manifest to register ecosystem
repositories with a running Railiance Fabric registry and to push graph and
library inventory when the local checkout has the required inputs.
Repo-local declarations remain useful self-description evidence. They should
not be treated as the default authority for external fabric membership,
ownership, tenant boundaries, or cross-boundary utility relations. Those belong
to the accountability-root discovery model described in
`docs/FabricDiscoveryAndUpdate.md`.
## Run The Railiance Manifest
Start the registry:
```bash
railiance-fabric-registry --db .railiance-fabric/registry.sqlite3 --port 8765
```
Sync the known local Railiance ecosystem repos:
```bash
railiance-fabric registry sync-manifest registry/railiance-repos.yaml
```
Sync every active State Hub repo that is available on this local host:
```bash
railiance-fabric registry sync-manifest registry/local-repos.yaml
```
Use `--json` for automation and `--strict` when unavailable repos or invalid
inputs should fail the command.
## Manifest Shape
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: RegistryOnboardingManifest
registry_url: http://127.0.0.1:8765
repositories:
- slug: railiance-fabric
name: railiance-fabric
path: ..
default_branch: main
state_hub_repo_id: 2c0de614-e468-4eb6-8157-470649ac8c05
declaration_paths:
- ..
sbom: bom.json
```
`path` is the local checkout used for git metadata and default graph discovery.
`declaration_paths` is optional; when omitted, the repo path is scanned for a
`fabric/` directory. Relative paths are resolved from the manifest file.
`sbom` or `sboms` may point to CycloneDX JSON/YAML files. When present, the
command ingests them as queryable library inventory after repository
registration.
## Onboarding Behavior
Each repository entry is registered first. If the checkout is unavailable or has
no Fabric declarations yet, the command leaves the repo registered and reports a
warning. This lets the registry represent known repos before every repo has
published local evidence.
When declarations exist, the command validates them, builds a graph snapshot,
and posts it to:
```text
POST /repositories/{repo_slug}/snapshots
```
The first Railiance manifest keeps the seed ecosystem graph in
`railiance-fabric` and registers adjacent repos as known sources. As discovery
roots mature, adjacent repos can contribute local evidence without making each
repo responsible for the whole external fabric relation model.
`registry/local-repos.yaml` is a broader local-host manifest. It is generated
from active State Hub repo records whose local path exists on the current WSL
host. It registers cross-domain local repos into the Fabric registry while only
syncing graph snapshots for repos that already have Fabric declarations.
When two active repo records point at the same checkout path, accountability
root discovery treats them as aliases of one repository identity. The canonical
identity can be declared with `canonical_slug`; otherwise discovery prefers the
slug matching the checkout directory name and then the entry with a remote URL.
Use `split_identity: true` only when shared paths are intentional and should
remain separate review candidates.

View File

@@ -0,0 +1,61 @@
# Registry Reset Operations
RAIL-FAB-WP-0016 allows a destructive registry graph reset, but only after an
archive has been produced and the operator uses an explicit confirmation token.
## Export Archive Only
```bash
railiance-fabric registry export-reset-archive \
.railiance-fabric/reset-archive.json \
--registry-url http://127.0.0.1:8765
```
The archive contains:
- repository registrations,
- current combined graph export,
- stored graph snapshots,
- discovery snapshots and accepted graph snapshot links,
- artifacts,
- library inventory,
- prior reset events,
- rollback notes.
## Guarded Reset
```bash
railiance-fabric registry reset-graph-data \
--registry-url http://127.0.0.1:8765 \
--archive .railiance-fabric/reset-archive.json \
--confirm RESET-RAILIANCE-FABRIC-GRAPH-DATA \
--reason "canon-aligned graph reset before full reingest"
```
The command first writes the archive, computes its SHA-256, then calls the
registry reset endpoint. The registry records a reset event with the archive
path, archive checksum, reason, and dropped row counts.
The reset deletes graph snapshots, discovery snapshots, artifacts, and library
inventory. Repository registration rows are preserved so reingest can start
from the known repo list.
## Rollback Limits
The archive is a JSON evidence bundle, not an automatic SQLite restore. Use it
to inspect or manually reinsert prior registry data if needed. After reset, the
intended source of truth is a fresh scan and acceptance pass from accountability
roots using the financial Fabric model. The current bridge is the Railiance
baseline projection:
```bash
railiance-fabric validate .
railiance-fabric export --format financial
railiance-fabric registry sync --repo-slug railiance-fabric .
```
Use repo-local declarations as evidence during reingest, not as the authority
for all external ownership, tenant, or utility relations.
Do not run the reset until the replacement scanner/projection path has passed
validation and a sample reingest review.

View File

@@ -0,0 +1,484 @@
# Repo Reality Scanner
The repo reality scanner discovers Fabric entities from repository evidence and
turns them into candidate graph facts. It is a discovery layer, not a new
authoring surface. Repo-owned declarations remain high-trust self-description
evidence, but financial Fabric ownership, tenant boundaries, and cross-boundary
utility relations must be resolved from accountability roots or review
decisions before they become accepted graph data.
## Contract
A scanner run emits a `FabricDiscoverySnapshot`. The snapshot is scoped to one
repository, one commit, and one scan profile. It contains:
- replacement scopes, which define the evidence sets that may be replaced on a
rescan
- candidate nodes, edges, and attributes
- source anchors for every candidate
- extractor provenance for every candidate
- tombstones for candidates that vanished inside a replacement scope
- reconciliation policy metadata
The JSON schema lives at `schemas/discovery-snapshot.schema.yaml`.
## Deterministic Scanner CLI
The first implementation slice adds an offline deterministic scan command:
```bash
railiance-fabric scan . \
--repo-slug railiance-fabric \
--commit "$(git rev-parse HEAD)" \
--dry-run \
--output discovery-snapshot.json
```
Use `--json` to print the full `FabricDiscoverySnapshot` to stdout. Without
`--json`, the command prints a concise summary of node, edge, attribute, and
replacement-scope counts. The scanner does not call registries, catalogs, or
LLMs in this mode; `--output` is the only write side effect.
The deterministic extractor framework currently covers:
- repository metadata from local git/path evidence
- README, INTENT, and SCOPE document presence and headings
- repo-owned Fabric declarations under `fabric/`
- Python `pyproject.toml` package metadata and dependencies
- Node `package.json` package metadata and dependencies
- common lockfiles such as `package-lock.json`, `poetry.lock`, and `uv.lock`
- Dockerfiles and Docker Compose services
- OpenAPI and AsyncAPI contract files
- Score workload files
- Kubernetes-style deployment manifests
- common service config files such as `application.yaml` and
`appsettings.json`
Each extractor emits candidates through the same accumulator so stable-key
duplicates merge inside a scan before the snapshot is returned.
## LLM-Assisted Extraction
LLM extraction is optional and explicit:
```bash
railiance-fabric scan . \
--repo-slug railiance-fabric \
--llm \
--llm-provider openai \
--llm-model gpt-4.1-mini \
--dry-run \
--output discovery-with-llm.json
```
The implementation integrates through `llm-connect` with `create_adapter` and
`RunConfig`. Tests use a `MockLLMAdapter`-compatible boundary so CI stays
offline. If `llm-connect` is unavailable, the provider call fails, or the model
returns malformed JSON, the scanner records a `review_artifacts` entry and keeps
the discovery snapshot schema-valid.
The LLM never receives the whole repository. The scanner first builds a compact
evidence bundle from deterministic candidates, prioritizing durable local
evidence such as Fabric declarations, services, capabilities, interfaces,
libraries, deployments, and small README/INTENT/SCOPE signals. The prompt asks
for strict JSON:
```json
{"nodes": [], "edges": [], "attributes": []}
```
Projected LLM candidates are always `origin: llm` and
`review_state: needs_review`. Candidates below the configured confidence
threshold become `llm_low_confidence` review artifacts instead of graph
candidates. Unresolved edge endpoints or attribute targets also become review
artifacts. Accepted graph data still requires deterministic evidence,
repo-owned declarations, or a later human review/acceptance path.
## Reconciliation And Dry-Run Diffs
Scans can be reconciled against a previous discovery snapshot:
```bash
railiance-fabric scan . \
--repo-slug railiance-fabric \
--previous-snapshot previous-discovery.json \
--dry-run \
--output current-discovery.json
```
The reconciler writes `reconciliation.diff` with explicit stable-key sets:
- `added`
- `changed`
- `retired`
- `conflicted`
It deduplicates candidates by stable key, merges source anchors and provenance,
and applies source-aware precedence when duplicate candidates disagree. The
current precedence is:
1. `repo_declaration`
2. `deterministic`
3. `catalog`
4. `registry`
5. `llm`
6. `manual`
Possible duplicates found through matching aliases, normalized labels,
relationship endpoints, or attribute targets are not silently merged. They are
marked `status: conflicted`, moved to `review_state: needs_review`, and listed
under `reconciliation.conflicts`.
Missing previous candidates become tombstones only when their replacement scope
is present in the current scan and has `mode: replacement`. Missing candidates
from additive scopes, such as broad LLM evidence bundles, are left alone.
Existing tombstones are preserved so repeated scans can explain graph drift.
## Registry Review And Acceptance
Discovery snapshots can be stored in the Fabric registry for review:
```bash
railiance-fabric scan . \
--repo-slug railiance-fabric \
--previous-snapshot previous-discovery.json \
--output discovery.json
railiance-fabric registry ingest-discovery discovery.json \
--repo-slug railiance-fabric
```
The registry keeps discovery snapshots separately from accepted graph snapshots
by repo, commit, and scan profile. It exposes latest/list/diff API routes so a
dry run can be reviewed without changing the accepted graph.
Accepted discovery can be projected into a normal graph snapshot:
```bash
railiance-fabric registry accept-discovery railiance-fabric 12 \
--accepted-key discovery:railiance-fabric:service-declaration:example
```
By default, the accept path only projects candidates already marked
`review_state: accepted`. Passing `--accepted-key` explicitly includes selected
candidate stable keys. Existing accepted graph nodes win over discovery nodes
with the same graph id, so repo-owned declarations are preserved. Projected
nodes carry discovery stable key, origin, review state, confidence, provenance,
and source anchors in graph attributes; the graph explorer payload exposes
those fields for review. For financial Fabric fields, accepted discovery still
needs an accountability-root, baseline inheritance rule, or explicit review
decision.
## Connector Follow-Up
Connector follow-up is explicit and separated from repo-local extraction:
```bash
railiance-fabric scan . \
--repo-slug railiance-fabric \
--connector local-fabric-registry \
--connector-manifest registry/local-repos.yaml \
--dry-run
```
The connector interface has slots for:
- package registries
- container registries
- API catalogs
- service catalogs
- deployment inventories
- existing Fabric registry data
The first implementation is `local-fabric-registry`, an offline-safe connector
that reads a local onboarding manifest such as `registry/local-repos.yaml`. It
adds a `FabricRegistryEntry` candidate, a `cataloged_as` edge from the
repository node, and registry-sourced attributes such as domain, remote URL,
default branch, State Hub repo id, and declaration paths.
Connector evidence uses its own replacement scope with source kind
`fabric_registry`, so rescans can replace catalog facts without retiring
repo-local evidence. Connector run metadata is recorded under `connector_runs`
with status, source, message, and candidate counts.
Connector-derived facts should be treated this way:
- accepted: only when the connector reads explicit repo-owned evidence,
accountability-root evidence, or a catalog already governed as authoritative
for that field
- candidate: stable local registry facts such as onboarding manifest entries,
declared remote URLs, State Hub ids, and declaration paths
- review-only: missing catalogs, rate limits, connector failures, ambiguous
matches, or facts from catalogs with unclear ownership
Failures do not corrupt the scan. Missing catalogs become
`connector_unavailable` review artifacts, malformed catalogs become
`connector_failed` artifacts, and future remote connectors should use
`connector_rate_limited` when backoff is required.
## Multi-Repo Orchestration
Known local repos can be scanned from the same onboarding manifest used by
`registry sync-manifest`:
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--dry-run \
--output-dir .fabric-discovery
```
The command isolates each repo. A missing path, invalid previous snapshot, or
registry write failure is reported for that repo without aborting the rest of
the run. The summary includes repo counts for scanned, changed, retired,
conflicted, LLM skipped, LLM failed, ingested, accepted, and errors so it can be
copied into State Hub progress notes or future automation output.
Useful controls:
- `--repo-slug <slug>` can be repeated to scan an allowlist.
- `--profile <name>` tags the scan profile and output filename.
- `--previous-dir <dir>` reconciles each repo against
`<slug>-<profile>.discovery.json` from an earlier run.
- `--llm` enables LLM-assisted extraction; `--deterministic-only` forces the
offline rule path.
- `--llm-max-runs <n>` caps how many repos may attempt LLM extraction in one
orchestration run, while `--llm-max-tokens` remains the per-repo request cap.
- `--connector local-fabric-registry` attaches manifest-derived registry facts
to every repo scan.
- `--ingest` stores discovery snapshots in the registry; `--accept` then
projects accepted candidates into graph snapshots. `--dry-run` suppresses
registry writes even when those flags are present.
Example review cycle:
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--repo-slug railiance-fabric \
--previous-dir .fabric-discovery \
--output-dir .fabric-discovery \
--connector local-fabric-registry \
--dry-run
```
After review, rerun with `--ingest` to store the snapshots. Add `--accept` only
when candidates marked `review_state: accepted` should be projected into the
registry graph.
For repeated operational loops, including default cache paths, registry-backed
previous snapshots, run reports, exit codes, and rescan health views, see
`docs/operational-rescan-loops.md`.
## Scan Profiles And Review Workflow
The initial profile is `deterministic`, which means repo-local extraction plus
any explicitly enabled offline connectors. Additional profiles should be named
for the evidence policy they represent, for example `deterministic-llm-draft`
or `catalog-followup`. Keep profile names stable because per-repo previous
snapshots use `<slug>-<profile>.discovery.json`.
Recommended workflow:
1. Run `scan` or `registry scan-manifest` with `--dry-run`.
2. Reconcile with `--previous-snapshot` or `--previous-dir` when a prior
snapshot exists.
3. Review candidates with `review_state: needs_review`, `status: conflicted`,
tombstones, and review artifacts before accepting anything.
4. Store reviewed output with `registry ingest-discovery`.
5. Use `registry accept-discovery` or `registry scan-manifest --ingest --accept`
only for candidates whose review state is acceptable for projection.
## Failure Modes
Failures are captured close to the evidence source:
- Missing repo paths, invalid manifest entries, unreadable previous snapshots,
and registry request failures mark that repo as `status: error` in
`scan-manifest` without stopping other repos.
- Connector failures become review artifacts such as `connector_unavailable` or
`connector_failed`.
- LLM provider failures and malformed model output become `llm_execution_error`
or `llm_output_invalid` review artifacts.
- Low-confidence LLM candidates become `llm_low_confidence` artifacts instead
of graph candidates.
- Possible duplicates are marked as conflicts and left for review instead of
being silently merged.
## Rollout Dry Run
The first small local rollout ran on 2026-05-19:
```bash
railiance-fabric registry scan-manifest registry/local-repos.yaml \
--repo-slug repo-scoping \
--repo-slug llm-connect \
--repo-slug railiance-fabric \
--dry-run \
--connector local-fabric-registry
```
Result:
- `repo-scoping`: 18 nodes, 17 edges, 13 attributes
- `llm-connect`: 5 nodes, 4 edges, 13 attributes
- `railiance-fabric`: 55 nodes, 63 edges, 13 attributes
- summary: 3 scanned, 0 changed, 0 retired, 0 conflicted, 3 LLM skipped,
0 LLM failed, 0 accepted, 0 errors
Follow-up backlog from this first pass:
- Add a standard discovery snapshot directory, likely `.fabric-discovery/`, so
repeated dry-runs can reconcile by default.
- Add a previous-from-registry option so manifest scans can diff against the
latest stored discovery snapshot without exporting JSON first.
- Expand runtime/deployment extraction beyond local manifests to cover live
server and deployment inventory connectors.
- Add review UI affordances for conflicts, tombstones, and bulk acceptance once
enough repos have baseline snapshots.
- Define privacy and budget defaults before enabling non-mock LLM providers in
multi-repo scans.
## Identity
Identity is the main safety boundary. The scanner must not append guesses on
every run. It needs to produce stable keys that are repeatable for the same
observed entity.
Candidate node keys use this shape:
```text
discovery:{repo_slug}:{entity_kind}:{normalized_name}[:source_fingerprint]
```
Use the optional source fingerprint when a name is too generic or when multiple
entities of the same kind can share a display name. Examples include HTTP
routes, generated clients, deployment manifests, and catalog records.
Candidate edge keys use a relationship fingerprint over:
- source stable key
- edge type
- target stable key
- optional evidence scope
Candidate attribute keys use the entity stable key plus the normalized
attribute name and, where needed, a source fingerprint.
Stable-key parts are lowercased and normalized to ASCII-like identity segments.
The helper functions in `railiance_fabric.discovery` define the initial rules.
## Source Anchors
Every candidate must carry one or more source anchors. A source anchor identifies
why the scanner believes the fact exists. Anchors can point to files, package
manifests, lockfiles, API contracts, deployment manifests, service catalogs,
registries, LLM evidence bundles, or manual review notes.
Source anchors include a fingerprint. The fingerprint should cover stable
location fields such as path, URL, ref, line range, or JSON pointer. Snippets are
useful for review but should not be the only identity anchor because formatting
noise can churn snippets.
## Replacement Scopes
A replacement scope says which extractor owns which set of candidates. Rescans
may retire missing candidates only inside the same scope.
Examples:
- `scope:repo-scoping:python-package:package_manifest:<hash>`
- `scope:state-hub:fabric-declarations:declaration`
- `scope:llm-connect:readme-summary:file:<hash>`
- `scope:railiance-fabric:local-registry:fabric_registry`
Scopes have a mode:
- `replacement`: candidates missing from the next run in the same scope become
tombstones.
- `additive`: candidates are added or updated, but absence does not retire old
candidates.
LLM extractors should usually use replacement mode only for tightly bounded
evidence bundles. Broad repo summaries are safer as additive or review-only
until the extraction prompts are proven stable.
## Merge Precedence
When multiple sources describe the same entity, reconciliation uses this
precedence:
1. `repo_declaration`
2. `deterministic`
3. `catalog`
4. `registry`
5. `llm`
6. `manual`
Manual review can override local candidate state, but it should not silently
rewrite repo-owned declarations. If accepted discoveries should become durable
repo-local evidence, generate a repo-owned declaration patch for human review.
If they affect financial ownership, fabric containment, tenancy, or utility
value boundaries, generate a baseline or accountability-root review item
instead.
## Duplicate Handling
The reconciler should merge candidates with the same stable key automatically.
It should also look for possible duplicates using:
- alias overlap
- identical source anchors
- identical evidence fingerprints
- normalized label similarity within the same entity kind
- relationship fingerprints with the same endpoints and edge type
- declaration ids that match discovery aliases
Exact stable-key matches can be merged automatically. Alias-only or
similarity-only matches should become `needs_review` conflicts unless an
extractor has a source-specific rule that makes the match deterministic.
## Rescan And Tombstones
On a rescan, the scanner compares the previous accepted discovery snapshot with
the newly produced snapshot for the same repo/profile.
- Same stable key: update in place.
- Same source anchor but changed attributes: update with changed evidence.
- Missing from same replacement scope: create a tombstone.
- Missing from a different scope: leave untouched.
- Reappears after tombstone: reactivate if the stable key and scope match.
- Reappears with a new key but same alias/source anchor: flag as possible
duplicate resurrection.
Tombstones explain graph drift and prevent immediate re-creation loops. They
should be retained long enough to compare several scan cycles and can later be
compacted by repo, extractor, or entity kind.
## Mapping To Fabric Graphs
Discovery candidates can project into the existing graph model when accepted:
- candidate service nodes map to `ServiceDeclaration`-like graph nodes
- candidate capabilities and interfaces map to provider surface nodes
- candidate dependencies map to dependency nodes and `consumes` edges
- candidate deployment/runtime entities map to graph explorer infrastructure
nodes until declarations gain first-class runtime support
- candidate libraries map to library inventory records and graph explorer nodes
If a repo-owned declaration already exists for the same entity, discovery output
should attach as supporting evidence instead of creating another node.
## LLM Boundary
LLM extraction through `llm-connect` is optional and schema-gated. The scanner
should use deterministic preselection to build small evidence bundles, ask for
structured JSON, validate the JSON against the discovery schema, and record:
- extractor id and version
- prompt version
- provider and model
- usage metadata
- confidence and uncertainty
- rationale
Malformed, low-confidence, or conflicting LLM output becomes review material,
not accepted graph data.

340
docs/semantic-attractors.md Normal file
View File

@@ -0,0 +1,340 @@
# Semantic Attractors
## Intent
Semantic attractors are view entities that help an operator orient inside a
medium or large graph. An attractor represents a topic, concern, capability
area, operating mode, or other conceptual pole such as `security`,
`development`, `operations`, `identity`, `data`, or `delivery`.
The graph explorer can place attractors on the canvas and connect graph
entities to them with view-only relationship strength. The stronger an
entity's semantic closeness to an attractor, the more that attractor should
pull the entity in force-directed or spring-based layouts.
The first motivating use case is repository orientation. Given a set of
repositories, the operator defines attractors such as `security`,
`development`, and `operations`. Railiance Fabric reads each repository's
`SCOPE.md`, estimates semantic closeness to those attractors, and maps that
score to layout force. The resulting map becomes a navigational surface: repos
with similar purpose drift toward the same conceptual pole without replacing
the underlying dependency or responsibility graph.
## What Attractors Are
An attractor is not a fabric node in the source graph. It is a graph-view
artifact with these responsibilities:
- name a topic or concern that is useful for orientation;
- define how closeness to that topic is measured;
- expose a score for each eligible entity;
- translate that score into layout hints and optional visual edges;
- keep the scoring evidence inspectable so the map does not become mysterious.
Attractors should be saved as view/profile configuration, operator presets, or
host-provided explorer configuration. They should not mutate repo-owned Fabric
declarations, and they should not imply that a repository provides or consumes
a capability.
## Why This Helps
Dependency edges answer "what depends on what?" Ownership and deployment
metadata answer "who owns this?" and "where does this run?" Those questions are
necessary, but they can still leave a large repo collection hard to scan.
Attractors answer a softer question: "what is this near, conceptually?"
This gives operators a fast way to discover clusters such as:
- repos that are security-heavy but not obvious from their names;
- operations tooling that depends on development systems;
- application repos that are unexpectedly close to platform/runtime concerns;
- thin adapter repos that sit between two conceptual poles;
- orphaned or ambiguous repos that have weak attraction to every known topic.
## Core Model
An attractor definition should be serializable and stable:
```yaml
id: security
label: Security
description: Identity, authorization, secrets, MFA, audit, policy, and trust boundaries.
applies_to:
layers: [repository]
evidence:
sources:
- type: scope_markdown
path: SCOPE.md
scoring:
method: lexical_semantic_profile
anchors:
- security
- identity
- authorization
- secrets
- audit
- policy
- mfa
negative_anchors:
- unrelated
normalization:
mode: per_entity_softmax
layout:
min_score: 0.15
max_score: 1.0
strength_scale: 0.8
ideal_length:
min: 80
max: 420
presentation:
color: "#be123c"
edge_style: dashed
```
The exact schema can evolve, but the responsibilities should remain separate:
- `applies_to` chooses which graph elements can be scored.
- `evidence` declares which text or metadata is used.
- `scoring` defines the semantic metric.
- `normalization` turns raw scores into comparable view weights.
- `layout` maps weights to graph layout hints.
- `presentation` controls the optional visual attractor node and edges.
## Scoring From SCOPE.md
`SCOPE.md` is a useful first evidence source because it is intentionally short,
repo-owned, and written to explain when a repository is relevant. For repository
attraction, the scorer should use sections such as:
- `One-liner`
- `Core Idea`
- `In Scope`
- `Relevant When`
- `Provided Capabilities`
- `Related / Overlapping Repositories`
- `Terminology`
Sections such as `Out of Scope` and `Not Relevant When` should be used
carefully. They can reduce false positives, but they should not erase a topic
just because the repo mentions a boundary. For example, a repo can say it is
not an authorization engine while still being semantically near security
because it models secrets, policy, or trust boundaries.
The first implementation can use a transparent lexical profile:
1. Parse `SCOPE.md` into sections.
2. Tokenize section text and provided capability keywords.
3. Weight section matches, with `One-liner`, `Core Idea`, `In Scope`, and
capability keywords carrying more weight than incidental notes.
4. Score each attractor by matching configured anchors and related terms.
5. Normalize scores per entity so one verbose `SCOPE.md` does not dominate.
6. Store the score, confidence, and top evidence snippets in the view payload.
Later implementations can replace or augment lexical scoring with embeddings,
LLM-assisted classification, or operator-reviewed labels. The contract should
not depend on a particular scorer.
## Score Semantics
Attractor scores should be continuous values in `[0, 1]`.
Suggested interpretation:
| Score | Meaning |
|-------|---------|
| `0.00` | no useful evidence of semantic closeness |
| `0.10` to `0.30` | weak signal; useful only as a faint layout hint |
| `0.30` to `0.60` | moderate closeness; entity should visibly lean toward the attractor |
| `0.60` to `0.85` | strong closeness; entity likely belongs near the attractor cluster |
| `0.85` to `1.00` | primary semantic identity or explicit operator label |
Every score should carry a confidence separate from closeness. A repo with a
thin or missing `SCOPE.md` may have low confidence even if a few terms match.
Attractors should also support multi-attraction. A repository can be close to
both `development` and `operations`; the layout should then place it between
those poles instead of forcing a single category. This is the main difference
from zones: zones preserve a single-surface invariant, while attractors are
allowed to overlap because they are layout forces, not containers.
## Layout Mapping
Attraction scores become layout hints. They should not become domain edges.
A graph explorer can map scores to synthetic view edges:
```json
{
"data": {
"id": "attractor:security->repo:flex-auth",
"source": "attractor:security",
"target": "repo:flex-auth",
"edgeType": "semantic_attraction",
"displayOnly": true,
"score": 0.82,
"confidence": 0.74,
"strength": "strong",
"layoutAffinity": 0.82,
"layoutIdealLength": 110,
"layoutElasticity": 0.9,
"sourceReferences": [
{
"type": "scope_markdown",
"path": "SCOPE.md",
"section": "In Scope"
}
]
},
"classes": "semantic-attraction"
}
```
For force-directed layouts:
- stronger scores should increase spring strength or edge weight;
- stronger scores should shorten ideal length;
- weak scores may be hidden visually while still applying a small force;
- edges below a configured threshold should not affect layout;
- display-only attraction edges should be excluded from dependency, boundary,
blast-radius, and zone-connectivity diagnostics.
Attractor nodes can be pinned, arranged on a ring, placed by the operator, or
computed from the current profile. For first use, a stable radial placement is
usually enough: place three to eight attractors around the graph, then let
repositories find their balance.
## View Payload Shape
The graph explorer payload should be able to carry attractor metadata without
changing the canonical Fabric graph.
Recommended top-level view extension:
```json
{
"view": {
"attractors": {
"enabled": true,
"definitionSet": "repo-concerns-v1",
"definitions": [
{
"id": "security",
"label": "Security",
"description": "Identity, authorization, secrets, audit, and policy.",
"color": "#be123c"
}
],
"scores": [
{
"attractor_id": "security",
"element_id": "repo:flex-auth",
"score": 0.82,
"confidence": 0.74,
"method": "lexical_semantic_profile",
"evidence": [
{
"source": "SCOPE.md",
"section": "Core Idea",
"terms": ["authorization", "policy"]
}
]
}
]
}
}
}
```
The renderer may choose to materialize these into synthetic nodes and edges at
runtime. A host may also emit synthetic display-only elements directly if that
is easier for the current engine.
## Operator Workflow
A useful attractor workflow should feel like mapmaking:
1. Choose a preset such as `Security / Development / Operations`.
2. Review the generated scores and evidence for a few known repos.
3. Hide or pin attractors that are not useful for the current question.
4. Save the attractor definition set in the graph profile.
5. Use the resulting layout to discover ambiguous, central, or misplaced repos.
The UI should expose:
- a toggle for semantic attractors;
- a definition-set selector;
- score threshold controls;
- optional visual attraction edges;
- pinned/unpinned attractor placement;
- detail panels explaining why a repo is close to an attractor;
- diagnostics for missing evidence, low confidence, and overly broad
attractors.
## Relationship To Zones
Zones and attractors solve different orientation problems.
Zones are bounded drawing surfaces. A visible node belongs to zero or one zone
in a given view. They are useful for deployment environments, access zones,
ownership surfaces, and other container-like questions.
Attractors are semantic force points. A visible node can be pulled by multiple
attractors at once. They are useful for topical orientation, concern mapping,
and discovering conceptual neighborhoods.
The two concepts can combine cleanly:
- zones can show where entities run;
- attractors can pull repos inside or outside those zones based on semantic
concern;
- zone diagnostics should ignore semantic attraction edges unless explicitly
configured otherwise;
- attractor scores can be summarized inside zone details.
## Initial Presets
A first repository-orientation preset should keep the set small:
| Attractor | Topic Signal |
|-----------|--------------|
| `security` | identity, secrets, authorization, policy, audit, MFA, trust boundaries |
| `development` | source code, build, CI/CD, package publishing, scaffolding, developer workflows |
| `operations` | deployment, runtime, monitoring, backups, incidents, infrastructure lifecycle |
Useful follow-up presets:
- `data`, `identity`, `delivery`, `governance`
- `platform`, `application`, `tooling`
- `financial`, `runtime`, `coordination`
Attractors should start as operator-chosen presets rather than global truth.
The same repository can be viewed through different conceptual lenses.
## Implementation Path
The concept can be implemented incrementally:
1. Add an attractor definition format for graph explorer profiles.
2. Parse repo `SCOPE.md` files during registry sync or graph export.
3. Compute transparent lexical scores for repositories.
4. Include attractor scores and evidence in the graph explorer payload.
5. Add synthetic attractor nodes and display-only attraction edges in the UI.
6. Map attraction scores to layout hints for the force-directed layout.
7. Add detail-panel evidence and low-confidence diagnostics.
8. Support saved attractor presets and operator score overrides.
This keeps attractors as a view concern until the scoring model proves useful.
If a semantic relation becomes durable domain knowledge, it can later be
promoted into a proper Fabric declaration with separate evidence and review.
## Open Questions
- Should attractor definitions live in graph profiles, repo config, or a shared
registry preset file?
- Should scoring run during registry sync, export, or entirely in the browser?
- How much operator override should be allowed before scores become maintained
labels rather than computed evidence?
- What is the right default for missing or stale `SCOPE.md` evidence?
- Should the first implementation use only lexical scoring, or should it also
prepare a pluggable embedding scorer interface?

View File

@@ -1,26 +1,27 @@
# State Hub Integration Contract
Railiance Fabric is the authoring and validation layer for ecosystem graph
declarations. State Hub should ingest Fabric outputs as a read model for
coordination, search, dashboards, and planning. It should not become the
primary authoring surface for services, capabilities, interfaces, dependencies,
or bindings.
Railiance Fabric is the discovery, validation, and versioning layer for the
Railiance infrastructure-responsibility graph. State Hub should ingest Fabric
outputs as a read model for coordination, search, dashboards, and planning. It
should not become the primary authoring surface for Fabric topology,
ownership, fabric membership, or cross-boundary utility relations.
## Source-Of-Truth Boundary
| Layer | Owns | Does Not Own |
|-------|------|--------------|
| Participating repos | Declaration files under `fabric/` | Global graph interpretation |
| Railiance Fabric | Schemas, type catalogs, validation, graph construction, exports | State Hub tasks/progress/decisions |
| State Hub | Read-model storage, links to repos/workstreams/tasks/progress, dashboard/search views | Editing Fabric declarations |
| Deployment/accountability roots | Durable evidence of infrastructure, deployment, ownership, utility, and payment responsibility | State Hub task state |
| Participating repos | Self-description evidence such as code, manifests, API contracts, package metadata, and legacy `fabric/` declarations | All external deployment/fabric relations |
| Railiance Fabric | Schemas, discovery, validation, graph construction, accepted snapshots, exports | State Hub tasks/progress/decisions |
| State Hub | Read-model storage, links to repos/workstreams/tasks/progress, dashboard/search views | Editing Fabric topology or inventing ownership |
The flow is:
```text
repo-local fabric/*.yaml
accountability roots + durable deployment evidence + repo evidence
|
v
railiance-fabric validate/export
railiance-fabric scan/validate/export
|
v
State Hub graph read model
@@ -31,15 +32,25 @@ dashboard, search, planning, progress links
## Export Shape
The CLI emits `FabricGraphExport` JSON:
The CLI and registry emit `FabricGraphExport` JSON:
```bash
railiance-fabric export --format json
railiance-fabric export --format financial
```
Schema: `schemas/state-hub-export.schema.yaml`
Top-level shape:
The schema now accepts two export families:
- `railiance.fabric/v1alpha1`: legacy declaration-centered graph export.
- `railiance.fabric/v1alpha2` with `schema_version:
financial-fabric-v1`: financial Fabric graph export.
### Legacy v1alpha1 Shape
The legacy top-level shape remains supported for compatibility with
`STATE-WP-0050`:
```yaml
apiVersion: railiance.fabric/v1alpha1
@@ -58,6 +69,10 @@ Node fields:
| `repo` | Owning repo slug. |
| `domain` | Owning domain slug. |
| `lifecycle` | Declaration lifecycle. |
| `canon_category` | Canon-aligned entity category when known. |
| `canon_anchor` | Canon surface that owns the selected category. |
| `mapping_fit` | Mapping confidence bucket: `direct`, `partial`, `conflict`, `gap`, or `unknown`. |
| `evidence_state` | Evidence state for the node claim: `observed`, `declared`, `inferred`, `proposed`, or `gap`. |
Edge fields:
@@ -65,7 +80,87 @@ Edge fields:
|-------|---------|
| `from` | Source node id. |
| `to` | Target node id. |
| `type` | Relationship type, such as `provides`, `exposes`, `available_via`, `consumes`, `binds:exact`, or `uses_interface`. |
| `type` | Fabric relationship type, such as `provides`, `exposes`, `available_via`, `consumes`, `binds:exact`, or `uses_interface`. |
| `canonical_type` | Canon-aligned relationship family when known, such as `exposes`, `depends_on`, `deploys`, or `flows_to`. |
| `display_only` | `true` when the edge is a visualization/layout relationship rather than a canonical graph claim. |
| `evidence_state` | Evidence state for the claim: `observed`, `declared`, `inferred`, `proposed`, or `gap`. |
### Financial v1alpha2 Shape
The financial Fabric export adds first-class responsibility and value
semantics:
```yaml
apiVersion: railiance.fabric/v1alpha2
kind: FabricGraphExport
schema_version: financial-fabric-v1
netkingdom:
id: railiance.netkingdom
king_actor_id: actor.railiance.king
actors: []
fabrics: []
nodes: []
edges: []
unresolved: []
```
Additional top-level sections:
| Field | Meaning |
|-------|---------|
| `schema_version` | Financial Fabric export schema identity. |
| `netkingdom` | Root responsibility context and king actor. |
| `actors` | King, lord, tenant, operator, and steward actors. |
| `fabrics` | Fabric and subfabric boundaries. |
| `unresolved` | Ownership, containment, or import gaps to display for review. |
Additional node fields:
| Field | Meaning |
|-------|---------|
| `containment` | Netkingdom, fabric, optional subfabric, environment, and optional deployment scenario. |
| `ownership` | Owner actor, owner role, and ownership resolution state. |
| `accounting` | Optional cost/profit center and allocation metadata. |
| `evidence` | Evidence state, review state, confidence, and evidence references. |
Additional edge fields:
| Field | Meaning |
|-------|---------|
| `relationship_category` | `containment`, `ownership`, `technical`, `utility`, `accounting`, or `evidence`. |
| `provider` / `consumer` | Owner and boundary context for utility edges. |
| `boundary` | Whether the edge crosses fabric or subfabric boundaries. |
| `utility` | Utility type, contract, payment schema, metering basis, and business model. |
| `accounting` | Optional cost/profit attribution for the relationship. |
| `evidence` | Evidence state, review state, confidence, and evidence references. |
Example payload: `examples/exports/financial-fabric-v1.json`.
## Operator Refresh During Reset
For the current reset, operators should produce both export families:
```bash
railiance-fabric validate .
railiance-fabric export --format json
railiance-fabric export --format financial
```
The `json` export remains the compatibility payload for State Hub graph views
implemented by `STATE-WP-0050`. The `financial` export is the vNext contract
artifact for `STATE-WP-0051` and should be reviewed whenever the baseline,
discovery inputs, ownership model, or registry materialization changes.
After workplan file changes, refresh State Hub's file-backed index from the
State Hub repo:
```bash
make fix-consistency REPO=railiance-fabric
```
Graph import and workplan consistency are separate. The consistency command
does not author Fabric graph topology; it only keeps State Hub's workplan cache
aligned with repo files.
## Proposed State Hub Read Model
@@ -119,9 +214,20 @@ fabric_graph_edges
edge_type
```
The normalized node/edge tables are optional at first. State Hub can begin with
`fabric_graph_exports.graph_json` and materialize node/edge tables once query
needs harden.
The `STATE-WP-0050` implementation already stores a v1alpha1 read model. The
`STATE-WP-0051` follow-up should extend that storage with:
- import/export schema version;
- netkingdom id;
- fabric and subfabric ids;
- actor ids and roles;
- node containment;
- node owner actor, owner role, and ownership resolution;
- edge relationship category;
- utility provider/consumer ownership context;
- fabric/subfabric boundary crossing flags;
- node and edge accounting attribution;
- unresolved ownership or containment gaps.
## Linking To Existing State Hub Entities
@@ -133,7 +239,7 @@ State Hub should enrich graph nodes by matching:
- progress events -> `repo_id` and related workstream/task when available
These links are annotations on the read model. They should never overwrite the
repo-owned declaration files.
Fabric export or source evidence.
## Ingestion Rules
@@ -143,7 +249,22 @@ repo-owned declaration files.
export validates.
4. Preserve historical exports long enough to compare graph drift.
5. Surface validation errors as State Hub progress events or human-review tasks,
but do not auto-edit declaration files.
but do not auto-edit Fabric topology, ownership, or source evidence.
6. For `v1alpha2`, preserve unresolved ownership/containment gaps rather than
inventing State Hub-owned values.
7. For `v1alpha2`, expose cost/profit center fields as accounting views, not as
fabric membership changes.
## Current State Hub Limitations
As of `STATE-WP-0050`, State Hub imports the legacy `v1alpha1` export as a
read model. It does not yet materialize the `v1alpha2` financial Fabric fields.
Until `STATE-WP-0051` is implemented, a `v1alpha2` export is a contract and
registry capability in `railiance-fabric`, not a fully queryable State Hub read
model. Operators should keep importing the current `v1alpha1` export for
existing dashboard/query behavior and use `v1alpha2` payloads for contract
verification and follow-on implementation.
## Initial Dashboard Queries

View File

@@ -28,12 +28,15 @@ Machine-readable catalog files:
| `audit-event-sink` | planned | high | confidential | `event-stream`, `http-api` |
| `scope-generation` | active | medium | internal | `cli`, `http-api` |
| `coordination-read-model` | active | high | internal | `http-api`, `event-stream` |
| `ecosystem-registry` | active | high | internal | `http-api`, `web-ui` |
## Interface Types
| Type | Lifecycle | Category | Typical Auth |
|------|-----------|----------|--------------|
| `http-api` | active | api | `none`, `oidc`, `jwt`, `mtls`, `api_key` |
| `web-ui` | active | ui | `none`, `oidc`, `jwt`, `mtls`, `api_key` |
| `mcp-api` | active | api | `none`, `oidc`, `jwt`, `mtls`, `api_key` |
| `oidc-discovery` | active | identity | `none` |
| `kubernetes-secret` | active | kubernetes | `kubernetes_service_account` |
| `kubernetes-crd` | active | kubernetes | `kubernetes_service_account` |

View File

@@ -1,7 +1,7 @@
# Declaration Fixtures
These fixtures support the T02 schema baseline and give the future validator
real inputs to exercise.
These fixtures support the legacy `v1alpha1` declaration schema and give the
validator real inputs to exercise.
`valid/` contains a coherent mini-graph:
@@ -11,5 +11,10 @@ real inputs to exercise.
- flex-auth runtime-secrets dependency
- binding assertion from flex-auth to OpenBao
`invalid/` contains schema-level failures. The future validator should report
clear errors for these before it attempts graph-level checks.
`invalid/` contains schema-level failures. The validator should report clear
errors for these before it attempts graph-level checks.
For the financial Fabric contract, use
`examples/exports/financial-fabric-v1.json`. That fixture exercises
king/lord/tenant actors, fabric/subfabric containment, ownership, cost/profit
attribution, and a cross-boundary utility edge.

View File

@@ -0,0 +1,104 @@
apiVersion: railiance.fabric/v1alpha2
kind: AccountabilityRootManifest
metadata:
id: example.accountability-roots
name: Example Accountability Roots
description: Minimal example showing how a tenant subfabric can be added without changing the parent fabric criterion.
netkingdom:
id: example.netkingdom
name: Example Netkingdom
king_actor_id: actor.example.king
actors:
- id: actor.example.king
role: king
name: Example King
authority:
recovery_authority: true
secrets_authority: true
backup_authority: true
termination_authority: true
- id: actor.example.lord
role: lord
name: Example Lord
- id: actor.example.tenant
role: tenant
name: Example Tenant
fabrics:
- id: fabric.example.primary
kind: Fabric
name: Example Primary Fabric
netkingdom_id: example.netkingdom
lord_actor_id: actor.example.lord
parent_fabric_id: null
status: active
boundary:
boundary_type: fabric
criterion: financial_and_operational_accountability
payment_responsibility: actor.example.lord
operational_responsibility: actor.example.king
recovery_responsibility: actor.example.king
- id: subfabric.example.tenant
kind: Subfabric
name: Example Tenant Subfabric
netkingdom_id: example.netkingdom
tenant_actor_id: actor.example.tenant
parent_fabric_id: fabric.example.primary
status: planned
boundary:
boundary_type: subfabric
criterion: restricted_paid_tenant_utility
payment_responsibility: actor.example.tenant
operational_responsibility: actor.example.lord
recovery_responsibility: actor.example.king
discovery_roots:
- id: root.example.state-hub
type: state_hub_repo_inventory
status: active
fabric_id: fabric.example.primary
owner_actor_id: actor.example.king
source:
base_url: http://127.0.0.1:8000
api_paths:
- /managed-repos/
safe_discovery: metadata_only
evidence_scope:
- repo_inventory
- repository_identity
refresh:
cadence: on_change
triggers:
- state_hub_repo_inventory_change
- operator_request
- id: root.example.tenant-api-contracts
type: endpoint_contract
status: planned
fabric_id: fabric.example.primary
subfabric_id: subfabric.example.tenant
owner_actor_id: actor.example.tenant
source:
repo_slug: example-tenant
path: contracts/openapi
safe_discovery: local_files
evidence_scope:
- endpoint_contract
- tenant_boundary
refresh:
cadence: on_change
triggers:
- endpoint_contract_change
- operator_request
refresh:
cadence: manual
triggers:
- operator_request
- state_hub_repo_inventory_change
- endpoint_contract_change
- lord_or_tenant_change
templates:
future_subfabric:
parent_fabric_id: fabric.example.primary
tenant_actor_role: tenant
required_updates:
- Add tenant actor.
- Add Subfabric with tenant_actor_id.
- Add subfabric-scoped discovery roots.

View File

@@ -0,0 +1,192 @@
{
"apiVersion": "railiance.fabric/v1alpha2",
"kind": "FabricGraphExport",
"schema_version": "financial-fabric-v1",
"generated_at": "2026-05-24T00:00:00Z",
"source": {
"producer": "railiance-fabric",
"registry": "registry",
"commit": "example",
"generation_reason": "operator_refresh"
},
"compatibility": {
"legacy_v1alpha1_supported": true,
"breaking_reset": false
},
"netkingdom": {
"id": "railiance.netkingdom",
"name": "Railiance Netkingdom",
"king_actor_id": "actor.railiance.king"
},
"actors": [
{
"id": "actor.railiance.king",
"kind": "FabricActor",
"role": "king",
"name": "Railiance King"
},
{
"id": "actor.railiance.primary-lord",
"kind": "FabricActor",
"role": "lord",
"name": "Railiance Primary Lord"
},
{
"id": "actor.coulomb.tenant",
"kind": "FabricActor",
"role": "tenant",
"name": "Coulomb Tenant"
}
],
"fabrics": [
{
"id": "fabric.railiance.primary",
"kind": "Fabric",
"name": "Railiance Primary Fabric",
"netkingdom_id": "railiance.netkingdom",
"lord_actor_id": "actor.railiance.primary-lord",
"parent_fabric_id": null,
"status": "active",
"boundary": {
"boundary_type": "fabric",
"criterion": "financial_and_operational_accountability"
},
"evidence_refs": []
},
{
"id": "subfabric.railiance.tenant.coulomb",
"kind": "Subfabric",
"name": "Coulomb Tenant Subfabric",
"netkingdom_id": "railiance.netkingdom",
"parent_fabric_id": "fabric.railiance.primary",
"tenant_actor_id": "actor.coulomb.tenant",
"status": "planned",
"boundary": {
"boundary_type": "subfabric",
"criterion": "restricted_paid_tenant_utility"
},
"evidence_refs": []
}
],
"nodes": [
{
"id": "state-hub.http",
"kind": "UtilityInterface",
"name": "State Hub HTTP API",
"repo": "state-hub",
"domain": "custodian",
"lifecycle": "active",
"containment": {
"netkingdom_id": "railiance.netkingdom",
"fabric_id": "fabric.railiance.primary",
"subfabric_id": null,
"environment": "local",
"deployment_scenario_id": null
},
"ownership": {
"owner_actor_id": "actor.railiance.primary-lord",
"owner_role": "lord",
"resolution": "inherited",
"inherited_from": "fabric.railiance.primary",
"supporting_actor_ids": []
},
"accounting": {
"cost_center_id": "cc.platform.shared",
"allocation_model": "direct"
},
"evidence": {
"state": "declared",
"review_state": "accepted",
"confidence": 0.9,
"refs": []
},
"canon_category": "endpoint",
"canon_anchor": "model/network",
"mapping_fit": "partial",
"evidence_state": "declared",
"attributes": {
"description": "Example tenant-facing State Hub API utility."
}
},
{
"id": "coulomb.automation-client",
"kind": "Service",
"name": "Coulomb Automation Client",
"repo": "coulomb-automation",
"domain": "railiance",
"lifecycle": "planned",
"containment": {
"netkingdom_id": "railiance.netkingdom",
"fabric_id": "fabric.railiance.primary",
"subfabric_id": "subfabric.railiance.tenant.coulomb",
"environment": "local",
"deployment_scenario_id": null
},
"ownership": {
"owner_actor_id": "actor.coulomb.tenant",
"owner_role": "tenant",
"resolution": "explicit",
"supporting_actor_ids": []
},
"accounting": {
"cost_center_id": "cc.coulomb.automation",
"allocation_model": "direct"
},
"evidence": {
"state": "declared",
"review_state": "accepted",
"confidence": 0.8,
"refs": []
},
"attributes": {}
}
],
"edges": [
{
"id": "utility:state-hub-http:coulomb-client",
"from": "state-hub.http",
"to": "coulomb.automation-client",
"type": "provides_utility_to",
"relationship_category": "utility",
"canonical_type": "depends_on",
"canon_anchor": "model/landscape",
"mapping_fit": "partial",
"display_only": false,
"evidence_state": "declared",
"provider": {
"owner_actor_id": "actor.railiance.primary-lord",
"fabric_id": "fabric.railiance.primary",
"subfabric_id": null
},
"consumer": {
"owner_actor_id": "actor.coulomb.tenant",
"fabric_id": "fabric.railiance.primary",
"subfabric_id": "subfabric.railiance.tenant.coulomb"
},
"boundary": {
"crosses_fabric_boundary": false,
"crosses_subfabric_boundary": true
},
"utility": {
"utility_type": "coordination_api",
"contract_id": "state-hub.http",
"payment_schema_id": "payment.internal-tenant-access",
"metering_basis": "unknown",
"business_model": "tenant_utility"
},
"accounting": {
"provider_profit_center_id": "pc.tenant-utilities",
"consumer_cost_center_id": "cc.coulomb.automation",
"allocation_model": "usage_weighted"
},
"evidence": {
"state": "declared",
"review_state": "accepted",
"confidence": 0.8,
"refs": []
},
"attributes": {}
}
],
"unresolved": []
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,8 @@
# Seed Declarations
These declarations are the first repo-local seed graph for Railiance Fabric.
They are legacy `v1alpha1` evidence used for validation, registry snapshots,
and compatibility exports.
They model current and planned Railiance ecosystem providers:
@@ -17,4 +19,9 @@ They model current and planned Railiance ecosystem providers:
The files are intentionally small. They are seed data for graph loading,
validation, and State Hub export work, not a claim that every upstream repo has
already adopted Fabric declarations as source of truth.
already published Fabric evidence.
The current financial responsibility baseline lives in
`fabric/financial/railiance-netkingdom.yaml`. It defines the Railiance
netkingdom, king, current lord, one active fabric, inherited node ownership,
and the template for future tenant subfabrics.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-apps.s5-releases.artifact-evidence-to-forge
name: S5 artifact evidence binding
owner: railiance-apps
repo: railiance-apps
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: railiance-apps.s5-releases.needs-artifact-evidence
provider_capability_id: railiance-forge.source-forge.artifact-promotion-evidence
provider_interface_id: railiance-forge.source-forge.evidence-contract
status: compatible
rationale: S5 release readiness should cite forge-owned artifact publish, restore, and operating evidence.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-apps.s5-releases.container-registry-to-forge
name: S5 container registry binding
owner: railiance-apps
repo: railiance-apps
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: railiance-apps.s5-releases.needs-container-registry
provider_capability_id: railiance-forge.source-forge.container-registry
provider_interface_id: railiance-forge.source-forge.oci-registry
status: compatible
rationale: S5 releases consume already-published app images from the forge-owned OCI registry.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-enablement.delivery-templates.runner-substrate-to-forge
name: Enablement runner substrate binding
owner: railiance-enablement
repo: railiance-enablement
domain: railiance
spec:
lifecycle: planned
environments: [dev, staging, prod]
dependency_id: railiance-enablement.delivery-templates.needs-runner-substrate
provider_capability_id: railiance-forge.source-forge.workflow-runner-substrate
provider_interface_id: railiance-forge.source-forge.runner-label-contract
status: compatible
rationale: S4 reusable templates should consume forge-owned runner labels, trust posture, and runner evidence.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-forge.source-forge.kubernetes-runtime-to-cluster
name: Forge Kubernetes runtime binding
owner: railiance-forge
repo: railiance-forge
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: railiance-forge.source-forge.needs-kubernetes-runtime
provider_capability_id: railiance-cluster.kubernetes.runtime
provider_interface_id: railiance-cluster.kubernetes.api
status: compatible
rationale: The forge runtime is deployed on the Railiance Kubernetes runtime provided by railiance-cluster.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-forge.source-forge.object-storage-to-artifact-store
name: Forge object storage binding
owner: railiance-forge
repo: railiance-forge
domain: railiance
spec:
lifecycle: planned
environments: [dev, staging, prod]
dependency_id: railiance-forge.source-forge.needs-object-storage
provider_capability_id: artifact-store.object-storage
provider_interface_id: artifact-store.object-storage.bucket
status: compatible
rationale: Durable forge artifact/blob preservation should use the planned Railiance object-storage provider rather than ad hoc forge-local storage.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-forge.source-forge.postgresql-to-cnpg
name: Forge PostgreSQL binding
owner: railiance-forge
repo: railiance-forge
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: railiance-forge.source-forge.needs-postgresql
provider_capability_id: railiance-platform.cnpg.postgresql
provider_interface_id: railiance-platform.cnpg.database-connection
status: compatible
rationale: Current Gitea database state is backed by the Railiance platform CNPG PostgreSQL service.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: railiance-forge.source-forge.runtime-secrets-to-openbao
name: Forge runtime secrets binding
owner: railiance-forge
repo: railiance-forge
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: railiance-forge.source-forge.needs-runtime-secrets
provider_capability_id: railiance-platform.openbao.runtime-secrets
provider_interface_id: railiance-platform.openbao.kv-v2
status: compatible
rationale: Runtime secret custody for forge workloads belongs to the platform OpenBao path; SOPS/age remains bootstrap only.

View File

@@ -0,0 +1,21 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-cluster.kubernetes.runtime
name: Kubernetes runtime
owner: railiance-cluster
repo: railiance-cluster
domain: railiance
source_links:
- label: Cluster scope
path: /home/worsch/railiance-cluster/SCOPE.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Provides Kubernetes runtime primitives and API access consumed by Railiance platform, forge, and app workloads.
capability_type: kubernetes-runtime
service_id: railiance-cluster.kubernetes
interface_ids:
- railiance-cluster.kubernetes.api
criticality: critical
data_classification: restricted

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-enablement.delivery-templates.ci-cd-templates
name: CI/CD workflow templates
owner: railiance-enablement
repo: railiance-enablement
domain: railiance
source_links:
- label: Enablement scope
path: /home/worsch/railiance-enablement/SCOPE.md
- label: Enablement intent
path: /home/worsch/railiance-enablement/INTENT.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Reusable Railiance workflow templates, promotion conventions, and delivery gates that consume forge runner labels and artifact evidence.
capability_type: ci-cd-template-catalog
service_id: railiance-enablement.delivery-templates
interface_ids:
- railiance-enablement.delivery-templates.workflow-template-contract
criticality: medium
data_classification: internal

View File

@@ -0,0 +1,24 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-fabric.registry.ecosystem-registry
name: Railiance ecosystem registry
owner: railiance-fabric
repo: railiance-fabric
domain: railiance
source_links:
- label: Registry store
path: railiance_fabric/registry.py
- label: Registry API docs
path: docs/registry-api.md
spec:
lifecycle: active
environments: [dev]
description: Registers repositories, ingests Fabric graph snapshots and library inventory, and exposes registry projections for discovery, State Hub export, xRegistry, and the interactive Fabric map.
capability_type: ecosystem-registry
service_id: railiance-fabric.registry
interface_ids:
- railiance-fabric.registry.http-api
- railiance-fabric.registry.graph-explorer-ui
criticality: high
data_classification: internal

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-forge.source-forge.artifact-promotion-evidence
name: Artifact promotion evidence
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Observability and evidence contract
path: /home/worsch/railiance-forge/docs/observability-operating-evidence.md
- label: Backup and restore handoff
path: /home/worsch/railiance-forge/docs/backup-restore-secret-handoff.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Provides artifact identity, provenance, publish, restore, and release-readiness evidence that downstream releases can cite.
capability_type: artifact-promotion-evidence
service_id: railiance-forge.source-forge
interface_ids:
- railiance-forge.source-forge.evidence-contract
criticality: high
data_classification: internal

View File

@@ -0,0 +1,21 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-forge.source-forge.container-registry
name: Container registry
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Container registry docs
path: /home/worsch/railiance-forge/docs/gitea-container-registry.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Provides the Gitea OCI container registry endpoint used by Railiance workloads.
capability_type: container-registry
service_id: railiance-forge.source-forge
interface_ids:
- railiance-forge.source-forge.oci-registry
criticality: high
data_classification: confidential

View File

@@ -0,0 +1,21 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-forge.source-forge.python-package-registry
name: Python package registry
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Package registry docs
path: /home/worsch/railiance-forge/docs/gitea-package-registry.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Provides the Gitea Python package registry endpoint used by Railiance source and app builds.
capability_type: python-package-registry
service_id: railiance-forge.source-forge
interface_ids:
- railiance-forge.source-forge.python-package-index
criticality: high
data_classification: confidential

View File

@@ -0,0 +1,22 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-forge.source-forge.source-hosting
name: Source hosting
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Forge scope
path: /home/worsch/railiance-forge/SCOPE.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Hosts Railiance Git repositories, review surfaces, repository metadata, and source-forge access paths.
capability_type: source-hosting
service_id: railiance-forge.source-forge
interface_ids:
- railiance-forge.source-forge.web-ui
- railiance-forge.source-forge.git-ssh
criticality: high
data_classification: confidential

View File

@@ -0,0 +1,21 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-forge.source-forge.workflow-runner-substrate
name: Workflow runner substrate
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Runner ownership contract
path: /home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Provides forge-backed runner labels, placement, credential boundaries, and runner health evidence consumed by workflow templates and release checks.
capability_type: workflow-runner-substrate
service_id: railiance-forge.source-forge
interface_ids:
- railiance-forge.source-forge.runner-label-contract
criticality: high
data_classification: restricted

View File

@@ -0,0 +1,30 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-apps.s5-releases.needs-artifact-evidence
name: S5 artifact evidence dependency
owner: railiance-apps
repo: railiance-apps
domain: railiance
source_links:
- label: Apps scope
path: /home/worsch/railiance-apps/SCOPE.md
- label: Observability and evidence contract
path: /home/worsch/railiance-forge/docs/observability-operating-evidence.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: railiance-apps.s5-releases
requires:
capability_type: artifact-promotion-evidence
capability_id: railiance-forge.source-forge.artifact-promotion-evidence
interface:
type: evidence-contract
version_constraint: ">=v1"
auth:
method: none
criticality: high
data_classification: internal
fallback:
mode: manual
description: App operators can record manual evidence, but S5 should cite forge-owned artifact readiness when promoting releases.

View File

@@ -0,0 +1,30 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-apps.s5-releases.needs-container-registry
name: S5 container registry dependency
owner: railiance-apps
repo: railiance-apps
domain: railiance
source_links:
- label: Apps scope
path: /home/worsch/railiance-apps/SCOPE.md
- label: Container registry docs
path: /home/worsch/railiance-forge/docs/gitea-container-registry.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: railiance-apps.s5-releases
requires:
capability_type: container-registry
capability_id: railiance-forge.source-forge.container-registry
interface:
type: oci-registry
version_constraint: ">=registry-v2"
auth:
method: api_key
criticality: high
data_classification: confidential
fallback:
mode: none
description: S5 releases require a reachable container registry for private or internal app images.

View File

@@ -0,0 +1,30 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-enablement.delivery-templates.needs-runner-substrate
name: Enablement runner substrate dependency
owner: railiance-enablement
repo: railiance-enablement
domain: railiance
source_links:
- label: Enablement scope
path: /home/worsch/railiance-enablement/SCOPE.md
- label: Runner ownership contract
path: /home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
consumer_service_id: railiance-enablement.delivery-templates
requires:
capability_type: workflow-runner-substrate
capability_id: railiance-forge.source-forge.workflow-runner-substrate
interface:
type: workflow-runner-label-contract
version_constraint: ">=v1"
auth:
method: none
criticality: high
data_classification: internal
fallback:
mode: manual
description: Reusable templates can remain draft-only until forge publishes runner labels and trust evidence.

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-forge.source-forge.needs-kubernetes-runtime
name: Forge Kubernetes runtime dependency
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Forge scope
path: /home/worsch/railiance-forge/SCOPE.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: railiance-forge.source-forge
requires:
capability_type: kubernetes-runtime
capability_id: railiance-cluster.kubernetes.runtime
interface:
type: kubernetes-api
version_constraint: ">=v1"
auth:
method: kubernetes_service_account
criticality: critical
data_classification: restricted
fallback:
mode: none
description: The forge runtime cannot operate without the Railiance Kubernetes runtime.

View File

@@ -0,0 +1,30 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-forge.source-forge.needs-object-storage
name: Forge object storage dependency
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Backup and restore handoff
path: /home/worsch/railiance-forge/docs/backup-restore-secret-handoff.md
- label: Platform OpenBao object-storage handoff
path: /home/worsch/railiance-platform/docs/openbao.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
consumer_service_id: railiance-forge.source-forge
requires:
capability_type: object-storage
capability_id: artifact-store.object-storage
interface:
type: object-storage-bucket
version_constraint: ">=v1"
auth:
method: sts_token
criticality: high
data_classification: confidential
fallback:
mode: manual
description: Current Gitea package blobs remain on PVC until durable object-storage backup or artifact preservation is proven.

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-forge.source-forge.needs-postgresql
name: Forge PostgreSQL dependency
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Backup and restore handoff
path: /home/worsch/railiance-forge/docs/backup-restore-secret-handoff.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: railiance-forge.source-forge
requires:
capability_type: postgresql-database-service
capability_id: railiance-platform.cnpg.postgresql
interface:
type: database-connection
version_constraint: ">=v16"
auth:
method: database_role
criticality: critical
data_classification: confidential
fallback:
mode: none
description: The forge runtime requires the Gitea database state and cannot degrade safely without it.

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: railiance-forge.source-forge.needs-runtime-secrets
name: Forge runtime secrets dependency
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Backup and restore handoff
path: /home/worsch/railiance-forge/docs/backup-restore-secret-handoff.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: railiance-forge.source-forge
requires:
capability_type: runtime-secrets
capability_id: railiance-platform.openbao.runtime-secrets
interface:
type: openbao-kv-v2-mount
version_constraint: ">=v1 <v2"
auth:
method: kubernetes_service_account
criticality: critical
data_classification: secret
fallback:
mode: manual
description: SOPS/age bootstrap can carry encrypted deploy input, but runtime secret custody belongs to the platform path.

View File

@@ -0,0 +1,227 @@
apiVersion: railiance.fabric/v1alpha2
kind: AccountabilityRootManifest
metadata:
id: railiance.accountability-roots
name: Railiance Accountability Roots
description: Current discovery roots for rebuilding the Railiance Fabric graph from durable accountability evidence.
source_links:
- label: Financial Fabric architecture
path: docs/FabricDiscoveryAndUpdate.md
- label: Financial baseline
path: fabric/financial/railiance-netkingdom.yaml
netkingdom:
id: railiance.netkingdom
name: Railiance Netkingdom
king_actor_id: actor.railiance.king
baseline_ref:
label: Railiance financial baseline
path: fabric/financial/railiance-netkingdom.yaml
actors:
- id: actor.railiance.king
role: king
name: Railiance King
description: Responsible for the Railiance netkingdom and recovery authority.
authority:
recovery_authority: true
secrets_authority: true
backup_authority: true
termination_authority: true
- id: actor.railiance.primary-lord
role: lord
name: Railiance Primary Lord
description: Pays for the current Railiance infrastructure boundary.
fabrics:
- id: fabric.railiance.primary
kind: Fabric
name: Railiance Primary Fabric
netkingdom_id: railiance.netkingdom
lord_actor_id: actor.railiance.primary-lord
parent_fabric_id: null
status: active
boundary:
boundary_type: fabric
criterion: financial_and_operational_accountability
payment_responsibility: actor.railiance.primary-lord
operational_responsibility: actor.railiance.king
recovery_responsibility: actor.railiance.king
evidence_refs:
- label: Railiance financial baseline
path: fabric/financial/railiance-netkingdom.yaml
discovery_roots:
- id: root.state-hub.attached-repos
type: state_hub_repo_inventory
status: active
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.primary-lord
source:
base_url: http://127.0.0.1:8000
api_paths:
- /managed-repos/
safe_discovery: metadata_only
evidence_scope:
- repo_inventory
- repository_identity
refresh:
cadence: on_change
triggers:
- state_hub_repo_inventory_change
- operator_request
notes: Read State Hub as repo inventory evidence only; State Hub does not author Fabric ownership or topology.
- id: root.gitea.coulomb
type: gitea_organization
status: active
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.primary-lord
source:
url: ssh://git@92.205.130.254:30022/coulomb
organization: coulomb
safe_discovery: metadata_only
evidence_scope:
- repo_inventory
- repository_identity
refresh:
cadence: on_change
triggers:
- git_commit
- operator_request
- id: root.registry.local-repos
type: registry_manifest
status: active
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.primary-lord
source:
manifest_path: registry/local-repos.yaml
safe_discovery: local_files
evidence_scope:
- repo_inventory
- repository_identity
- local_checkout
refresh:
cadence: on_change
triggers:
- state_hub_repo_inventory_change
- operator_request
- id: root.workspace.home-worsch
type: host_path
status: active
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.primary-lord
source:
path: /home/worsch
patterns:
- "*/.git"
- "*/fabric"
safe_discovery: local_files
evidence_scope:
- local_checkout
- repository_identity
refresh:
cadence: manual
triggers:
- operator_request
- id: root.railiance-fabric.checkout
type: repository_checkout
status: active
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.primary-lord
source:
repo_slug: railiance-fabric
path: /home/worsch/railiance-fabric
remote_url: gitea-remote:coulomb/railiance-fabric.git
safe_discovery: local_files
evidence_scope:
- repository_identity
- local_checkout
- service_configuration
- endpoint_contract
- deployment_topology
refresh:
cadence: on_change
triggers:
- git_commit
- deployment_manifest_change
- endpoint_contract_change
- operator_request
- id: root.deployment.local-manifests
type: deployment_automation
status: active
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.primary-lord
source:
path: /home/worsch
patterns:
- "**/compose.yaml"
- "**/compose.yml"
- "**/docker-compose.yaml"
- "**/Dockerfile"
- "**/*.service"
- "**/k8s/*.yaml"
- "**/deploy*.sh"
safe_discovery: local_files
evidence_scope:
- deployment_topology
- infrastructure
- service_configuration
refresh:
cadence: on_change
triggers:
- deployment_manifest_change
- infrastructure_manifest_change
- operator_request
- id: root.openbao.secret-metadata
type: secret_root
status: planned
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.king
source:
repo_slug: railiance-fabric
path: fabric/services/railiance-platform-openbao.yaml
safe_discovery: metadata_only
evidence_scope:
- secret_metadata
- infrastructure
refresh:
cadence: manual
triggers:
- secret_root_change
- operator_request
notes: Discover only existence and metadata for secret roots; never extract secret values.
- id: root.backup-recovery.metadata
type: backup_recovery
status: planned
fabric_id: fabric.railiance.primary
owner_actor_id: actor.railiance.king
source:
path: docs/financial-fabric-operator-guide.md
safe_discovery: explicit_review
evidence_scope:
- backup_recovery
- manual_review
refresh:
cadence: manual
triggers:
- backup_recovery_change
- operator_request
refresh:
cadence: manual
triggers:
- operator_request
- state_hub_repo_inventory_change
- git_commit
- deployment_manifest_change
- infrastructure_manifest_change
- endpoint_contract_change
- secret_root_change
- backup_recovery_change
- lord_or_tenant_change
notes: Manual rebuild is the default until snapshot deltas and freshness triggers are implemented.
templates:
future_subfabric:
parent_fabric_id: fabric.railiance.primary
tenant_actor_role: tenant
required_updates:
- Add tenant actor with role tenant.
- Add Subfabric under fabric.railiance.primary with tenant_actor_id.
- Add tenant-specific discovery roots with subfabric_id.
- Add cross-boundary utility edges with provider and consumer owner context.
note: Tenant subfabrics do not change the current root fabric criterion.

View File

@@ -0,0 +1,404 @@
apiVersion: railiance.fabric/v1alpha1
kind: DeploymentZoneInventory
generated_at: "2026-05-24T00:00:00+02:00"
source:
repo: railiance-fabric
workplan: RAIL-FAB-WP-0020
method: source-search-and-declared-surfaces
scope:
note: >
This inventory captures deployment-zone overlay evidence. It does not
define fabric membership, port ownership, live health, or access policy.
deployment_environments:
- id: dev
scenario: bernd-laptop
intended_reachability: private operator workstation
- id: test
scenario: coulombcore
intended_reachability: shared collaborator and early-access test stage
- id: prod
scenario: railiance01
intended_reachability: production stage, currently alpha-accessible to developers
surfaces:
- id: dev.bernd-laptop.railiance-fabric.registry-api
name: Railiance Fabric registry HTTP API
repo: railiance-fabric
service_id: railiance-fabric.registry
deployment_environment: dev
deployment_scenario: bernd-laptop
access_zone: private-dev
exposure_class: local-only
routing_authority: local-loopback-binding
policy_authority: local-loopback-binding
route_evidence:
route: http://127.0.0.1:8765
host: 127.0.0.1
port: 8765
protocol: http
evidence:
- path: fabric/interfaces/railiance-fabric-registry-http-api.yaml
kind: fabric-interface-declaration
- id: dev.bernd-laptop.railiance-fabric.graph-explorer
name: Railiance Fabric graph explorer UI
repo: railiance-fabric
service_id: railiance-fabric.registry
deployment_environment: dev
deployment_scenario: bernd-laptop
access_zone: private-dev
exposure_class: local-only
routing_authority: local-loopback-binding
policy_authority: local-loopback-binding
route_evidence:
route: http://127.0.0.1:8765/ui/graph-explorer
host: 127.0.0.1
port: 8765
protocol: http
path: /ui/graph-explorer
evidence:
- path: fabric/interfaces/railiance-fabric-registry-graph-explorer-ui.yaml
kind: fabric-interface-declaration
- id: dev.bernd-laptop.state-hub.api
name: State Hub HTTP API
repo: the-custodian
service_id: the-custodian.state-hub
deployment_environment: dev
deployment_scenario: bernd-laptop
access_zone: private-dev
exposure_class: local-only
routing_authority: local-loopback-binding
policy_authority: local-loopback-binding
route_evidence:
route: http://127.0.0.1:8000
host: 127.0.0.1
port: 8000
protocol: http
evidence:
- path: fabric/interfaces/the-custodian-state-hub-http-api.yaml
kind: fabric-interface-declaration
- id: dev.bernd-laptop.state-hub.mcp
name: State Hub MCP API
repo: the-custodian
service_id: the-custodian.state-hub
deployment_environment: dev
deployment_scenario: bernd-laptop
access_zone: private-dev
exposure_class: local-only
routing_authority: local-loopback-binding
policy_authority: local-loopback-binding
route_evidence:
route: http://127.0.0.1:8001
host: 127.0.0.1
port: 8001
protocol: http
evidence:
- path: fabric/interfaces/the-custodian-state-hub-mcp-api.yaml
kind: fabric-interface-declaration
- id: dev.bernd-laptop.state-hub.dashboard
name: State Hub dashboard
repo: the-custodian
service_id: the-custodian.state-hub
deployment_environment: dev
deployment_scenario: bernd-laptop
access_zone: private-dev
exposure_class: local-only
routing_authority: local-loopback-binding
policy_authority: local-loopback-binding
route_evidence:
route: http://127.0.0.1:3000
host: 127.0.0.1
port: 3000
protocol: http
evidence:
- path: fabric/interfaces/the-custodian-state-hub-dashboard.yaml
kind: fabric-interface-declaration
- id: dev.bernd-laptop.net-kingdom.control-surface
name: NetKingdom control surface
repo: net-kingdom
service_id: net-kingdom.iam-profile
deployment_environment: dev
deployment_scenario: bernd-laptop
access_zone: private-dev
exposure_class: local-only
routing_authority: local-loopback-binding
policy_authority: local-loopback-binding
route_evidence:
route: http://127.0.0.1:8876
host: 127.0.0.1
port: 8876
protocol: http
evidence:
- path: fabric/interfaces/net-kingdom-control-surface-ui.yaml
kind: fabric-interface-declaration
- path: ../net-kingdom/sso-mfa/k8s/keycape/README.md
kind: source-search-hit
note: local OIDC callback lists localhost port 8876
- id: test.coulombcore.state-hub.http-tunnel
name: State Hub HTTP API tunnel to coulombcore
repo: railiance-infra
service_id: the-custodian.state-hub
deployment_environment: test
deployment_scenario: coulombcore
access_zone: collaborator-test
exposure_class: collaborator-test
routing_authority: ops-bridge
policy_authority: ops-bridge-ssh
route_evidence:
route: http://127.0.0.1:18000
host: 127.0.0.1
port: 18000
protocol: http
tunnel_target: coulombcore
evidence:
- path: ../railiance-infra/docs/deploy-stack.md
lines: "127"
kind: source-search-hit
- id: test.coulombcore.state-hub.mcp-tunnel
name: State Hub MCP tunnel to coulombcore
repo: railiance-infra
service_id: the-custodian.state-hub
deployment_environment: test
deployment_scenario: coulombcore
access_zone: collaborator-test
exposure_class: collaborator-test
routing_authority: ops-bridge
policy_authority: ops-bridge-ssh
route_evidence:
route: http://127.0.0.1:18001
host: 127.0.0.1
port: 18001
protocol: http
tunnel_target: coulombcore
evidence:
- path: ../railiance-infra/docs/deploy-stack.md
lines: "128"
kind: source-search-hit
- id: test.coulombcore.k3s-api-tunnel
name: k3s API tunnel to coulombcore
repo: railiance-infra
deployment_environment: test
deployment_scenario: coulombcore
access_zone: collaborator-test
exposure_class: collaborator-test
routing_authority: ops-bridge
policy_authority: ops-bridge-ssh
route_evidence:
route: https://127.0.0.1:16443
host: 127.0.0.1
port: 16443
protocol: https
tunnel_target: coulombcore
evidence:
- path: ../railiance-infra/docs/deploy-stack.md
lines: "129"
kind: source-search-hit
- path: ../railiance-cluster/SCOPE.md
lines: "127"
kind: source-search-hit
note: cluster scope states it runs on COULOMBCORE
- id: prod.railiance01.gitea
name: Gitea ingress
repo: railiance-apps
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-public
exposure_class: production-public
routing_authority: traefik
policy_authority: null
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://gitea.coulomb.social
hostname: gitea.coulomb.social
port: 443
protocol: https
review:
status: candidate
note: access zone and policy authority require operator review
evidence:
- path: ../railiance-apps/manifests/gitea-ingress.yaml
lines: "2,12,14,16,27"
kind: kubernetes-ingress
- path: ../railiance-apps/workplans/railiance-apps-WP-0002-vergabe-teilnahme-on-railiance01.md
lines: "612,613"
kind: source-search-hit
note: places Gitea before vergabe-teilnahme on railiance01
- id: prod.railiance01.vergabe-teilnahme
name: Vergabe Teilnahme ingress
repo: railiance-apps
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-public
exposure_class: production-public
routing_authority: traefik
policy_authority: null
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://vergabe-teilnahme.whywhynot.de
hostname: vergabe-teilnahme.whywhynot.de
port: 443
protocol: https
review:
status: candidate
note: production public classification is inferred from ingress host and workplan
evidence:
- path: ../railiance-apps/manifests/vergabe-teilnahme-ingress.yaml
lines: "2,11,13,15,26"
kind: kubernetes-ingress
- path: ../railiance-apps/workplans/railiance-apps-WP-0002-vergabe-teilnahme-on-railiance01.md
lines: "22,40,68,69,163,612,613"
kind: source-search-hit
- id: prod.railiance01.authelia
name: Authelia ingress
repo: net-kingdom
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-public
exposure_class: production-public
routing_authority: traefik
policy_authority: authelia
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://auth.coulomb.social
hostname: auth.coulomb.social
port: 443
protocol: https
review:
status: candidate
note: railiance01 attribution comes from NetKingdom deployment workplan
evidence:
- path: ../net-kingdom/sso-mfa/k8s/authelia/ingress.yaml
lines: "13,22,24,26,38"
kind: kubernetes-ingress
- path: ../net-kingdom/workplans/NK-WP-0003-keycape-privacyidea-cluster-deployment.md
lines: "29,47,88,101"
kind: source-search-hit
- id: prod.railiance01.keycape
name: Keycape ingress
repo: net-kingdom
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-public
exposure_class: production-public
routing_authority: traefik
policy_authority: traefik-middleware
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://kc.coulomb.social
hostname: kc.coulomb.social
port: 443
protocol: https
review:
status: candidate
note: middleware is present, but intended audience still needs operator review
evidence:
- path: ../net-kingdom/sso-mfa/k8s/keycape/ingress.yaml
lines: "13,22,23,27,29,41"
kind: kubernetes-ingress
- path: ../net-kingdom/sso-mfa/k8s/keycape/middleware.yaml
lines: "9,24"
kind: traefik-middleware
- id: prod.railiance01.privacyidea
name: privacyIDEA ingress
repo: net-kingdom
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-admin
exposure_class: production-admin
routing_authority: traefik
policy_authority: traefik-middleware
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://pink.coulomb.social
hostname: pink.coulomb.social
port: 443
protocol: https
review:
status: candidate
note: admin classification inferred from privacyIDEA role and middleware
evidence:
- path: ../net-kingdom/sso-mfa/k8s/privacyidea/ingress.yaml
lines: "25,34,36,38,40,52,60,69,71,75,77,89"
kind: kubernetes-ingress
- path: ../net-kingdom/sso-mfa/k8s/privacyidea/middleware.yaml
lines: "19,41"
kind: traefik-middleware
- id: prod.railiance01.privacyidea-account
name: privacyIDEA account self-service ingress
repo: net-kingdom
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-public
exposure_class: production-public
routing_authority: traefik
policy_authority: traefik-middleware
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://pink-account.coulomb.social
hostname: pink-account.coulomb.social
port: 443
protocol: https
review:
status: candidate
note: self-service classification inferred from host name and middleware
evidence:
- path: ../net-kingdom/sso-mfa/k8s/privacyidea/ingress.yaml
lines: "94,103,104,106,108,120"
kind: kubernetes-ingress
- id: prod.railiance01.lldap
name: LLDAP ingress
repo: net-kingdom
deployment_environment: prod
deployment_scenario: railiance01
access_zone: production-admin
exposure_class: production-admin
routing_authority: traefik
policy_authority: traefik-admin-allowlist
tls_authority: cert-manager:letsencrypt-prod
route_evidence:
route: https://lldap.coulomb.social
hostname: lldap.coulomb.social
port: 443
protocol: https
review:
status: candidate
note: admin allowlist middleware indicates intended restricted access
evidence:
- path: ../net-kingdom/sso-mfa/k8s/lldap/ingress.yaml
lines: "12,21,22,24,26,38"
kind: kubernetes-ingress
- path: ../net-kingdom/sso-mfa/k8s/lldap/middleware.yaml
lines: "11"
kind: traefik-middleware
ambiguities:
- id: railiance01-coulombcore-ip-conflict
severity: high
summary: Source documents disagree on which host owns 92.205.130.254.
evidence:
- path: ../railiance-apps/workplans/railiance-apps-WP-0002-vergabe-teilnahme-on-railiance01.md
lines: "22,163"
note: says railiance01 and Traefik LoadBalancer use 92.205.130.254
- path: ../railiance-infra/SCOPE.md
lines: "126"
note: says COULOMBCORE is 92.205.130.254 and Railiance01 is 92.205.62.239
next: reconcile host inventory before treating IP evidence as authoritative
- id: prod-access-zone-review
severity: medium
summary: Production access zones are candidate classifications.
evidence:
- path: ../railiance-apps/manifests
note: app ingress manifests show routing and TLS but not business audience
- path: ../net-kingdom/sso-mfa/k8s
note: middleware and network policy hint at access intent but do not replace operator review
next: confirm each production host as public, admin, or early-access
- id: test-reachability-is-tunneled
severity: medium
summary: Current coulombcore routes are ops-bridge tunnel evidence, not public ingress evidence.
evidence:
- path: ../railiance-infra/docs/deploy-stack.md
lines: "127,128,129"
note: state-hub and k3s API access are tunnel commands
next: add executable test-stage ingress/service discovery when coulombcore manifests exist
missing_policy_authority:
- surface_id: prod.railiance01.gitea
reason: route and TLS are discovered, but access policy authority is not evident in the ingress artifact
- surface_id: prod.railiance01.vergabe-teilnahme
reason: route and TLS are discovered, but access policy authority is not evident in the ingress artifact

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
{
"apiVersion": "railiance.fabric/v1alpha2",
"change_sets": {
"blockers": [],
"containment": [],
"ownership": [],
"review_state": []
},
"current": {
"generated_at": "2026-05-24T12:04:20Z",
"manifest_fingerprint": "dd279b655d68222a99671c1c875afdaa70ae2f907fd526e6673ddf756bc90dae",
"manifest_id": "railiance.accountability-roots"
},
"edge_delta": {
"added": [
"candidate-edge:d448183c64bba5c0"
],
"changed": [],
"removed": [],
"unchanged": []
},
"generated_at": "2026-05-24T12:04:59Z",
"kind": "AccountabilityUpdateDelta",
"node_delta": {
"added": [
"identity:actor:actor.railiance.king",
"identity:actor:actor.railiance.primary-lord",
"identity:backup-recovery-root:docs-financial-fabric-operator-guide.md",
"identity:catalog-root:gitea_organization",
"identity:catalog-root:registry_manifest",
"identity:deployable:home-worsch-.config-systemd-user-custodian-sync.service",
"identity:deployable:home-worsch-activity-core-dockerfile",
"identity:deployable:home-worsch-go-src-crypto-internal-boring-dockerfile",
"identity:deployable:home-worsch-go-src-crypto-internal-nistec-fiat-dockerfile",
"identity:deployable:home-worsch-key-cape-dockerfile",
"identity:deployable:home-worsch-repo-scoping-var-checkouts-key-cape-a01db9828dd4-dockerfile",
"identity:deployable:home-worsch-state-hub-dockerfile",
"identity:deployable:home-worsch-the-custodian-infra-build-machines-haskell-files-build-agent.service",
"identity:deployable:home-worsch-vergabe-teilnahme-dockerfile",
"identity:fabric:fabric.railiance.primary",
"identity:host-path:fabric",
"identity:host-path:git",
"identity:host-path:home-worsch-.nvm-.git",
"identity:host-path:home-worsch-activity-core-.git",
"identity:host-path:home-worsch-artifact-store-.git",
"identity:host-path:home-worsch-can-you-assist-.git",
"identity:host-path:home-worsch-domain-tree-.git",
"identity:host-path:home-worsch-flex-auth-.git",
"identity:host-path:home-worsch-guide-board-.git",
"identity:host-path:home-worsch-helix-forge-.git",
"identity:host-path:home-worsch-ihp-railiance-probe-.git",
"identity:host-path:home-worsch-info-tech-canon-.git",
"identity:host-path:home-worsch-infospace-bench-.git",
"identity:host-path:home-worsch-inter-hub-.git",
"identity:host-path:home-worsch-issue-core-.git",
"identity:host-path:home-worsch-key-cape-.git",
"identity:host-path:home-worsch-kontextual-engine-.git",
"identity:host-path:home-worsch-llm-connect-.git",
"identity:host-path:home-worsch-markitect-filter-.git",
"identity:host-path:home-worsch-markitect-main-.git",
"identity:host-path:home-worsch-markitect-quarkdown-.git",
"identity:host-path:home-worsch-markitect-tool-.git",
"identity:host-path:home-worsch-net-kingdom-.git",
"identity:host-path:home-worsch-open-cmis-tck-.git",
"identity:host-path:home-worsch-open-reuse-.git",
"identity:host-path:home-worsch-ops-bridge-.git",
"identity:host-path:home-worsch-ops-warden-.git",
"identity:host-path:home-worsch-phase-memory-.git",
"identity:host-path:home-worsch-railiance-apps-.git",
"identity:host-path:home-worsch-railiance-cluster-.git",
"identity:host-path:home-worsch-railiance-enablement-.git",
"identity:host-path:home-worsch-railiance-infra-.git",
"identity:host-path:home-worsch-railiance-platform-.git",
"identity:host-path:home-worsch-repo-scoping-.git",
"identity:host-path:home-worsch-repo-seed-.git",
"identity:host-path:home-worsch-shard-wiki-.git",
"identity:host-path:home-worsch-state-hub-.git",
"identity:host-path:home-worsch-tegwick-control-.git",
"identity:host-path:home-worsch-the-custodian-.git",
"identity:host-path:home-worsch-user-engine-.git",
"identity:host-path:home-worsch-vantage-point-.git",
"identity:host-path:home-worsch-vergabe-teilnahme-.git",
"identity:host-path:home-worsch-whynot-control-.git",
"identity:host-path:home-worsch-whynot-design-.git",
"identity:netkingdom:railiance.netkingdom",
"identity:repository:activity-core",
"identity:repository:artifact-store",
"identity:repository:domain-tree",
"identity:repository:flex-auth",
"identity:repository:guide-board",
"identity:repository:helix-forge",
"identity:repository:ihp-railiance-probe",
"identity:repository:infospace-bench",
"identity:repository:inter-hub",
"identity:repository:issue-core",
"identity:repository:key-cape",
"identity:repository:kontextual-engine",
"identity:repository:llm-connect",
"identity:repository:markitect-filter",
"identity:repository:markitect-project",
"identity:repository:markitect-quarkdown",
"identity:repository:markitect-tool",
"identity:repository:net-kingdom",
"identity:repository:open-cmis-tck",
"identity:repository:open-reuse",
"identity:repository:ops-bridge",
"identity:repository:ops-warden",
"identity:repository:phase-memory",
"identity:repository:railiance-apps",
"identity:repository:railiance-cluster",
"identity:repository:railiance-enablement",
"identity:repository:railiance-fabric",
"identity:repository:railiance-infra",
"identity:repository:railiance-platform",
"identity:repository:repo-scoping",
"identity:repository:state-hub",
"identity:repository:the-custodian",
"identity:repository:vergabe-teilnahme",
"identity:secret-root:fabric-services-railiance-platform-openbao.yaml"
],
"changed": [],
"removed": [],
"unchanged": []
},
"previous": {},
"summary": {
"edges_added": 1,
"edges_changed": 0,
"edges_removed": 0,
"edges_unchanged": 0,
"meaningful_change_count": 95,
"nodes_added": 94,
"nodes_changed": 0,
"nodes_removed": 0,
"nodes_unchanged": 0,
"promotion_needed": true
}
}

View File

@@ -0,0 +1,65 @@
apiVersion: railiance.fabric/v1alpha2
kind: FinancialFabricBaseline
metadata:
id: railiance.netkingdom-baseline
name: Railiance Netkingdom Baseline
spec:
netkingdom:
id: railiance.netkingdom
name: Railiance Netkingdom
king_actor_id: actor.railiance.king
actors:
- id: actor.railiance.king
kind: FabricActor
role: king
name: Railiance King
description: Responsible for the Railiance netkingdom and recovery authority.
authority:
recovery_authority: true
secrets_authority: true
backup_authority: true
termination_authority: true
- id: actor.railiance.primary-lord
kind: FabricActor
role: lord
name: Railiance Primary Lord
description: Pays for the current Railiance infrastructure boundary.
fabrics:
- id: fabric.railiance.primary
kind: Fabric
name: Railiance Primary Fabric
netkingdom_id: railiance.netkingdom
lord_actor_id: actor.railiance.primary-lord
parent_fabric_id: null
status: active
boundary:
boundary_type: fabric
criterion: financial_and_operational_accountability
payment_responsibility: actor.railiance.primary-lord
operational_responsibility: actor.railiance.king
recovery_responsibility: actor.railiance.king
evidence_refs: []
defaults:
containment:
netkingdom_id: railiance.netkingdom
fabric_id: fabric.railiance.primary
subfabric_id: null
environment: local
deployment_scenario_id: null
ownership:
owner_actor_id: actor.railiance.primary-lord
owner_role: lord
resolution: inherited
inherited_from: fabric.railiance.primary
supporting_actor_ids:
- actor.railiance.king
accounting:
cost_center_id: null
profit_center_id: null
allocation_model: null
future_subfabric_template:
kind: Subfabric
parent_fabric_id: fabric.railiance.primary
netkingdom_id: railiance.netkingdom
tenant_actor_role: tenant
note: Add a tenant actor and subfabric without changing the root fabric criterion.

View File

@@ -0,0 +1,35 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: net-kingdom.control-surface.ui
name: NetKingdom Control Surface
owner: net-kingdom
repo: net-kingdom
domain: railiance
spec:
lifecycle: active
environments: [dev]
description: Local NetKingdom control surface on the operator workstation.
interface_type: web-ui
version: v1
service_id: net-kingdom.iam-profile
capability_ids:
- net-kingdom.iam-profile.issuer
endpoint:
url: http://127.0.0.1:8876
notes: Local workstation endpoint after moving away from the Fabric registry port.
deployment_overlay:
deployment_environment: dev
deployment_scenario: bernd-laptop
routing_authority: net-kingdom-local-process
access_zone: private-dev
policy_authority: local-loopback-binding
exposure_class: local-only
route_evidence:
host: 127.0.0.1
port: 8876
protocol: tcp
route: http://127.0.0.1:8876
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-cluster.kubernetes.api
name: Kubernetes API
owner: railiance-cluster
repo: railiance-cluster
domain: railiance
source_links:
- label: Cluster scope
path: /home/worsch/railiance-cluster/SCOPE.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Kubernetes API surface and RBAC-controlled runtime contract consumed by Railiance workloads and operators.
interface_type: kubernetes-api
version: v1
service_id: railiance-cluster.kubernetes
capability_ids:
- railiance-cluster.kubernetes.runtime
auth:
method: kubernetes_service_account
data_classification: restricted

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-enablement.delivery-templates.workflow-template-contract
name: Workflow template contract
owner: railiance-enablement
repo: railiance-enablement
domain: railiance
source_links:
- label: Enablement scope
path: /home/worsch/railiance-enablement/SCOPE.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Template contract for reusable Railiance CI/CD and GitOps workflow patterns.
interface_type: workflow-template-contract
version: v1
service_id: railiance-enablement.delivery-templates
capability_ids:
- railiance-enablement.delivery-templates.ci-cd-templates
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,40 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-fabric.registry.graph-explorer-ui
name: Railiance Fabric Graph Explorer UI
owner: railiance-fabric
repo: railiance-fabric
domain: railiance
source_links:
- label: UI shell
path: railiance_fabric/graph_explorer_ui.py
- label: Graph explorer operations
path: docs/graph-explorer-operations.md
spec:
lifecycle: active
environments: [dev]
description: Browser UI for exploring the local Fabric registry graph, onboarding gaps, dependencies, interfaces, saved local views, and shareable graph state.
interface_type: web-ui
version: v1alpha1
service_id: railiance-fabric.registry
capability_ids:
- railiance-fabric.registry.ecosystem-registry
endpoint:
url: http://127.0.0.1:8765/ui/graph-explorer
notes: Local workstation UI when the registry service is running.
deployment_overlay:
deployment_environment: dev
deployment_scenario: bernd-laptop
routing_authority: railiance-fabric-registry
access_zone: private-dev
policy_authority: local-loopback-binding
exposure_class: local-only
route_evidence:
host: 127.0.0.1
port: 8765
protocol: tcp
route: http://127.0.0.1:8765/ui/graph-explorer
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,40 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-fabric.registry.http-api
name: Railiance Fabric Registry HTTP API
owner: railiance-fabric
repo: railiance-fabric
domain: railiance
source_links:
- label: HTTP routes
path: railiance_fabric/server.py
- label: API docs
path: docs/registry-api.md
spec:
lifecycle: active
environments: [dev]
description: Local HTTP API for repository registration, graph snapshot ingestion, graph queries, inventory views, State Hub export, Backstage projection, xRegistry projection, and graph explorer payloads.
interface_type: http-api
version: v1alpha1
service_id: railiance-fabric.registry
capability_ids:
- railiance-fabric.registry.ecosystem-registry
endpoint:
url: http://127.0.0.1:8765
notes: Local workstation endpoint when the registry service is running.
deployment_overlay:
deployment_environment: dev
deployment_scenario: bernd-laptop
routing_authority: local-process
access_zone: private-dev
policy_authority: local-loopback-binding
exposure_class: local-only
route_evidence:
host: 127.0.0.1
port: 8765
protocol: tcp
route: http://127.0.0.1:8765
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-forge.source-forge.evidence-contract
name: Forge evidence contract
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Observability and evidence contract
path: /home/worsch/railiance-forge/docs/observability-operating-evidence.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Release-readiness, artifact promotion, restore, storage, and operating evidence contract for forge consumers.
interface_type: evidence-contract
version: v1
service_id: railiance-forge.source-forge
capability_ids:
- railiance-forge.source-forge.artifact-promotion-evidence
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,25 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-forge.source-forge.git-ssh
name: Git SSH endpoint
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Observability and evidence contract
path: /home/worsch/railiance-forge/docs/observability-operating-evidence.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Git-over-SSH endpoint contract for repository clone, fetch, and push operations when exposed.
interface_type: git-ssh
version: gitea-current
service_id: railiance-forge.source-forge
capability_ids:
- railiance-forge.source-forge.source-hosting
endpoint:
notes: Record the published SSH host and port once the endpoint is verified.
auth:
method: static_secret
data_classification: confidential

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-forge.source-forge.oci-registry
name: Gitea OCI registry
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Container registry docs
path: /home/worsch/railiance-forge/docs/gitea-container-registry.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: OCI registry endpoint served by current Gitea for Railiance container images.
interface_type: oci-registry
version: registry-v2
service_id: railiance-forge.source-forge
capability_ids:
- railiance-forge.source-forge.container-registry
endpoint:
url: https://gitea.coulomb.social/v2/
auth:
method: api_key
scopes:
- package:read
- package:write
data_classification: confidential

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-forge.source-forge.python-package-index
name: Gitea Python package index
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Package registry docs
path: /home/worsch/railiance-forge/docs/gitea-package-registry.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Python package index endpoint served by current Gitea for internal Railiance packages.
interface_type: python-package-index
version: simple-api
service_id: railiance-forge.source-forge
capability_ids:
- railiance-forge.source-forge.python-package-registry
endpoint:
url: https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/
auth:
method: api_key
scopes:
- package:read
- package:write
data_classification: confidential

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-forge.source-forge.runner-label-contract
name: Runner label contract
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Runner ownership contract
path: /home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Semantic runner labels, placement, trust levels, and credential boundaries consumed by workflow templates and release checks.
interface_type: workflow-runner-label-contract
version: v1
service_id: railiance-forge.source-forge
capability_ids:
- railiance-forge.source-forge.workflow-runner-substrate
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,25 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-forge.source-forge.web-ui
name: Source forge web UI
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Observability and evidence contract
path: /home/worsch/railiance-forge/docs/observability-operating-evidence.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Current Gitea web UI and HTTP endpoint for source hosting and package workflows.
interface_type: web-ui
version: gitea-current
service_id: railiance-forge.source-forge
capability_ids:
- railiance-forge.source-forge.source-hosting
endpoint:
url: https://gitea.coulomb.social/
auth:
method: unknown
data_classification: confidential

View File

@@ -0,0 +1,35 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: the-custodian.state-hub.dashboard
name: State Hub Dashboard
owner: the-custodian
repo: the-custodian
domain: custodian
spec:
lifecycle: active
environments: [dev]
description: Local browser dashboard for State Hub coordination views.
interface_type: web-ui
version: v1
service_id: the-custodian.state-hub
capability_ids:
- the-custodian.state-hub.coordination
endpoint:
url: http://127.0.0.1:3000
notes: Local workstation dashboard endpoint when the State Hub frontend is running.
deployment_overlay:
deployment_environment: dev
deployment_scenario: bernd-laptop
routing_authority: vite-dev-server
access_zone: private-dev
policy_authority: local-loopback-binding
exposure_class: local-only
route_evidence:
host: 127.0.0.1
port: 3000
protocol: tcp
route: http://127.0.0.1:3000
auth:
method: none
data_classification: internal

View File

@@ -15,6 +15,21 @@ spec:
service_id: the-custodian.state-hub
capability_ids:
- the-custodian.state-hub.coordination
endpoint:
url: http://127.0.0.1:8000
notes: Local workstation State Hub REST API.
deployment_overlay:
deployment_environment: dev
deployment_scenario: bernd-laptop
routing_authority: state-hub-local-process
access_zone: private-dev
policy_authority: local-loopback-binding
exposure_class: local-only
route_evidence:
host: 127.0.0.1
port: 8000
protocol: tcp
route: http://127.0.0.1:8000
auth:
method: none
data_classification: internal

View File

@@ -0,0 +1,35 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: the-custodian.state-hub.mcp-api
name: State Hub MCP API
owner: the-custodian
repo: the-custodian
domain: custodian
spec:
lifecycle: active
environments: [dev]
description: Local MCP surface for State Hub coordination tools.
interface_type: mcp-api
version: v1
service_id: the-custodian.state-hub
capability_ids:
- the-custodian.state-hub.coordination
endpoint:
url: http://127.0.0.1:8001
notes: Local workstation MCP endpoint when State Hub is running.
deployment_overlay:
deployment_environment: dev
deployment_scenario: bernd-laptop
routing_authority: state-hub-local-process
access_zone: private-dev
policy_authority: local-loopback-binding
exposure_class: local-only
route_evidence:
host: 127.0.0.1
port: 8001
protocol: tcp
route: http://127.0.0.1:8001
auth:
method: none
data_classification: internal

View File

@@ -15,3 +15,4 @@ spec:
- net-kingdom.iam-profile.issuer
exposes_interfaces:
- net-kingdom.iam-profile.oidc-discovery
- net-kingdom.control-surface.ui

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-apps.s5-releases
name: Railiance S5 app releases
owner: railiance-apps
repo: railiance-apps
domain: railiance
source_links:
- label: Apps scope
path: /home/worsch/railiance-apps/SCOPE.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: S5 application release surface that consumes forge artifacts, app manifests, runbooks, dry-runs, and smoke evidence.
service_type: app-release-surface
provides_capabilities: []
exposes_interfaces: []

View File

@@ -0,0 +1,20 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-cluster.kubernetes
name: Railiance Kubernetes runtime
owner: railiance-cluster
repo: railiance-cluster
domain: railiance
source_links:
- label: Cluster scope
path: /home/worsch/railiance-cluster/SCOPE.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Kubernetes runtime layer that provides the API server, namespaces, workloads, Services, Ingresses, and controller substrate for Railiance services.
service_type: cluster-runtime
provides_capabilities:
- railiance-cluster.kubernetes.runtime
exposes_interfaces:
- railiance-cluster.kubernetes.api

View File

@@ -0,0 +1,22 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-enablement.delivery-templates
name: Railiance delivery templates
owner: railiance-enablement
repo: railiance-enablement
domain: railiance
source_links:
- label: Enablement scope
path: /home/worsch/railiance-enablement/SCOPE.md
- label: Enablement intent
path: /home/worsch/railiance-enablement/INTENT.md
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Reusable CI/CD and GitOps workflow template surface for Railiance workload delivery.
service_type: enablement-template-surface
provides_capabilities:
- railiance-enablement.delivery-templates.ci-cd-templates
exposes_interfaces:
- railiance-enablement.delivery-templates.workflow-template-contract

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-fabric.registry
name: Railiance Fabric Registry
owner: railiance-fabric
repo: railiance-fabric
domain: railiance
source_links:
- label: Registry server implementation
path: railiance_fabric/server.py
- label: Operations guide
path: docs/graph-explorer-operations.md
spec:
lifecycle: active
environments: [dev]
description: Local ecosystem registry and graph explorer service for registered Railiance repositories, Fabric graph snapshots, inventory, and map-oriented exports.
service_type: registry-service
provides_capabilities:
- railiance-fabric.registry.ecosystem-registry
exposes_interfaces:
- railiance-fabric.registry.http-api
- railiance-fabric.registry.graph-explorer-ui

View File

@@ -0,0 +1,31 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-forge.source-forge
name: Railiance source forge
owner: railiance-forge
repo: railiance-forge
domain: railiance
source_links:
- label: Forge scope
path: /home/worsch/railiance-forge/SCOPE.md
- label: Forge intent
path: /home/worsch/railiance-forge/INTENT.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Current Gitea source forge and future Forgejo migration surface for source hosting, registries, runner substrate, and release artifact evidence.
service_type: forge-runtime
provides_capabilities:
- railiance-forge.source-forge.source-hosting
- railiance-forge.source-forge.container-registry
- railiance-forge.source-forge.python-package-registry
- railiance-forge.source-forge.workflow-runner-substrate
- railiance-forge.source-forge.artifact-promotion-evidence
exposes_interfaces:
- railiance-forge.source-forge.web-ui
- railiance-forge.source-forge.git-ssh
- railiance-forge.source-forge.oci-registry
- railiance-forge.source-forge.python-package-index
- railiance-forge.source-forge.runner-label-contract
- railiance-forge.source-forge.evidence-contract

View File

@@ -15,3 +15,5 @@ spec:
- the-custodian.state-hub.coordination
exposes_interfaces:
- the-custodian.state-hub.http-api
- the-custodian.state-hub.mcp-api
- the-custodian.state-hub.dashboard

View File

@@ -11,6 +11,7 @@ requires-python = ">=3.12"
dependencies = [
"jsonschema>=4.18",
"PyYAML>=6.0",
"referencing>=0.30",
]
[project.scripts]

File diff suppressed because it is too large Load Diff

212
railiance_fabric/canon.py Normal file
View File

@@ -0,0 +1,212 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
CANONICAL_NODE_CATEGORIES = (
"source-repository",
"software-system",
"service",
"endpoint",
"deployment",
"runtime-resource",
"datastore",
"flow",
"policy",
"control",
"evidence",
"task",
"consumer-purpose",
"telemetry-signal",
)
CANONICAL_EDGE_TYPES = (
"built_from",
"implements",
"exposes",
"depends_on",
"deploys",
"flows_to",
"governed_by",
"evidenced_by",
"observed_by",
"part_of",
"reads_or_writes",
"creates_task",
)
DISPLAY_ONLY_EDGE_TYPES = (
"collapsed_into",
"declares",
"grouped_with",
"highlight_path",
"near",
"owns_deployment",
"same_color_group",
)
EVIDENCE_STATES = ("observed", "declared", "inferred", "proposed", "gap")
MAPPING_FITS = ("direct", "partial", "conflict", "gap", "unknown")
@dataclass(frozen=True)
class CanonNodeMapping:
category: str
canon_anchor: str
fit: str
notes: str = ""
@dataclass(frozen=True)
class CanonEdgeMapping:
canonical_type: str
canon_anchor: str
fit: str
display_only: bool = False
notes: str = ""
UNKNOWN_NODE_MAPPING = CanonNodeMapping(
category="unknown",
canon_anchor="",
fit="gap",
notes="No canon mapping has been selected for this Fabric node kind yet.",
)
UNKNOWN_EDGE_MAPPING = CanonEdgeMapping(
canonical_type="",
canon_anchor="",
fit="gap",
notes="No canon mapping has been selected for this Fabric edge type yet.",
)
NODE_KIND_CANON_MAP: dict[str, CanonNodeMapping] = {
"ApplicationEndpoint": CanonNodeMapping("endpoint", "model/network", "direct"),
"BindingAssertion": CanonNodeMapping("evidence", "model/observability", "partial"),
"CapabilityDeclaration": CanonNodeMapping("software-system", "model/landscape", "partial"),
"ContainerBuild": CanonNodeMapping("deployment", "model/devsecops", "partial"),
"DependencyDeclaration": CanonNodeMapping("service", "model/landscape", "gap"),
"DeploymentService": CanonNodeMapping("deployment", "model/devsecops", "direct"),
"DomainName": CanonNodeMapping("endpoint", "model/network", "partial"),
"ExternalLibrary": CanonNodeMapping("software-system", "model/landscape", "partial"),
"FabricRegistryEntry": CanonNodeMapping("source-repository", "model/devsecops", "partial"),
"Fabric": CanonNodeMapping("control", "model/governance", "gap"),
"FabricActor": CanonNodeMapping("control", "model/governance", "gap"),
"InterfaceDeclaration": CanonNodeMapping("endpoint", "model/network", "partial"),
"Library": CanonNodeMapping("software-system", "model/landscape", "partial"),
"Lockfile": CanonNodeMapping("evidence", "model/observability", "partial"),
"Netkingdom": CanonNodeMapping("software-system", "model/landscape", "gap"),
"NetworkPort": CanonNodeMapping("endpoint", "model/network", "direct"),
"ProfitCenter": CanonNodeMapping("control", "model/governance", "gap"),
"Repository": CanonNodeMapping("source-repository", "model/devsecops", "direct"),
"RuntimeService": CanonNodeMapping("runtime-resource", "model/landscape", "direct"),
"ScoreWorkload": CanonNodeMapping("deployment", "model/devsecops", "direct"),
"Server": CanonNodeMapping("runtime-resource", "model/landscape", "partial"),
"ServiceConfig": CanonNodeMapping("evidence", "model/observability", "partial"),
"ServiceDeclaration": CanonNodeMapping("service", "model/landscape", "direct"),
"Subfabric": CanonNodeMapping("control", "model/governance", "gap"),
"UtilityInterface": CanonNodeMapping("endpoint", "model/network", "partial"),
"CostCenter": CanonNodeMapping("control", "model/governance", "gap"),
}
EDGE_TYPE_CANON_MAP: dict[str, CanonEdgeMapping] = {
"available_via": CanonEdgeMapping("exposes", "model/network", "partial"),
"attributed_to_cost_center": CanonEdgeMapping("governed_by", "model/governance", "gap"),
"attributed_to_profit_center": CanonEdgeMapping("governed_by", "model/governance", "gap"),
"binds": CanonEdgeMapping("depends_on", "model/landscape", "partial"),
"builds_container": CanonEdgeMapping("built_from", "model/devsecops", "partial"),
"cataloged_as": CanonEdgeMapping("evidenced_by", "model/observability", "partial"),
"consumes": CanonEdgeMapping("depends_on", "model/landscape", "partial"),
"contains": CanonEdgeMapping("part_of", "model/landscape", "partial"),
"declares": CanonEdgeMapping("part_of", "model/devsecops", "partial", display_only=True),
"declares_package": CanonEdgeMapping("built_from", "model/devsecops", "partial"),
"defines_deployment": CanonEdgeMapping("built_from", "model/devsecops", "partial"),
"defines_runtime_object": CanonEdgeMapping("deploys", "model/devsecops", "partial"),
"defines_workload": CanonEdgeMapping("deploys", "model/devsecops", "partial"),
"deployed_as": CanonEdgeMapping("deploys", "model/devsecops", "partial"),
"depends_on_library": CanonEdgeMapping("depends_on", "model/landscape", "partial"),
"documents_interface": CanonEdgeMapping("evidenced_by", "model/observability", "partial"),
"exposes": CanonEdgeMapping("exposes", "model/network", "direct"),
"exposes_port": CanonEdgeMapping("exposes", "model/network", "direct"),
"listens_on": CanonEdgeMapping("exposes", "model/network", "direct"),
"names_endpoint": CanonEdgeMapping("exposes", "model/network", "partial"),
"opens_port": CanonEdgeMapping("exposes", "model/network", "partial"),
"operated_by": CanonEdgeMapping("governed_by", "model/governance", "partial"),
"owned_by": CanonEdgeMapping("governed_by", "model/governance", "partial"),
"owns_deployment": CanonEdgeMapping("part_of", "model/devsecops", "partial", display_only=True),
"provides": CanonEdgeMapping("implements", "model/landscape", "partial"),
"provides_utility_to": CanonEdgeMapping("depends_on", "model/landscape", "partial"),
"resolves_to": CanonEdgeMapping("flows_to", "model/network", "partial"),
"routes_to_port": CanonEdgeMapping("flows_to", "model/network", "partial"),
"routes_to_service": CanonEdgeMapping("flows_to", "model/network", "partial"),
"runs_on": CanonEdgeMapping("deploys", "model/devsecops", "partial"),
"suggests_capability": CanonEdgeMapping("creates_task", "model/task", "partial"),
"uses_config": CanonEdgeMapping("evidenced_by", "model/observability", "partial"),
"uses_interface": CanonEdgeMapping("depends_on", "model/landscape", "partial"),
"uses_lockfile": CanonEdgeMapping("evidenced_by", "model/observability", "partial"),
}
def node_canon_mapping(kind: str) -> CanonNodeMapping:
if kind in NODE_KIND_CANON_MAP:
return NODE_KIND_CANON_MAP[kind]
if kind.startswith("Kubernetes"):
return CanonNodeMapping("runtime-resource", "model/landscape", "direct")
return UNKNOWN_NODE_MAPPING
def edge_canon_mapping(edge_type: str) -> CanonEdgeMapping:
normalized = str(edge_type or "").strip()
if normalized.startswith("binds:"):
return EDGE_TYPE_CANON_MAP["binds"]
if normalized in EDGE_TYPE_CANON_MAP:
return EDGE_TYPE_CANON_MAP[normalized]
if normalized in CANONICAL_EDGE_TYPES:
return CanonEdgeMapping(normalized, _anchor_for_canonical_edge(normalized), "direct")
if normalized in DISPLAY_ONLY_EDGE_TYPES:
return CanonEdgeMapping("", "", "gap", display_only=True)
return UNKNOWN_EDGE_MAPPING
def evidence_state_for(
*,
origin: str = "",
source_kind: str = "",
review_state: str = "",
confidence: float | None = None,
) -> str:
if review_state == "rejected":
return "gap"
if origin == "llm":
return "proposed"
if confidence is not None and confidence < 0.5:
return "inferred"
if source_kind in {"package_registry", "container_registry", "service_catalog", "fabric_registry"}:
return "observed"
if source_kind in {"llm"}:
return "proposed"
if not source_kind and origin == "deterministic":
return "inferred"
return "declared"
def source_kind_from_anchor(source_anchor: dict[str, Any]) -> str:
return str(source_anchor.get("source_kind") or "")
def _anchor_for_canonical_edge(edge_type: str) -> str:
return {
"built_from": "model/devsecops",
"implements": "model/security",
"exposes": "model/network",
"depends_on": "model/landscape",
"deploys": "model/devsecops",
"flows_to": "model/network",
"governed_by": "model/governance",
"evidenced_by": "model/observability",
"observed_by": "model/observability",
"part_of": "model/landscape",
"reads_or_writes": "model/data",
"creates_task": "model/task",
}.get(edge_type, "")

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More