Compare commits

...

148 Commits

Author SHA1 Message Date
cbfb3d0f74 Draft capability entry (reuse-surface REUSE-WP-0017-T04, cohort 3)
Honest first-pass maturity vector grounded in README/docs/tests present
in this repo; no invented evidence. Flagged for human review before
publish. See reuse-surface history/2026-07-06-coverage-classification.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 19:50:53 +02:00
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
d1c003411f Add registry inventory and drift views 2026-05-17 20:49:28 +02:00
3bf22e18ba Add registry feed and library inventory 2026-05-17 20:41:31 +02:00
faff5fb728 Add registry artifacts and projections 2026-05-17 20:31:12 +02:00
2523eecce2 Start ecosystem registry service 2026-05-17 20:06:44 +02:00
19f9fddc35 Establish Railiance Fabric graph model 2026-05-17 19:47:37 +02:00
239 changed files with 47683 additions and 3 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 -->

18
.custodian-brief.md Normal file
View File

@@ -0,0 +1,18 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — railiance-fabric
**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)*
## Active Workstreams
*(none — repo may need first-session setup)*
---
## MCP Orientation (when available)
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

225
AGENTS.md Normal file
View File

@@ -0,0 +1,225 @@
# railiance-fabric — Agent Instructions
## Repo Identity
**Purpose:** railiance-fabric - (fill in purpose)
**Domain:** financials
**Repo slug:** railiance-fabric
**Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38`
**Workplan prefix:** `RAILIANCE-WP-`
---
## State Hub Integration
The Custodian State Hub tracks work across all domains. Interact via HTTP REST —
there is no MCP server for Codex agents.
| Context | URL |
|---------|-----|
| Local workstation | `http://127.0.0.1:8000` |
| Remote via tunnel | `http://127.0.0.1:18000` |
| Optional local edge relay | http://127.0.0.1:18080 |
When an operator has enabled the edge relay, set API_BASE to the relay URL.
Queueable writes return an explicit queued receipt if the central hub is
unreachable. Treat that as pending local evidence, then ask the operator to run
statehub outbox status/replay after connectivity returns.
### Orient at session start
```bash
# Offline brief — works without hub connection
cat .custodian-brief.md
# Active workplans for this domain
curl -s "http://127.0.0.1:8000/workplans/?topic_id=ca369340-a64e-442e-98f1-a4fa7dc74a38&status=active" \
| python3 -m json.tool
# Check inbox
curl -s "http://127.0.0.1:8000/messages/?to_agent=railiance-fabric&unread_only=true" \
| python3 -m json.tool
```
Mark a message read:
```bash
curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
-H "Content-Type: application/json" -d '{}'
```
### Log progress (required at session close)
```bash
curl -s -X POST http://127.0.0.1:8000/progress/ \
-H "Content-Type: application/json" \
-d '{
"summary": "what was done",
"event_type": "note",
"author": "codex",
"workplan_id": "<uuid>",
"task_id": "<uuid>"
}'
```
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": "progress"}'
# values: wait | todo | progress | done | cancel
```
### Flag a task for human review
```bash
curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
-H "Content-Type: application/json" \
-d '{"needs_human": true, "intervention_note": "reason"}'
```
---
## Session Protocol
**Start:**
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: ready`, `active`, or `blocked` files and open tasks
4. Check human-needed tasks: `GET /tasks/?needs_human=true`
**During work:**
- Update task statuses in workplan files as tasks progress
- Record significant decisions via `POST /decisions/`
**Close:**
1. Update workplan file task statuses to reflect progress
2. Log: `POST /progress/` with a summary of what changed
3. After workplan file changes, run:
```bash
statehub fix-consistency
```
Coding agents should run this directly; ask the operator only if the CLI or
State Hub API is unavailable. This syncs task status from files into the hub DB.
---
## Credential and access routing
**Audience:** Codex, Claude Code, Grok, and custodian agents that call **llm-connect**
for inference. Run this check **before** requesting secrets, API keys, SSH access,
login tokens, or database passwords — in any repo, not only `ops-warden`.
ops-warden **issues SSH certificates only** (`warden sign`, `cert_command`). Every
other credential need belongs to another subsystem. **Do not** message
`ops-warden` on State Hub expecting a secret value; the reply is a pointer, not a key.
### Lookup (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. -->
---
## Workplan Convention (ADR-001)
Work items originate as files in this repo — not in the hub. The hub is a
read/cache/index layer that rebuilds from files.
**File location:** `workplans/RAILIANCE-WP-NNNN-<slug>.md`
**Archived location:** finished workplans may move to
`workplans/archived/YYMMDD-RAILIANCE-WP-NNNN-<slug>.md`. The `YYMMDD` prefix is
the completion/archive date; the frontmatter `id` does not change.
**Ad Hoc Tasks:** small opportunistic fixes discovered during a session use
`workplans/ADHOC-YYYY-MM-DD.md` with task ids `ADHOC-YYYY-MM-DD-T01`, etc. Use
this only for low-risk work completed directly; create a normal workplan for
anything needing analysis, design, approval, dependencies, or multiple phases.
**Frontmatter:**
```yaml
---
id: RAILIANCE-WP-NNNN
type: workplan
title: "..."
domain: financials
repo: railiance-fabric
status: proposed | ready | active | blocked | backlog | finished | archived
owner: codex
topic_slug: ...
created: "YYYY-MM-DD"
updated: "YYYY-MM-DD"
state_hub_workstream_id: "<uuid>" # written by fix-consistency — do not edit
---
```
Use `proposed` for a new draft, `ready` after review against current repo
state, and `finished` after implementation. `stalled` and `needs_review` are
derived health labels, not frontmatter statuses.
**Task block format** (one per `##` section):
```
## Task Title
` ` `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
` ` `
Task description text.
```
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
2. Notify the custodian operator to run `make fix-consistency REPO=railiance-fabric`
(or send a message to the hub agent via `POST /messages/`)

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

232
INTENT.md Normal file
View File

