feat: define accountability root manifest

This commit is contained in:
2026-05-24 03:00:29 +02:00
parent 455362153d
commit a1bd9df8e4
7 changed files with 875 additions and 3 deletions

View File

@@ -0,0 +1,51 @@
# 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
```
## 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.
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.

View File

@@ -42,6 +42,14 @@ 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`.
The financial export must satisfy these invariants:
- every accepted node has resolvable ownership;

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

View File

@@ -0,0 +1,402 @@
$schema: "https://json-schema.org/draft/2020-12/schema"
$id: "https://railiance.local/fabric/schemas/accountability-root-manifest.schema.yaml"
title: "AccountabilityRootManifest"
type: object
additionalProperties: false
required:
- apiVersion
- kind
- metadata
- netkingdom
- actors
- fabrics
- discovery_roots
- refresh
properties:
apiVersion:
type: string
const: "railiance.fabric/v1alpha2"
kind:
type: string
const: AccountabilityRootManifest
metadata:
type: object
additionalProperties: false
required:
- id
- name
properties:
id:
$ref: "#/$defs/stableId"
name:
type: string
minLength: 1
description:
type: string
source_links:
type: array
items:
$ref: "#/$defs/sourceLink"
netkingdom:
$ref: "#/$defs/netkingdom"
actors:
type: array
minItems: 1
items:
$ref: "#/$defs/actor"
fabrics:
type: array
minItems: 1
items:
$ref: "#/$defs/fabric"
discovery_roots:
type: array
minItems: 1
items:
$ref: "#/$defs/discoveryRoot"
refresh:
$ref: "#/$defs/refreshPolicy"
templates:
type: object
additionalProperties: false
properties:
future_subfabric:
$ref: "#/$defs/futureSubfabricTemplate"
$defs:
stableId:
type: string
minLength: 3
maxLength: 180
pattern: "^[A-Za-z0-9][A-Za-z0-9._:/@+-]*$"
pathString:
type: string
minLength: 1
sourceLink:
type: object
additionalProperties: false
required:
- label
properties:
label:
type: string
minLength: 1
path:
type: string
minLength: 1
url:
type: string
minLength: 1
ref:
type: string
minLength: 1
anyOf:
- required: [path]
- required: [url]
- required: [ref]
netkingdom:
type: object
additionalProperties: false
required:
- id
- name
- king_actor_id
properties:
id:
$ref: "#/$defs/stableId"
name:
type: string
minLength: 1
king_actor_id:
$ref: "#/$defs/stableId"
baseline_ref:
$ref: "#/$defs/sourceLink"
actor:
type: object
additionalProperties: false
required:
- id
- role
- name
properties:
id:
$ref: "#/$defs/stableId"
role:
type: string
enum:
- king
- lord
- tenant
- operator
- steward
name:
type: string
minLength: 1
description:
type: string
authority:
type: object
additionalProperties: false
properties:
recovery_authority:
type: boolean
secrets_authority:
type: boolean
backup_authority:
type: boolean
termination_authority:
type: boolean
evidence_refs:
type: array
items:
$ref: "#/$defs/sourceLink"
fabric:
type: object
additionalProperties: false
required:
- id
- kind
- name
- netkingdom_id
- status
- boundary
properties:
id:
$ref: "#/$defs/stableId"
kind:
type: string
enum:
- Fabric
- Subfabric
name:
type: string
minLength: 1
netkingdom_id:
$ref: "#/$defs/stableId"
lord_actor_id:
$ref: "#/$defs/stableId"
tenant_actor_id:
$ref: "#/$defs/stableId"
parent_fabric_id:
oneOf:
- $ref: "#/$defs/stableId"
- type: "null"
status:
type: string
enum:
- active
- planned
- retired
boundary:
type: object
additionalProperties: false
required:
- boundary_type
- criterion
properties:
boundary_type:
type: string
enum:
- fabric
- subfabric
criterion:
type: string
minLength: 1
payment_responsibility:
$ref: "#/$defs/stableId"
operational_responsibility:
$ref: "#/$defs/stableId"
recovery_responsibility:
$ref: "#/$defs/stableId"
evidence_refs:
type: array
items:
$ref: "#/$defs/sourceLink"
allOf:
- if:
properties:
kind:
const: Fabric
then:
required:
- lord_actor_id
- if:
properties:
kind:
const: Subfabric
then:
required:
- parent_fabric_id
- tenant_actor_id
discoveryRoot:
type: object
additionalProperties: false
required:
- id
- type
- status
- fabric_id
- owner_actor_id
- source
- evidence_scope
properties:
id:
$ref: "#/$defs/stableId"
type:
type: string
enum:
- state_hub_repo_inventory
- gitea_organization
- gitea_repository
- registry_manifest
- repository_checkout
- host_path
- deployment_automation
- infrastructure_manifest
- service_config
- endpoint_contract
- backup_recovery
- secret_root
- manual_review_queue
status:
type: string
enum:
- active
- planned
- disabled
fabric_id:
$ref: "#/$defs/stableId"
subfabric_id:
$ref: "#/$defs/stableId"
owner_actor_id:
$ref: "#/$defs/stableId"
source:
type: object
additionalProperties: false
properties:
base_url:
type: string
minLength: 1
url:
type: string
minLength: 1
organization:
type: string
minLength: 1
repo_slug:
type: string
minLength: 1
path:
$ref: "#/$defs/pathString"
remote_url:
type: string
minLength: 1
manifest_path:
$ref: "#/$defs/pathString"
api_paths:
type: array
items:
type: string
minLength: 1
patterns:
type: array
items:
type: string
minLength: 1
safe_discovery:
type: string
enum:
- metadata_only
- local_files
- content_hash
- explicit_review
evidence_scope:
type: array
minItems: 1
uniqueItems: true
items:
type: string
enum:
- repo_inventory
- repository_identity
- local_checkout
- deployment_topology
- service_configuration
- infrastructure
- endpoint_contract
- backup_recovery
- secret_metadata
- fabric_boundary
- tenant_boundary
- accounting_boundary
- manual_review
refresh:
$ref: "#/$defs/refreshPolicy"
evidence_refs:
type: array
items:
$ref: "#/$defs/sourceLink"
notes:
type: string
refreshPolicy:
type: object
additionalProperties: false
required:
- cadence
- triggers
properties:
cadence:
type: string
enum:
- manual
- hourly
- daily
- weekly
- on_change
triggers:
type: array
uniqueItems: true
items:
type: string
enum:
- operator_request
- state_hub_repo_inventory_change
- git_commit
- deployment_manifest_change
- infrastructure_manifest_change
- endpoint_contract_change
- secret_root_change
- backup_recovery_change
- lord_or_tenant_change
- scheduled_rebuild
notes:
type: string
futureSubfabricTemplate:
type: object
additionalProperties: false
required:
- parent_fabric_id
- tenant_actor_role
- required_updates
properties:
parent_fabric_id:
$ref: "#/$defs/stableId"
tenant_actor_role:
type: string
const: tenant
required_updates:
type: array
minItems: 1
items:
type: string
minLength: 1
note:
type: string