@@ -0,0 +1,232 @@
# Railiance Fabric Intent
Date: 2026-05-17
## Intent
Railiance Fabric exists to make the Railiance ecosystem understandable,
discoverable, and evolvable as services begin to depend on one another.
It models the living fabric of repositories, services, capabilities,
interfaces, and dependencies so humans and agents can answer questions like:
- Which service provides runtime secrets?
- Which repos consume the NetKingdom IAM Profile?
- What breaks if the flex-auth decision envelope changes?
- Which workloads require OpenBao KV, dynamic database credentials, or
object-storage credential vending?
- Which dependencies are declared, missing, stale, or boundary-violating?
The core idea is simple:
```text
repo -> service -> capability -> interface -> dependency
```
Repos remain the source of truth for what they provide and require. Railiance
Fabric gives those declarations a shared schema, validation model, graph view,
and discovery surface.
## Why This Exists
Railiance is entering the phase where platform services, identity services,
application workloads, automation, policy engines, storage, and observability
will interact continuously.
Without an explicit ecosystem graph, those interactions become folklore:
implicit dependencies, stale mental maps, fragile deployment order, and unclear
ownership when interfaces change.
Railiance Fabric turns that implicit web into a reviewable graph:
- capabilities are discoverable by name and semantics
- interfaces are typed and versioned
- consumers declare their requirements
- providers declare what they actually offer
- State Hub can ingest the graph as a read model
- agents can reason about blast radius, missing providers, and safe sequencing
## Responsibility Boundary
### Repositories Own Declarations
Each repo owns file-backed declarations for its provided capabilities,
consumed capabilities, services, and interface contracts.
Examples:
```text
fabric/capabilities/*.yaml
fabric/dependencies/*.yaml
fabric/interfaces/*.yaml
fabric/services/*.yaml
```
These files are reviewable, versioned with the repo, and changed through normal
pull-request or workplan flow.
### Railiance Fabric Owns The Graph Model
Railiance Fabric owns:
- declaration schemas
- validation rules
- graph construction
- local inspection tools
- provider/consumer matching
- compatibility and drift checks
- example declarations for core Railiance services
- export formats for State Hub, docs, and dashboards
### State Hub Owns The Read Model
State Hub should ingest the ecosystem graph and expose it for coordination,
but it should not become the primary authoring surface for capability and
dependency declarations.
This keeps ADR-001 intact: formal work and declarations originate in repos;
the hub reads, visualizes, and coordinates.
## First-Class Concepts
### Repository
A source-controlled project with ownership, workplans, implementation, and
local declarations.
### Service
A deployable or callable unit produced by a repository. A repo may produce zero
or more services.
Examples: OpenBao, key-cape, flex-auth API, Topaz deployment, artifact-store.
### Capability
A stable semantic ability that consumers can depend on without hard-coding the
current implementation.
Examples:
- runtime secrets
- IAM Profile issuer
- authorization decision service
- PostgreSQL database service
- object-storage credential vending
- scope generation
### Interface
The concrete contract through which a capability is consumed.
Examples:
- HTTP API
- OIDC discovery
- Kubernetes Secret
- Kubernetes CRD
- Helm release
- CLI
- database connection
- object-storage bucket
- event stream
- policy package
- OpenBao KV v2 mount
- OpenBao database dynamic credential role
### Dependency
A consumer's declared requirement for a capability or interface, including
version, environment, auth, data classification, criticality, and fallback
expectations.
### Binding
A resolved edge between a consumer dependency and a provider capability.
Bindings may be exact, compatible, degraded, missing, or disputed.
## Design Principles
- Source of truth lives in repos.
- Capabilities are stable; implementations may move.
- Interfaces are typed, versioned, and testable.
- Dependencies are explicit requirements, not accidental imports.
- Discovery is graph search, not tribal memory.
- Validation should catch missing providers before deployment time.
- Compatibility should be machine-checkable where possible.
- Human-readable files matter; agents and humans must both be able to inspect
declarations without a running service.
- The model must support partial adoption. A repo can begin with one declared
capability or dependency and mature over time.
- The graph should reveal boundary violations without pretending to own every
domain's decisions.
## Strategic Role
Railiance Fabric sits between repository scoping, State Hub, and the Railiance
deployment stack.
```text
repo-local declarations
|
v
Railiance Fabric schema and graph tools
|
+-- State Hub ingestion and coordination
+-- documentation and topology maps
+-- agent planning and blast-radius analysis
+-- deployment readiness checks
```
It complements:
- `repo-scoping`, which explains what a repo is useful for.
- `the-custodian/state-hub`, which coordinates domains, workstreams, tasks, and
progress.
- `railiance-platform`, which deploys shared S3 services such as OpenBao,
PostgreSQL, Valkey, and object storage.
- `net-kingdom`, which owns identity, credential, and security architecture.
- `flex-auth`, which owns authorization policy and decision semantics.
## Non-Goals
Railiance Fabric is not:
- a deployment orchestrator
- a replacement for State Hub
- a replacement for SCOPE.md
- a service mesh
- a CMDB that must manually mirror everything
- an authorization engine
- a secret manager
- a package registry
It may inform those systems, but its job is the ecosystem graph and declaration
model.
## Early Questions
- What is the smallest declaration schema that is useful without becoming
ceremony?
- Which capability and interface types must exist on day one?
- How should provider/consumer matching handle environment, version, auth,
tenant, and data-class constraints?
- Which graph checks are advisory, and which should block deployment?
- How does State Hub ingest the graph without becoming the authoring source?
- How do we represent capabilities that are planned but not deployed yet?
## Maturity Target
A mature Railiance Fabric should let a human or agent ask:
```text
Show all consumers of OpenBao.
Show missing providers for production Railiance.
Show every service that depends on NetKingdom identity claims.
Show all interfaces crossing from S3 platform services into S5 applications.
Show blast radius for changing flex-auth decision envelope v1.
Show runtime readiness for tenant:coulomb onboarding.
```
and receive source-linked, repo-owned answers.

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

157
README.md
View File

@@ -1,3 +1,156 @@
# repo-seed
# Railiance Fabric
A git repository template to bootstrap coulomb projects from.
Railiance Fabric models the durable infrastructure-responsibility graph of the
Railiance netkingdom.
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
From a checkout with the Python dependencies installed:
```bash
railiance-fabric validate .
```
During early bootstrapping, the local module entry point works too:
```bash
PYTHONPATH=. python -m railiance_fabric.cli validate .
```
The validator loads `fabric/` declarations, checks schema conformance, verifies
catalog type names, catches missing references/providers, checks active
production dependency source links, and warns about dependency cycles.
## Query The Graph
```bash
railiance-fabric providers runtime-secrets
railiance-fabric consumers railiance-platform.openbao.kv-v2
railiance-fabric dependency-path flex-auth.api
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 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. See `docs/registry-api.md` for the current registry HTTP API.
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
```
The initial service exposes repository registration, graph snapshot ingestion,
artifact attachment, graph query endpoints, State Hub export, and early
Backstage/xRegistry projection endpoints. It stores snapshots in SQLite and
reuses the Fabric graph export shape.
Feed the running service from this checkout:
```bash
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
railiance-fabric registry ingest-cyclonedx bom.json --repo-slug railiance-fabric
```
Useful inspection endpoints include:
```text
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.

139
SCOPE.md Normal file
View File

@@ -0,0 +1,139 @@
# SCOPE
> This file helps you quickly understand what this repository is about,
> when it is relevant, and when it is not.
> It is intentionally lightweight and may be incomplete.
---
## One-liner
Defines the Railiance ecosystem graph model so repos can declare services,
capabilities, interfaces, dependencies, and bindings in source-controlled files.
---
## Core Idea
Railiance Fabric turns implicit cross-repo dependencies into a reviewable graph.
Participating repos remain the source of truth for what they provide and
consume; this repo owns the shared schema, validation rules, graph construction,
query tooling, seed examples, and export format that State Hub can ingest as a
read model.
---
## In Scope
- YAML declaration schemas for services, capabilities, interfaces,
dependencies, and binding assertions.
- Capability and interface type catalogs for the Railiance ecosystem.
- Seed declarations for core Railiance providers and consumers.
- Local graph loading, validation, discovery queries, and export tooling.
- State Hub ingestion contract for graph exports.
- Adoption guidance for adding declarations to other repos.
---
## Out of Scope
- Deployment orchestration or GitOps ownership.
- Replacing State Hub workstreams, tasks, decisions, or progress events.
- Replacing repo-scoping, SCOPE.md, ADRs, service meshes, secret managers, or
authorization engines.
- Making State Hub the authoring surface for capability declarations.
- Runtime traffic discovery that bypasses repo-owned declarations.
---
## Relevant When
- You need to declare what a Railiance repo provides or consumes.
- You need to ask which services depend on a capability or interface.
- You need to validate missing providers, stale interfaces, or compatibility
issues before sequencing work.
- You need a graph export that State Hub can display without owning the source
declarations.
---
## Not Relevant When
- You are deploying infrastructure rather than modeling its ecosystem contract.
- You need to manage State Hub tasks, decisions, messages, or progress events.
- You need service-specific implementation details owned by another repo.
- You need an authorization, secret-management, or package-registry runtime.
---
## Current State
- Status: active planning
- Implementation: intent and first workplan present
- Stability: evolving
- Usage: internal Railiance ecosystem modeling
The first workplan is `RAIL-FAB-WP-0001`, which establishes vocabulary, schema,
seed examples, validator/query tooling, and State Hub integration.
---
## How It Fits
- Upstream dependencies: repo-owned declarations in participating Railiance
repos.
- Downstream consumers: State Hub read model, documentation, dashboards, and
agent planning flows.
- Often used with: `repo-scoping`, `the-custodian/state-hub`,
`railiance-platform`, `net-kingdom`, `flex-auth`, and `artifact-store`.
---
## Terminology
- Preferred terms: repository, service, capability, interface, dependency,
binding.
- Also known as: ecosystem graph, capability graph, dependency graph.
- Potentially confusing terms: State Hub is the read/cache/index layer here,
not the authoring source for declarations.
---
## Related / Overlapping Repositories
- `repo-scoping` — explains what a repo is useful for; Railiance Fabric models
what repos provide and consume.
- `the-custodian/state-hub` — coordinates domains, workstreams, tasks, and
progress; it should ingest Fabric graph exports as a read model.
- `railiance-platform` — deploys shared platform services that should become
graph provider nodes.
- `net-kingdom` — owns identity, credential, and security architecture that
appears in capability/interface declarations.
- `flex-auth` — owns authorization policy and decision semantics that should be
represented as graph capabilities and interfaces.
---
## Getting Oriented
- Start with: `INTENT.md`
- Key files / directories: `workplans/`
- Entry points: `workplans/RAIL-FAB-WP-0001-ecosystem-graph-model.md`
---
## Provided Capabilities
```capability
type: tooling
title: Railiance ecosystem graph model
description: Shared declaration schema, validation model, query tooling, and State Hub export contract for Railiance service/capability/dependency graphs.
keywords: [railiance, graph, capabilities, dependencies, interfaces, state-hub]
```
---
## Notes
Repos own declarations. Railiance Fabric owns graph semantics and validation.
State Hub owns coordination and display of ingested read models.

11
catalog/README.md Normal file
View File

@@ -0,0 +1,11 @@
# Type Catalog
This directory contains the first Railiance Fabric type catalog.
- `capability-types.yaml` defines stable semantic capabilities.
- `interface-types.yaml` defines concrete integration surfaces.
Declaration schemas keep `capability_type` and `interface_type` as strings so
the core document shape stays decoupled from catalog evolution. The validator
planned in `RAIL-FAB-WP-0001-T05` should load these catalogs and reject unknown
types unless an explicit experimental override is added later.

View File

@@ -0,0 +1,207 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityTypeCatalog
metadata:
id: railiance-fabric.capability-types
name: Railiance capability type catalog
owner: railiance-fabric
repo: railiance-fabric
domain: railiance
spec:
version: v1alpha1
types:
- id: runtime-secrets
name: Runtime secrets
lifecycle: active
description: Stores or vends runtime secrets needed by workloads after deployment.
default_criticality: critical
default_data_classification: secret
expected_interface_types:
- openbao-kv-v2-mount
- kubernetes-secret
tags: [security, platform, secrets]
- id: iam-profile-issuer
name: IAM Profile issuer
lifecycle: active
description: Issues or serves identity profile claims used by Railiance services.
default_criticality: critical
default_data_classification: restricted
expected_interface_types:
- oidc-discovery
- http-api
tags: [identity, security]
- id: authorization-decision-service
name: Authorization decision service
lifecycle: active
description: Evaluates authorization policy and returns allow/deny decisions with context.
default_criticality: critical
default_data_classification: restricted
expected_interface_types:
- http-api
- policy-package
tags: [authorization, policy, security]
- id: postgresql-database-service
name: PostgreSQL database service
lifecycle: active
description: Provides PostgreSQL databases, roles, and connection endpoints for workloads.
default_criticality: high
default_data_classification: confidential
expected_interface_types:
- database-connection
- openbao-dynamic-credential-role
tags: [database, platform]
- id: redis-compatible-cache
name: Redis-compatible cache
lifecycle: active
description: Provides Redis protocol compatible caching or ephemeral data storage.
default_criticality: medium
default_data_classification: internal
expected_interface_types:
- database-connection
- kubernetes-secret
tags: [cache, platform]
- id: object-storage
name: Object storage
lifecycle: planned
description: Provides bucket-style durable object storage for Railiance workloads.
default_criticality: high
default_data_classification: confidential
expected_interface_types:
- object-storage-bucket
- http-api
tags: [storage, platform]
- id: object-storage-credential-vending
name: Object-storage credential vending
lifecycle: planned
description: Issues scoped temporary credentials for object-storage access.
default_criticality: high
default_data_classification: secret
expected_interface_types:
- http-api
- openbao-dynamic-credential-role
- 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
description: Accepts audit, operational, or domain events for durable recording or routing.
default_criticality: high
default_data_classification: confidential
expected_interface_types:
- event-stream
- http-api
tags: [events, audit, observability]
- id: scope-generation
name: Scope generation
lifecycle: active
description: Produces repo or project scope descriptions used by humans and agents.
default_criticality: medium
default_data_classification: internal
expected_interface_types:
- cli
- http-api
tags: [planning, agents, documentation]
- id: coordination-read-model
name: Coordination read model
lifecycle: active
description: Exposes coordination state for repos, workstreams, tasks, decisions, and progress.
default_criticality: high
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

@@ -0,0 +1,186 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceTypeCatalog
metadata:
id: railiance-fabric.interface-types
name: Railiance interface type catalog
owner: railiance-fabric
repo: railiance-fabric
domain: railiance
spec:
version: v1alpha1
types:
- id: http-api
name: HTTP API
lifecycle: active
description: Request/response HTTP interface, usually JSON over HTTPS.
category: api
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
description: OpenID Connect discovery metadata and JWKS endpoints.
category: identity
typical_auth_methods: [none]
versioning: issuer URL and advertised metadata.
- id: kubernetes-secret
name: Kubernetes Secret
lifecycle: active
description: Kubernetes Secret object consumed by workloads in a namespace.
category: kubernetes
typical_auth_methods: [kubernetes_service_account]
versioning: object name, key schema, and owner annotations.
- id: kubernetes-crd
name: Kubernetes CRD
lifecycle: active
description: Kubernetes custom resource definition and versioned resource schema.
category: kubernetes
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
description: Helm chart/release interface used to install or configure a service.
category: deployment
typical_auth_methods: [kubernetes_service_account]
versioning: chart version and values schema.
- id: cli
name: CLI
lifecycle: active
description: Command-line interface consumed by humans, agents, or automation.
category: tooling
typical_auth_methods: [none, oidc, api_key, unknown]
versioning: command version and documented flags.
- id: database-connection
name: Database connection
lifecycle: active
description: Network database endpoint plus credentials and connection parameters.
category: data
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
description: Bucket, prefix, policy, and endpoint contract for object storage.
category: storage
typical_auth_methods: [sts_token, static_secret, openbao_token]
versioning: bucket policy version and object layout contract.
- id: event-stream
name: Event stream
lifecycle: planned
description: Pub/sub or streaming interface for audit, operational, or domain events.
category: events
typical_auth_methods: [jwt, mtls, api_key, unknown]
versioning: subject/topic names and event envelope schema.
- id: policy-package
name: Policy package
lifecycle: active
description: Versioned policy bundle consumed by an authorization runtime.
category: policy
typical_auth_methods: [none, oidc, jwt]
versioning: package version and policy input/output schema.
- id: openbao-kv-v2-mount
name: OpenBao KV v2 mount
lifecycle: active
description: OpenBao KV v2 mount path and secret layout contract.
category: secrets
typical_auth_methods: [kubernetes_service_account, openbao_token]
versioning: mount path, key layout, and policy version.
- id: openbao-dynamic-credential-role
name: OpenBao dynamic credential role
lifecycle: active
description: OpenBao role that issues dynamic credentials for another service.
category: credentials
typical_auth_methods: [kubernetes_service_account, openbao_token]
versioning: role name, policy, lease semantics, and backend version.
- id: sts-token
name: STS token
lifecycle: planned
description: Temporary scoped credential issued for object storage or similar services.
category: credentials
typical_auth_methods: [oidc, jwt, mtls]
versioning: token claim schema, audience, and lease semantics.

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.

207
docs/adoption-guide.md Normal file
View File

@@ -0,0 +1,207 @@
# Adoption Guide
This guide shows another repo how to adopt Railiance Fabric declarations without
reading Railiance Fabric source code.
## 1. Add The Directory Layout
Create the declaration directories in your repo:
```text
fabric/
services/
capabilities/
interfaces/
dependencies/
bindings/
```
Start with only the files you need. A repo can adopt Fabric with one service
and one capability, or with one dependency on a capability provided elsewhere.
## 2. Declare A Service
Create `fabric/services/<repo>-<service>.yaml`:
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: your-repo.your-service
name: Your Service
owner: your-repo
repo: your-repo
domain: railiance
source_links:
- label: Service README
path: README.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: What this service does.
service_type: app-service
provides_capabilities: []
exposes_interfaces: []
```
Use lower-case dotted IDs. Prefer IDs that begin with the owning repo slug.
## 3. Declare A Provided Capability
Create `fabric/capabilities/<repo>-<capability>.yaml`:
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: your-repo.your-service.runtime-secrets
name: Runtime secrets
owner: your-repo
repo: your-repo
domain: railiance
source_links:
- label: Capability docs
path: docs/runtime-secrets.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: What this capability provides.
capability_type: runtime-secrets
service_id: your-repo.your-service
interface_ids:
- your-repo.your-service.kv-v2
criticality: high
data_classification: secret
```
Pick `capability_type` from `catalog/capability-types.yaml`.
## 4. Declare An Interface
Create `fabric/interfaces/<repo>-<interface>.yaml`:
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: your-repo.your-service.http-api
name: Your Service HTTP API
owner: your-repo
repo: your-repo
domain: railiance
source_links:
- label: API docs
path: docs/api.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: How consumers call this interface.
interface_type: http-api
version: v1
service_id: your-repo.your-service
capability_ids:
- your-repo.your-service.some-capability
auth:
method: oidc
data_classification: internal
```
Pick `interface_type` from `catalog/interface-types.yaml`.
## 5. Declare A Dependency
Create `fabric/dependencies/<repo>-<dependency>.yaml`:
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: your-repo.your-service.needs-runtime-secrets
name: Runtime secrets dependency
owner: your-repo
repo: your-repo
domain: railiance
source_links:
- label: Deployment values
path: deploy/values.yaml
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: your-repo.your-service
requires:
capability_type: runtime-secrets
interface:
type: openbao-kv-v2-mount
version_constraint: ">=v1 <v2"
auth:
method: kubernetes_service_account
criticality: high
data_classification: secret
fallback:
mode: none
description: Service cannot start without runtime secrets.
```
Active production dependencies should include at least one source link.
## 6. Add A Binding Only When Needed
Most bindings can be computed by the graph loader from dependency requirements
and provider capabilities. Add a `BindingAssertion` when you need to pin,
override, dispute, or document a planned provider:
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: your-repo.your-service.runtime-secrets-to-openbao
name: Runtime secrets binding
owner: your-repo
repo: your-repo
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: your-repo.your-service.needs-runtime-secrets
provider_capability_id: railiance-platform.openbao.runtime-secrets
provider_interface_id: railiance-platform.openbao.kv-v2
status: compatible
rationale: This service uses OpenBao KV v2 for runtime secrets.
```
## 7. Validate Locally
From the Railiance Fabric repo:
```bash
railiance-fabric validate /path/to/your-repo
```
During early bootstrapping:
```bash
PYTHONPATH=. python -m railiance_fabric.cli validate /path/to/your-repo
```
Useful discovery checks:
```bash
railiance-fabric providers runtime-secrets /path/to/your-repo
railiance-fabric consumers runtime-secrets /path/to/your-repo
railiance-fabric unresolved /path/to/your-repo
```
For multi-repo validation, pass multiple roots:
```bash
railiance-fabric validate /path/to/repo-a /path/to/repo-b
```
## 8. Export For State Hub
```bash
railiance-fabric export --format json /path/to/your-repo
```
State Hub should ingest that export as a read model. Do not edit declarations in
State Hub; change them in the owning repo and re-export.

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.