View File

@@ -0,0 +1,64 @@
from pathlib import Path
from railiance_fabric.financial_baseline import load_financial_baseline
from railiance_fabric.loader import load_yaml
from railiance_fabric.schema_validation import draft202012_validator
MANIFEST_PATH = Path("fabric/discovery/railiance-accountability-roots.yaml")
EXAMPLE_PATH = Path("examples/discovery/accountability-root-manifest.yaml")
SCHEMA_PATH = Path("schemas/accountability-root-manifest.schema.yaml")
def test_accountability_root_manifests_match_schema() -> None:
validator = draft202012_validator(SCHEMA_PATH)
for path in (MANIFEST_PATH, EXAMPLE_PATH):
manifest = load_yaml(path)
assert list(validator.iter_errors(manifest)) == []
def test_railiance_manifest_matches_financial_baseline() -> None:
manifest = load_yaml(MANIFEST_PATH)
baseline = load_financial_baseline()
assert manifest["netkingdom"]["id"] == baseline["netkingdom"]["id"]
assert manifest["netkingdom"]["king_actor_id"] == baseline["netkingdom"]["king_actor_id"]
baseline_actor_ids = {actor["id"] for actor in baseline["actors"]}
manifest_actor_ids = {actor["id"] for actor in manifest["actors"]}
assert baseline_actor_ids <= manifest_actor_ids
primary_fabric = next(fabric for fabric in manifest["fabrics"] if fabric["id"] == "fabric.railiance.primary")
assert primary_fabric["kind"] == "Fabric"
assert primary_fabric["status"] == "active"
assert primary_fabric["boundary"]["criterion"] == "financial_and_operational_accountability"
def test_railiance_manifest_covers_required_root_kinds() -> None:
manifest = load_yaml(MANIFEST_PATH)
root_types = {root["type"] for root in manifest["discovery_roots"]}
assert {
"state_hub_repo_inventory",
"gitea_organization",
"registry_manifest",
"host_path",
"repository_checkout",
"deployment_automation",
"backup_recovery",
"secret_root",
} <= root_types
assert all(root["fabric_id"] == "fabric.railiance.primary" for root in manifest["discovery_roots"])
assert all(root["source"]["safe_discovery"] for root in manifest["discovery_roots"])
def test_example_manifest_can_add_tenant_subfabric() -> None:
manifest = load_yaml(EXAMPLE_PATH)
subfabrics = [fabric for fabric in manifest["fabrics"] if fabric["kind"] == "Subfabric"]
assert len(subfabrics) == 1
assert subfabrics[0]["parent_fabric_id"] == "fabric.example.primary"
assert subfabrics[0]["tenant_actor_id"] == "actor.example.tenant"
assert any(root.get("subfabric_id") == "subfabric.example.tenant" for root in manifest["discovery_roots"])