258
docs/declaration-schema.md Normal file
View File

@@ -0,0 +1,258 @@
# Declaration Schema
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 that publish local evidence should use this layout:
```text
fabric/
services/*.yaml
capabilities/*.yaml
interfaces/*.yaml
dependencies/*.yaml
bindings/*.yaml
```
Railiance Fabric itself keeps reusable schemas in `schemas/` and examples in
`examples/declarations/`.
## Shared Shape
Every declaration has:
```yaml
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-platform.openbao
name: OpenBao
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
```
`metadata.id` is the stable graph identifier. Use lower-case dotted IDs that
begin with the owning repo slug when possible:
```text
<repo>.<service>
<repo>.<service>.<capability>
<repo>.<service>.<interface>
<repo>.<consumer>.<dependency>
```
## Shared Fields
| Field | Meaning |
|-------|---------|
| `apiVersion` | Schema API version. Currently `railiance.fabric/v1alpha1`. |
| `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` | 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. |
| `spec.lifecycle` | `planned`, `active`, `deprecated`, or `retired`. |
| `spec.environments` | One or more of `dev`, `staging`, `prod`, or `all`. |
## Declaration Kinds
### ServiceDeclaration
A deployable or callable unit produced by a repo.
Required type-specific fields:
- `spec.description`
Optional relationship fields:
- `spec.service_type`
- `spec.provides_capabilities`
- `spec.exposes_interfaces`
Schema: `schemas/service.schema.yaml`
### CapabilityDeclaration
A stable semantic ability that consumers depend on.
Required type-specific fields:
- `spec.description`
- `spec.capability_type`
- `spec.service_id`
- `spec.criticality`
- `spec.data_classification`
Optional relationship fields:
- `spec.interface_ids`
- `spec.compatibility`
Schema: `schemas/capability.schema.yaml`
`spec.capability_type` should match a type in
`catalog/capability-types.yaml`. Unknown types are allowed by the document
schema but should fail graph validation.
### InterfaceDeclaration
A concrete integration surface through which a capability is consumed.
Required type-specific fields:
- `spec.description`
- `spec.interface_type`
- `spec.version`
- `spec.service_id`
- `spec.auth.method`
- `spec.data_classification`
Optional relationship fields:
- `spec.capability_ids`
- `spec.endpoint`
- `spec.auth.audience`
- `spec.auth.scopes`
- `spec.compatibility`
Schema: `schemas/interface.schema.yaml`
`spec.interface_type` should match a type in `catalog/interface-types.yaml`.
Unknown types are allowed by the document schema but should fail graph
validation.
### DependencyDeclaration
A consumer's declared requirement for a capability or interface.
Required type-specific fields:
- `spec.consumer_service_id`
- `spec.requires.capability_type`
- `spec.criticality`
- `spec.data_classification`
Optional constraint fields:
- `spec.requires.capability_id`
- `spec.interface.type`
- `spec.interface.version_constraint`
- `spec.auth.method`
- `spec.fallback`
- `spec.compatibility`
Schema: `schemas/dependency.schema.yaml`
`spec.requires.capability_type` and `spec.interface.type` should match the
type catalogs. Unknown types are allowed by the document schema but should fail
graph validation.
### BindingAssertion
A source-controlled assertion that resolves a dependency to a provider
capability and, optionally, a provider interface. Most bindings should be
computed by the graph loader; binding assertions are for overrides, disputes,
or planned relationships that need an explicit record.
Required type-specific fields:
- `spec.dependency_id`
- `spec.provider_capability_id`
- `spec.status`
- `spec.rationale`
Optional relationship fields:
- `spec.provider_interface_id`
- `spec.compatibility`
Schema: `schemas/binding.schema.yaml`
## Shared Value Sets
### Lifecycle
```text
planned, active, deprecated, retired
```
### Environment
```text
dev, staging, prod, all
```
Use `all` only when the declaration truly applies across every environment.
### Data Classification
```text
public, internal, confidential, restricted, secret
```
### Criticality
```text
low, medium, high, critical
```
### Auth Method
```text
none, oidc, jwt, mtls, kubernetes_service_account, openbao_token,
static_secret, database_role, sts_token, api_key, unknown
```
`unknown` is allowed for discovery-stage declarations but should not remain on
active production dependencies.
## Compatibility
The optional `compatibility` object records machine-checkable or human-reviewed
constraints:
```yaml
compatibility:
version: "v1"
requires:
- "decision-envelope >=1.0 <2.0"
compatible_with:
- "flex-auth.decision-api.v1"
breaks:
- "decision-envelope v0"
notes: "Envelope v1 is required for tenant-scoped decisions."
```
T05 will decide which compatibility fields are advisory and which should fail
validation.
## Source Links
Use `metadata.source_links` when a declaration is based on a concrete source:
```yaml
source_links:
- label: OpenBao Helm values
path: charts/openbao/values.yaml
- label: Runtime secrets workplan
url: https://example.invalid/workplans/openbao-runtime-secrets
```
At least one source link is recommended for `active` declarations. T05 will
make source-link requirements stricter for active production dependencies.

113
docs/discovery-queries.md Normal file
View File

@@ -0,0 +1,113 @@
# Discovery Queries And Exports
Railiance Fabric includes a first CLI surface for inspecting local declaration
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`.
## Providers
List providers for a capability type or capability id:
```bash
railiance-fabric providers runtime-secrets
railiance-fabric providers railiance-platform.openbao.runtime-secrets
```
Output columns:
```text
provider_id service_id lifecycle environments interfaces
```
## Consumers
List consumers of a capability type/id or interface type/id:
```bash
railiance-fabric consumers runtime-secrets
railiance-fabric consumers railiance-platform.openbao.kv-v2
```
Output columns:
```text
consumer_service_id dependency_id requires provider_capability_id provider_interface_id status
```
## Dependency Path
Show dependency paths for a service:
```bash
railiance-fabric dependency-path flex-auth.api
```
This walks declared dependencies and binding assertions recursively through
provider services.
## Unresolved Dependencies
Show dependencies with no matching provider or a `missing`/`disputed` binding:
```bash
railiance-fabric unresolved
```
## Blast Radius
Show consumers affected by an interface type or interface id:
```bash
railiance-fabric blast-radius openbao-kv-v2-mount
railiance-fabric blast-radius railiance-platform.openbao.kv-v2
```
## Exports
Export the graph as JSON:
```bash
railiance-fabric export --format json
```
Export the graph as Mermaid:
```bash
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