View File

@@ -4,7 +4,7 @@ type: workplan
title: "Accountability Root Discovery And Update Loop"
domain: railiance
repo: railiance-fabric
status: ready
status: active
owner: codex
topic_slug: railiance
created: "2026-05-23"
@@ -39,7 +39,7 @@ interfaces, or cross-boundary utility.
```task
id: RAIL-FAB-WP-0018-T01
status: todo
status: done
priority: high
state_hub_task_id: "38ae49fb-ce21-489c-ba67-7f76ab4febc9"
```
@@ -65,6 +65,23 @@ Done when:
- the format can add future tenant subfabrics without changing the top-level
fabric criterion.
Result:
- Added `schemas/accountability-root-manifest.schema.yaml` for
`railiance.fabric/v1alpha2` accountability-root manifests.
- Added `fabric/discovery/railiance-accountability-roots.yaml` to represent
the current Railiance one-fabric baseline, State Hub/Gitea/repo/host roots,
deployment automation roots, and safe metadata-only secret/backup roots.
- Added `examples/discovery/accountability-root-manifest.yaml` to show how a
tenant subfabric can be added without changing the parent fabric criterion.
- Added `docs/accountability-root-manifest.md` and linked the manifest from the
financial Fabric operator guide.
- Added schema/baseline coverage in `tests/test_accountability_roots.py`.
- Verified with `python3 -m pytest tests/test_accountability_roots.py -q`,
`python3 -m railiance_fabric.cli validate .`,
`python3 -m railiance_fabric.cli export --format financial .`, and full
`python3 -m pytest`.
## T02 - Implement Durable Evidence Discovery Adapters
```task
@@ -210,4 +227,3 @@ Done when:
and cross-boundary utility changes.
- Live telemetry remains out of scope.
- The current Railiance baseline can be rebuilt from scratch and exported.