@@ -0,0 +1,256 @@
# Ecosystem Registry Service Direction
This note compares Railiance Fabric with adjacent projects and standards before
starting a service implementation for registering repositories, libraries,
services, capabilities, interfaces, and dependencies.
## Recommendation
Build a small Railiance Ecosystem Registry service as the API and indexed read
model over accepted Fabric graph snapshots, discovery evidence, and supporting
inventory.
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.
Railiance should borrow that shape where useful, especially for versioned
resources, import/export, filtering, and contract registries. Railiance should
not begin by claiming xRegistry compliance; it should keep a compatible path.
## Standards And Projects To Compare
| Project or standard | What it is good at | What Railiance should borrow | What not to copy as the core |
|---------------------|--------------------|-------------------------------|------------------------------|
| [CNCF xRegistry](https://xregistry.io/) | Vendor-neutral metadata registries with REST APIs, document views, versioned resources, endpoint/schema/message extensions. | Use as the primary comparison for registry API shape, versioned metadata, import/export, filtering, document/API symmetry, and future endpoint/message/schema projections. | Do not make every Fabric concept an xRegistry resource on day one; keep the Railiance graph model readable and repo-native first. |
| [Backstage Software Catalog](https://github.com/backstage/backstage/blob/master/docs/features/software-catalog/descriptor-format.md) | Developer portal catalog entities such as Component, API, Resource, System, Domain, ownership, relations, and `catalog-info.yaml`. | Support Backstage export/import projections for teams that want a portal later. Borrow the ownership and domain/system vocabulary where it aligns. | Do not make Backstage the authoritative store or require its plugin/runtime model before Railiance needs a portal. |
| [CycloneDX](https://cyclonedx.org/specification/overview/) | Supply-chain inventory for components, services, dependencies, relationships, and vulnerability/security context. | Use CycloneDX SBOM/SaaSBOM imports for libraries, packages, third-party services, component dependency graphs, and provenance facets. | Do not stretch CycloneDX into the whole ecosystem model; it is strongest for bill-of-materials and supply-chain evidence. |
| [OpenAPI](https://spec.openapis.org/oas/latest) | Machine-readable HTTP API contracts. | Attach OpenAPI documents to Fabric `InterfaceDeclaration` records for HTTP APIs and expose them through the registry. | Do not use OpenAPI to describe non-HTTP dependencies or ownership relationships. |
| [AsyncAPI](https://www.asyncapi.com/docs/reference/specification/v3.0.0) | Machine-readable event/message-driven API contracts with channels, messages, operations, and protocol bindings. | Attach AsyncAPI documents to event-stream interfaces and use its vocabulary for channel/message contracts. | Do not use AsyncAPI for general service inventory. |
| [CloudEvents](https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md) | Common event envelope metadata across services, platforms, and systems. | Use CloudEvents as the preferred event envelope for registry events and for Fabric event interfaces when the ecosystem needs portable event metadata. | Do not use CloudEvents as a catalog model; it is an event envelope. |
| [Open Service Broker API](https://www.openservicebrokerapi.org/) | Lifecycle commands for service catalogs, provisioning, binding, unbinding, and deprovisioning. | Borrow the clear distinction between service catalog, service instance, and binding if Railiance later adds self-service provisioning. | Do not implement provisioning as part of the initial registry; registration and discovery come first. |
| [Score](https://developer.humanitec.com/app-humanitec-io/docs/score/overview/) | Platform-agnostic workload intent for container workloads, with runtime requirements resolved by a platform. | Optionally import workload requirements into Fabric dependencies when repos already use Score. | Do not make Score mandatory; it is workload runtime intent, not an ecosystem graph. |
| [OpenLineage](https://openlineage.io/docs/spec/object-model/) | Job, run, dataset, and facet model for observing data movement and transformation. | Use its facet idea for extensible metadata and consider data-lineage projections later. | Do not use it as the general service/capability/dependency model. |
## Service Boundary
The registry service should own:
- repository registration and repository metadata snapshots
- ingestion of validated Fabric graph exports
- validation results per repo and commit
- indexed graph queries across all registered repos
- version history and drift comparisons between snapshots
- optional ingestion of supporting artifacts such as CycloneDX SBOMs,
OpenAPI documents, AsyncAPI documents, and Score workload files
- State Hub export or event emission for coordination views
The registry service should not own:
- hand-editing repo declarations through a central UI
- deployment orchestration
- service provisioning
- policy enforcement gates before the model has adoption
- replacing State Hub workstreams, tasks, progress, or planning state
- replacing a developer portal
## Initial Data Model
Railiance Fabric already has first-class declarations for:
- `ServiceDeclaration`
- `CapabilityDeclaration`
- `InterfaceDeclaration`
- `DependencyDeclaration`
- `BindingAssertion`
The registry service should add service-level records around those declarations:
| Entity | Purpose |
|--------|---------|
| Repository | Registered source repo, URL, default branch, State Hub repo id, scan config, last accepted snapshot. |
| Snapshot | Immutable ingest result for a repo at a commit. |
| Graph Node | Indexed projection of a service, capability, interface, dependency, or binding. |
| Graph Edge | Indexed relationship such as provides, exposes, consumes, binds, or uses interface. |
| Artifact | Supporting document such as CycloneDX SBOM, OpenAPI, AsyncAPI, Score, README, or source link. |
| Validation Result | Errors, warnings, schema versions, catalog versions, and unresolved references. |
| Registry Event | Change event emitted when a repo, snapshot, node, edge, or validation result changes. |
## API Shape
Start with a small HTTP API that mirrors the local CLI answers:
```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
GET /search?q=jsonschema
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
POST /artifacts
GET /artifacts/{artifact_id}
GET /exports/state-hub
GET /exports/backstage
GET /exports/xregistry
```
`POST /repositories/{repo_slug}/snapshots` should accept the current
`FabricGraphExport` plus source metadata:
```json
{
"repo_slug": "railiance-fabric",
"commit": "git-sha",
"generated_at": "2026-05-17T00:00:00Z",
"graph": {
"apiVersion": "railiance.fabric/v1alpha1",
"kind": "FabricGraphExport",
"nodes": [],
"edges": []
}
}
```
## Interoperability Direction
The first implementation should be Railiance-native but deliberately
projection-friendly:
- Backstage projection: export `Component`, `API`, `Resource`, `System`, and
`Domain` entities from Fabric nodes where possible.
- xRegistry projection: expose schemas, messages, endpoints, and possibly
Fabric-specific registry groups once the internal model settles.
- CycloneDX import: attach SBOM components, services, and dependencies to repo
and service nodes.
- OpenAPI/AsyncAPI attachment: connect contract documents to interface nodes
and validate that declared interface type/version metadata is consistent.
- CloudEvents events: emit registry changes such as
`railiance.fabric.repository.registered`,
`railiance.fabric.snapshot.accepted`, and
`railiance.fabric.validation.failed`.
- Score import: map workload resources and dependencies into draft Fabric
dependency declarations only when a repo opts in.
## Suggested Architecture
```text
repo-local fabric/*.yaml
|
v
railiance-fabric validate/export
|
v
Ecosystem Registry ingest API
|
+--> snapshot store
+--> graph index
+--> artifact index
+--> validation result store
|
+--> State Hub export/events
+--> Backstage/xRegistry projections
+--> query API for agents and humans
```
Keep the first service boring: the existing Python loader and validator should
be reused. A lightweight Python HTTP service with a local relational store is
enough for the first useful version. Once ingestion and query semantics are
stable, the backing store can be replaced or expanded.
## First Implementation Slice
1. Service scaffold using the existing loader, validator, and graph export
model.
2. Repository registration endpoint with repo slug, URL, default branch, and
optional State Hub repo id.
3. Snapshot ingest endpoint that validates a `FabricGraphExport` and stores it
atomically.
4. Query endpoints for providers, consumers, unresolved dependencies, dependency
paths, and blast radius.
5. State Hub export endpoint matching `docs/state-hub-integration.md`.
6. Contract attachment for OpenAPI and AsyncAPI documents.
7. CycloneDX SBOM attachment for library/package inventory.
8. CloudEvents-style registry events once mutation endpoints exist.
## First Service Slice
The initial implementation is deliberately dependency-light:
- `railiance_fabric.registry` owns SQLite persistence, snapshot validation, and
graph query helpers.
- `railiance_fabric.server` exposes a stdlib HTTP service.
- `railiance-fabric-registry` starts the service.
The first endpoint set is:
```text
GET /health
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
GET /search?q=jsonschema
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
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
GET /exports/state-hub
GET /exports/backstage
GET /exports/xregistry
GET /exports/libraries/xregistry
```
The local CLI can feed a running registry:
```bash
railiance-fabric registry sync --repo-slug railiance-fabric .
railiance-fabric registry ingest-cyclonedx bom.json --repo-slug railiance-fabric
```
## Open Design Questions
- Should the registry pull repos itself, or should repos/agents push validated
exports from CI? Push is simpler and keeps credentials narrower.
- Should repository registration live first in State Hub and sync into Fabric
Registry, or should Fabric Registry own its own repo registry and annotate
State Hub ids? The current boundary suggests Fabric Registry owns graph
registration, State Hub owns planning/coordination.
- Should the first storage backend be SQLite for local operations or Postgres
from the start? SQLite is enough for proving semantics; Postgres is better
once multiple agents write concurrently.
- Should xRegistry compatibility be a projection only, or should the internal
registry model follow xRegistry group/resource/version terminology? Start as
projection; revisit after the first API is exercised.

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.

56
docs/first-rollout.md Normal file
View File

@@ -0,0 +1,56 @@
# First Rollout
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 contribute local evidence while
financial Fabric ownership and boundary decisions come from accountability-root
discovery.
## Seeded Repos
| Repo | Seeded Service(s) | First Capability |
|------|-------------------|------------------|
| `railiance-platform` | OpenBao, CNPG, Valkey | runtime secrets, PostgreSQL, Redis-compatible cache |
| `net-kingdom` | IAM Profile contract | IAM Profile issuer |
| `key-cape` | IAM Profile API | IAM Profile issuer implementation |
| `flex-auth` | flex-auth API, Topaz | authorization decisions |
| `artifact-store` | object storage service | object storage, credential vending |
| `repo-scoping` | scope generator | scope generation |
| `the-custodian` | State Hub | coordination read model |
## Promotion Path
For each owning repo:
1. Copy the matching seed files from `railiance-fabric/fabric/` into the owning
repo's own `fabric/` directory.
2. Replace seed source links with repo-local source links.
3. Validate the owning repo by itself.
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 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
1. `railiance-platform`: owns OpenBao, CNPG, and Valkey provider declarations.
2. `key-cape`: owns the first concrete IAM Profile implementation.
3. `flex-auth`: owns authorization decisions and concrete consumers of OpenBao
and IAM Profile capabilities.
4. `the-custodian/state-hub`: owns coordination read-model declarations and is
the first export consumer.
5. `repo-scoping`: owns scope-generation provider declarations.
6. `artifact-store`: can promote planned object-storage declarations when its
interfaces stabilize.
## Completion Signal
The rollout is good enough for the next phase when:
- each repo can validate its own declarations
- the combined graph has no unresolved dependencies
- State Hub can ingest a `FabricGraphExport`
- dashboard/search views can answer provider, consumer, unresolved, and blast
radius questions from the ingested graph

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

@@ -0,0 +1,280 @@
# State Hub Integration Contract
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 |
|-------|------|--------------|
| 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
accountability roots + durable deployment evidence + repo evidence
|
v
railiance-fabric scan/validate/export
|
v
State Hub graph read model
|
v
dashboard, search, planning, progress links
```
## Export Shape
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`
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
kind: FabricGraphExport
nodes: []
edges: []
```
Node fields:
| Field | Meaning |
|-------|---------|
| `id` | Stable graph id from declaration metadata. |
| `kind` | Declaration kind: service, capability, interface, dependency, or binding. |
| `name` | Human-readable name. |
| `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:
| Field | Meaning |
|-------|---------|
| `from` | Source node id. |
| `to` | Target node id. |
| `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
Add a State Hub ingestion endpoint or job that stores the latest graph export
per source repo:
```text
POST /fabric/graph-exports
```
Suggested payload:
```json
{
"repo_slug": "railiance-fabric",
"commit": "<git-sha>",
"generated_at": "2026-05-17T00:00:00Z",
"graph": {
"apiVersion": "railiance.fabric/v1alpha1",
"kind": "FabricGraphExport",
"nodes": [],
"edges": []
}
}
```
Suggested storage:
```text
fabric_graph_exports
id
repo_id
commit
generated_at
graph_json
created_at
fabric_graph_nodes
export_id
graph_id
kind
name
repo_slug
domain_slug
lifecycle
fabric_graph_edges
export_id
from_graph_id
to_graph_id
edge_type
```
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
State Hub should enrich graph nodes by matching:
- `node.repo` -> `managed_repos.slug`
- `node.domain` -> `domains.slug`
- workplan source links -> `workstreams.slug` or file-backed workplan index
- progress events -> `repo_id` and related workstream/task when available
These links are annotations on the read model. They should never overwrite the
Fabric export or source evidence.
## Ingestion Rules
1. Reject exports that fail `schemas/state-hub-export.schema.yaml`.
2. Record the source repo and commit for every accepted export.
3. Replace the previous latest export for the same repo only after the new
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 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
State Hub should be able to answer:
- providers for a capability type
- consumers of a capability or interface
- unresolved dependencies
- blast radius for an interface id or type
- graph nodes by repo/domain/lifecycle
These are the same query families exposed locally by Railiance Fabric. The hub
read model should match local answers for the same export.

71
docs/type-catalog.md Normal file
View File

@@ -0,0 +1,71 @@
# Core Type Catalog
The type catalog names the stable semantic capabilities and concrete
integration surfaces used by Railiance Fabric declarations.
The catalog has two jobs:
- prevent ad hoc strings in repo-owned declaration files
- give the future validator enough metadata to warn about mismatched
capability/interface combinations
Machine-readable catalog files:
- `catalog/capability-types.yaml`
- `catalog/interface-types.yaml`
## Capability Types
| Type | Lifecycle | Default Criticality | Default Data | Expected Interfaces |
|------|-----------|---------------------|--------------|---------------------|
| `runtime-secrets` | active | critical | secret | `openbao-kv-v2-mount`, `kubernetes-secret` |
| `iam-profile-issuer` | active | critical | restricted | `oidc-discovery`, `http-api` |
| `authorization-decision-service` | active | critical | restricted | `http-api`, `policy-package` |
| `postgresql-database-service` | active | high | confidential | `database-connection`, `openbao-dynamic-credential-role` |
| `redis-compatible-cache` | active | medium | internal | `database-connection`, `kubernetes-secret` |
| `object-storage` | planned | high | confidential | `object-storage-bucket`, `http-api` |
| `object-storage-credential-vending` | planned | high | secret | `http-api`, `openbao-dynamic-credential-role`, `sts-token` |
| `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` |
| `helm-release` | active | deployment | `kubernetes_service_account` |
| `cli` | active | tooling | `none`, `oidc`, `api_key`, `unknown` |
| `database-connection` | active | data | `database_role`, `static_secret`, `openbao_token` |
| `object-storage-bucket` | planned | storage | `sts_token`, `static_secret`, `openbao_token` |
| `event-stream` | planned | events | `jwt`, `mtls`, `api_key`, `unknown` |
| `policy-package` | active | policy | `none`, `oidc`, `jwt` |
| `openbao-kv-v2-mount` | active | secrets | `kubernetes_service_account`, `openbao_token` |
| `openbao-dynamic-credential-role` | active | credentials | `kubernetes_service_account`, `openbao_token` |
| `sts-token` | planned | credentials | `oidc`, `jwt`, `mtls` |
## Validation Rules For T05
The graph validator should initially enforce:
- every `CapabilityDeclaration.spec.capability_type` exists in
`capability-types.yaml`
- every `InterfaceDeclaration.spec.interface_type` exists in
`interface-types.yaml`
- every `DependencyDeclaration.spec.requires.capability_type` exists in
`capability-types.yaml`
- every `DependencyDeclaration.spec.interface.type`, when present, exists in
`interface-types.yaml`
- provider interface types should be among the capability type's
`expected_interface_types`, unless a declaration includes a documented
compatibility note
The validator should warn, not fail, when a declaration uses a planned type in
an active production dependency. That keeps early adoption possible while still
surfacing rollout risk.

40
docs/validator.md Normal file
View File

@@ -0,0 +1,40 @@
# Validator
The first validator entry point is:
```bash
railiance-fabric validate <repo-or-file>...
```
It accepts:
- a repo root containing `fabric/`
- a `fabric/` directory
- one or more declaration YAML files
The validator currently checks:
- YAML load errors
- declaration schema conformance
- duplicate graph IDs
- unknown capability and interface types
- missing service, capability, interface, dependency, and binding references
- missing provider capabilities for dependencies
- binding provider/dependency capability type mismatches
- active production dependencies without `metadata.source_links`
- active production dependencies whose providers do not cover the environment
- service dependency cycles from binding assertions
Exit behavior:
- exits `0` when there are no errors
- exits `1` when errors are present
- exits `1` for warnings only when `--warnings-as-errors` is used
Examples:
```bash
PYTHONPATH=. python -m railiance_fabric.cli validate .
PYTHONPATH=. python -m railiance_fabric.cli validate fabric/
PYTHONPATH=. python -m railiance_fabric.cli validate examples/declarations/invalid/*.yaml
```

View File

@@ -0,0 +1,20 @@
# Declaration Fixtures
These fixtures support the legacy `v1alpha1` declaration schema and give the
validator real inputs to exercise.
`valid/` contains a coherent mini-graph:
- OpenBao service
- OpenBao runtime-secrets capability
- OpenBao KV v2 interface
- flex-auth runtime-secrets dependency
- binding assertion from flex-auth to OpenBao
`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,15 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: flex-auth.api.bad-binding-status
name: Bad binding status
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [dev]
dependency_id: flex-auth.api.needs-runtime-secrets
provider_capability_id: railiance-platform.openbao.runtime-secrets
status: accepted
rationale: Invalid because accepted is not a binding status.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-platform.openbao.bad-lifecycle
name: Bad lifecycle capability
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: started
environments: [dev]
description: Invalid because lifecycle must use the shared enum.
capability_type: runtime-secrets
service_id: railiance-platform.openbao
criticality: high
data_classification: secret

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: flex-auth.api.bad-environment
name: Bad environment dependency
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [production]
consumer_service_id: flex-auth.api
requires:
capability_type: runtime-secrets
criticality: high
data_classification: secret

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-platform.openbao.bad-auth
name: Bad auth interface
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: active
environments: [dev]
description: Invalid because oauth2 is not in the initial auth-method enum.
interface_type: http-api
version: v1
service_id: railiance-platform.openbao
auth:
method: oauth2
data_classification: internal

View File

@@ -0,0 +1,11 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
name: Missing ID Service
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: active
environments: [dev]
description: Invalid because metadata.id is required.

View File

@@ -0,0 +1,23 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: flex-auth.api.runtime-secrets-to-openbao
name: flex-auth runtime secrets binding
owner: flex-auth
repo: flex-auth
domain: railiance
source_links:
- label: Runtime secrets binding note
path: docs/runtime-secrets.md
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: flex-auth.api.needs-runtime-secrets
provider_capability_id: railiance-platform.openbao.runtime-secrets
provider_interface_id: railiance-platform.openbao.kv-v2
status: exact
rationale: flex-auth uses the OpenBao KV v2 mount as its runtime secrets provider.
compatibility:
version: v1
compatible_with:
- railiance-platform.openbao.kv-v2

View File

@@ -0,0 +1,26 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-platform.openbao.runtime-secrets
name: Runtime secrets
owner: railiance-platform
repo: railiance-platform
domain: railiance
source_links:
- label: Runtime secrets workplan
path: workplans/RAIL-PLAT-WP-openbao-runtime-secrets.md
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Stores and serves workload runtime secrets through OpenBao.
capability_type: runtime-secrets
service_id: railiance-platform.openbao
interface_ids:
- railiance-platform.openbao.kv-v2
criticality: critical
data_classification: secret
compatibility:
version: v1
compatible_with:
- railiance-platform.openbao.kv-v2
notes: Initial runtime secrets capability for Railiance workloads.

View File

@@ -0,0 +1,31 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: flex-auth.api.needs-runtime-secrets
name: flex-auth runtime secrets dependency
owner: flex-auth
repo: flex-auth
domain: railiance
source_links:
- label: flex-auth deployment values
path: deploy/values.yaml
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: flex-auth.api
requires:
capability_type: runtime-secrets
interface:
type: openbao-kv-v2-mount
version_constraint: ">=v1 <v2"
auth:
method: kubernetes_service_account
audience: openbao
criticality: critical
data_classification: secret
fallback:
mode: none
description: flex-auth cannot start without runtime secrets.
compatibility:
requires:
- openbao-kv-v2-mount v1

View File

@@ -0,0 +1,29 @@
apiVersion: railiance.fabric/v1alpha1
kind: InterfaceDeclaration
metadata:
id: railiance-platform.openbao.kv-v2
name: OpenBao KV v2 mount
owner: railiance-platform
repo: railiance-platform
domain: railiance
source_links:
- label: OpenBao KV mount manifest
path: manifests/openbao/kv-v2.yaml
spec:
lifecycle: active
environments: [dev, staging, prod]
description: KV v2 secret mount exposed to approved Railiance workloads.
interface_type: openbao-kv-v2-mount
version: v1
service_id: railiance-platform.openbao
capability_ids:
- railiance-platform.openbao.runtime-secrets
endpoint:
path: secret/data/railiance
auth:
method: kubernetes_service_account
audience: openbao
data_classification: secret
compatibility:
version: v1
notes: Consumers must use workload service-account authentication.

View File

@@ -0,0 +1,20 @@
apiVersion: railiance.fabric/v1alpha1
kind: ServiceDeclaration
metadata:
id: railiance-platform.openbao
name: OpenBao
owner: railiance-platform
repo: railiance-platform
domain: railiance
source_links:
- label: OpenBao platform chart
path: charts/openbao/values.yaml
spec:
lifecycle: active
environments: [dev, staging, prod]
description: OpenBao service used by Railiance workloads for runtime secrets.
service_type: platform-service
provides_capabilities:
- railiance-platform.openbao.runtime-secrets
exposes_interfaces:
- railiance-platform.openbao.kv-v2

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

27
fabric/README.md Normal file
View File

@@ -0,0 +1,27 @@
# 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:
- OpenBao runtime secrets
- NetKingdom IAM Profile contract
- key-cape IAM Profile implementation
- flex-auth authorization decisions
- Topaz delegated PDP runtime
- CloudNativePG PostgreSQL
- Valkey Redis-compatible cache
- artifact-store object storage and credential vending
- State Hub coordination read model
- repo-scoping scope generation
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 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: artifact-store.object-storage.runtime-secrets-to-openbao
name: artifact-store runtime secrets binding
owner: artifact-store
repo: artifact-store
domain: railiance
spec:
lifecycle: planned
environments: [dev, staging, prod]
dependency_id: artifact-store.object-storage.needs-runtime-secrets
provider_capability_id: railiance-platform.openbao.runtime-secrets
provider_interface_id: railiance-platform.openbao.kv-v2
status: compatible
rationale: Planned object-storage credential vending should use OpenBao for protected runtime secrets.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: flex-auth.api.iam-profile-to-key-cape
name: flex-auth IAM Profile binding
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: flex-auth.api.needs-iam-profile
provider_capability_id: key-cape.iam-profile.issuer
provider_interface_id: key-cape.iam-profile.oidc-discovery
status: compatible
rationale: key-cape is the lightweight IAM Profile implementation for Railiance workloads.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: flex-auth.api.runtime-secrets-to-openbao
name: flex-auth runtime secrets binding
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: flex-auth.api.needs-runtime-secrets
provider_capability_id: railiance-platform.openbao.runtime-secrets
provider_interface_id: railiance-platform.openbao.kv-v2
status: exact
rationale: flex-auth uses OpenBao KV v2 as the runtime secrets provider.

View File

@@ -0,0 +1,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: flex-auth.api.topaz-runtime-binding
name: flex-auth Topaz runtime binding
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
dependency_id: flex-auth.api.needs-topaz-runtime
provider_capability_id: flex-auth.topaz.authorization-runtime
provider_interface_id: flex-auth.topaz.http-api
status: exact
rationale: flex-auth delegates PDP execution to its Topaz runtime.

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,16 @@
apiVersion: railiance.fabric/v1alpha1
kind: BindingAssertion
metadata:
id: the-custodian.state-hub.postgresql-to-cnpg
name: State Hub PostgreSQL binding
owner: the-custodian
repo: the-custodian
domain: custodian
spec:
lifecycle: active
environments: [all]
dependency_id: the-custodian.state-hub.needs-postgresql
provider_capability_id: railiance-platform.cnpg.postgresql
provider_interface_id: railiance-platform.cnpg.database-connection
status: compatible
rationale: State Hub persists coordination data in PostgreSQL, with CNPG as the Railiance database provider.

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: artifact-store.object-storage.credentials
name: Object-storage credential vending
owner: artifact-store
repo: artifact-store
domain: railiance
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Planned scoped credential vending for object-storage access.
capability_type: object-storage-credential-vending
service_id: artifact-store.storage-service
interface_ids:
- artifact-store.object-storage.sts
criticality: high
data_classification: secret

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: artifact-store.object-storage
name: Object storage
owner: artifact-store
repo: artifact-store
domain: railiance
spec:
lifecycle: planned
environments: [dev, staging, prod]
description: Planned object storage for artifacts and workload data.
capability_type: object-storage
service_id: artifact-store.storage-service
interface_ids:
- artifact-store.object-storage.bucket
criticality: high
data_classification: confidential

View File

@@ -0,0 +1,19 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: flex-auth.api.authorization-decisions
name: flex-auth authorization decisions
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Evaluates Railiance authorization requests and returns decision envelopes.
capability_type: authorization-decision-service
service_id: flex-auth.api
interface_ids:
- flex-auth.api.http-api
- flex-auth.api.policy-package
criticality: critical
data_classification: restricted

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: flex-auth.topaz.authorization-runtime
name: Topaz authorization runtime
owner: flex-auth
repo: flex-auth
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Delegated PDP runtime used for authorization policy evaluation.
capability_type: authorization-decision-service
service_id: flex-auth.topaz
interface_ids:
- flex-auth.topaz.http-api
criticality: critical
data_classification: restricted

View File

@@ -0,0 +1,19 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: key-cape.iam-profile.issuer
name: key-cape IAM Profile issuer
owner: key-cape
repo: key-cape
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Implements IAM Profile claim serving for Railiance workloads.
capability_type: iam-profile-issuer
service_id: key-cape.iam-profile
interface_ids:
- key-cape.iam-profile.http-api
- key-cape.iam-profile.oidc-discovery
criticality: critical
data_classification: restricted

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: net-kingdom.iam-profile.issuer
name: NetKingdom IAM Profile issuer
owner: net-kingdom
repo: net-kingdom
domain: railiance
spec:
lifecycle: active
environments: [all]
description: Defines the IAM Profile identity claims contract for Railiance.
capability_type: iam-profile-issuer
service_id: net-kingdom.iam-profile
interface_ids:
- net-kingdom.iam-profile.oidc-discovery
criticality: critical
data_classification: restricted

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,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-platform.cnpg.postgresql
name: CloudNativePG PostgreSQL
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Provides PostgreSQL databases and connection endpoints.
capability_type: postgresql-database-service
service_id: railiance-platform.cnpg
interface_ids:
- railiance-platform.cnpg.database-connection
criticality: high
data_classification: confidential

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-platform.openbao.runtime-secrets
name: Runtime secrets
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Stores and serves workload runtime secrets through OpenBao.
capability_type: runtime-secrets
service_id: railiance-platform.openbao
interface_ids:
- railiance-platform.openbao.kv-v2
criticality: critical
data_classification: secret

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: railiance-platform.valkey.cache
name: Valkey cache
owner: railiance-platform
repo: railiance-platform
domain: railiance
spec:
lifecycle: active
environments: [dev, staging, prod]
description: Provides Redis-compatible cache storage.
capability_type: redis-compatible-cache
service_id: railiance-platform.valkey
interface_ids:
- railiance-platform.valkey.database-connection
criticality: medium
data_classification: internal

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: repo-scoping.scope-generation
name: Repo scope generation
owner: repo-scoping
repo: repo-scoping
domain: custodian
spec:
lifecycle: active
environments: [all]
description: Generates repo scope, boundary, and usefulness descriptions.
capability_type: scope-generation
service_id: repo-scoping.scope-generator
interface_ids:
- repo-scoping.scope-generator.cli
criticality: medium
data_classification: internal

View File

@@ -0,0 +1,18 @@
apiVersion: railiance.fabric/v1alpha1
kind: CapabilityDeclaration
metadata:
id: the-custodian.state-hub.coordination
name: State Hub coordination read model
owner: the-custodian
repo: the-custodian
domain: custodian
spec:
lifecycle: active
environments: [all]
description: Exposes repo, workstream, task, decision, and progress state for coordination.
capability_type: coordination-read-model
service_id: the-custodian.state-hub
interface_ids:
- the-custodian.state-hub.http-api
criticality: high
data_classification: internal

View File

@@ -0,0 +1,24 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: artifact-store.object-storage.needs-runtime-secrets
name: artifact-store runtime secrets dependency
owner: artifact-store
repo: artifact-store
domain: railiance
spec:
lifecycle: planned
environments: [dev, staging, prod]
consumer_service_id: artifact-store.storage-service
requires:
capability_type: runtime-secrets
interface:
type: openbao-kv-v2-mount
version_constraint: ">=v1 <v2"
auth:
method: kubernetes_service_account
criticality: high
data_classification: secret
fallback:
mode: none
description: Credential vending needs a protected source for signing and backend secrets.

View File

@@ -0,0 +1,27 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: flex-auth.api.needs-iam-profile
name: flex-auth IAM Profile dependency
owner: flex-auth
repo: flex-auth
domain: railiance
source_links:
- label: Seed dependency declaration
path: fabric/README.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: flex-auth.api
requires:
capability_type: iam-profile-issuer
interface:
type: oidc-discovery
version_constraint: ">=v1 <v2"
auth:
method: none
criticality: critical
data_classification: restricted
fallback:
mode: none
description: Authorization decisions require trusted IAM Profile claims.

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: flex-auth.api.needs-runtime-secrets
name: flex-auth runtime secrets dependency
owner: flex-auth
repo: flex-auth
domain: railiance
source_links:
- label: Seed dependency declaration
path: fabric/README.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: flex-auth.api
requires:
capability_type: runtime-secrets
interface:
type: openbao-kv-v2-mount
version_constraint: ">=v1 <v2"
auth:
method: kubernetes_service_account
audience: openbao
criticality: critical
data_classification: secret
fallback:
mode: none
description: flex-auth cannot start without runtime secrets.

View File

@@ -0,0 +1,28 @@
apiVersion: railiance.fabric/v1alpha1
kind: DependencyDeclaration
metadata:
id: flex-auth.api.needs-topaz-runtime
name: flex-auth Topaz runtime dependency
owner: flex-auth
repo: flex-auth
domain: railiance
source_links:
- label: Seed dependency declaration
path: fabric/README.md
spec:
lifecycle: active
environments: [dev, staging, prod]
consumer_service_id: flex-auth.api
requires:
capability_type: authorization-decision-service
capability_id: flex-auth.topaz.authorization-runtime
interface:
type: http-api
version_constraint: ">=v1 <v2"
auth:
method: oidc
criticality: high
data_classification: restricted
fallback:
mode: degraded
description: flex-auth can fall back to limited local policy checks only for non-critical paths.

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.

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