diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 40d5b24..c800982 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -9,7 +9,7 @@ | Kind | ID | Status | Lane | Source | | --- | --- | --- | --- | --- | | workplan | RESOURCE-WP-0001 | finished | — | workplans/RESOURCE-WP-0001-statehub-bootstrap.md | -| workplan | RESOURCE-WP-0002 | finished | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | +| workplan | RESOURCE-WP-0002 | active | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | | workplan | RESOURCE-WP-0003 | finished | — | workplans/RESOURCE-WP-0003-managed-infrastructure-portfolio-control.md | | workplan | RESOURCE-WP-0004 | finished | — | workplans/RESOURCE-WP-0004-financial-entity-procurement-terms.md | | workplan | RESOURCE-WP-0005 | finished | — | workplans/RESOURCE-WP-0005-resource-procurement-facility.md | @@ -17,8 +17,8 @@ | task | RESOURCE-WP-0001-T01 | done | — | workplans/RESOURCE-WP-0001-statehub-bootstrap.md | | task | RESOURCE-WP-0001-T02 | done | — | workplans/RESOURCE-WP-0001-statehub-bootstrap.md | | task | RESOURCE-WP-0001-T03 | done | — | workplans/RESOURCE-WP-0001-statehub-bootstrap.md | -| task | RESOURCE-WP-0002-T01 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | -| task | RESOURCE-WP-0002-T02 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | +| task | RESOURCE-WP-0002-T01 | progress | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | +| task | RESOURCE-WP-0002-T02 | progress | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | | task | RESOURCE-WP-0002-T03 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | | task | RESOURCE-WP-0002-T04 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | | task | RESOURCE-WP-0002-T05 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | @@ -43,7 +43,7 @@ | task | RESOURCE-WP-0005-T05 | done | — | workplans/RESOURCE-WP-0005-resource-procurement-facility.md | | task | RESOURCE-WP-0005-T06 | done | — | workplans/RESOURCE-WP-0005-resource-procurement-facility.md | | task | RESOURCE-WP-0005-T07 | done | — | workplans/RESOURCE-WP-0005-resource-procurement-facility.md | -| task | RESOURCE-WP-0006-T01 | done | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | -| task | RESOURCE-WP-0006-T02 | done | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | +| task | RESOURCE-WP-0006-T01 | todo | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | +| task | RESOURCE-WP-0006-T02 | progress | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | | task | RESOURCE-WP-0006-T03 | todo | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | -| task | RESOURCE-WP-0006-T04 | done | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | +| task | RESOURCE-WP-0006-T04 | todo | — | workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md | diff --git a/data/resources/apps-pg.json b/data/resources/apps-pg.json index f9a2eca..7f94f9b 100644 --- a/data/resources/apps-pg.json +++ b/data/resources/apps-pg.json @@ -1,27 +1,10 @@ { - "schema_version": "0.3", + "schema_version": "0.2", "record_scope": "inventory", "id": "resource:railiance:apps-pg", "financial_entity_id": null, "procuring_entity_id": "entity:railiance", "entity_gap": "shared allocation; coulomb-social maps to entity:coulomb; vergabe-teilnahme has no financial entity", - "description": "Shared CloudNativePG cluster apps-pg on reef-railiance. Holds isolated consumer databases; not the platform-pg backup target.", - "decision": { - "status": "gap", - "chosen": "Live discovered cluster; no formal procurement decision in this repo", - "rejected": [], - "approved_by": null, - "approved_on": null, - "ref": "docs/evidence/RESOURCE-WP-0003-apps-pg-evidence-foldin-2026-08-14.md" - }, - "operational_refs": [ - "reef:railiance/declarations/reef.yaml" - ], - "credential_handles": [], - "consumers": { - "potential": ["coulomb-social", "vergabe-teilnahme"], - "actual": ["coulomb-social", "vergabe-teilnahme"] - }, "resource_class": "database", "status": "active", "management_model": "self_managed", diff --git a/data/resources/binky-rapp-qonto.json b/data/resources/binky-rapp-qonto.json index cbca9b8..3b34b8a 100644 --- a/data/resources/binky-rapp-qonto.json +++ b/data/resources/binky-rapp-qonto.json @@ -1,28 +1,9 @@ { - "schema_version": "0.3", "record_scope": "inventory", + "schema_version": "0.2", "record_scope": "inventory", "id": "resource:tenant:friendly:binky:rapp-qonto", "financial_entity_id": "entity:binky", "procuring_entity_id": "entity:railiance", "entity_gap": null, - "description": "Binky Qonto assistant on reef-railiance (Knative plus dedicated egress). Railiance procures the runtime; Binky is the financial consumer.", - "decision": { - "status": "gap", - "chosen": "Live discovered tenant workload; no formal procurement decision in this repo", - "rejected": [], - "approved_by": null, - "approved_on": null, - "ref": "/home/worsch/rapp-qonto/docs/security-and-reliability-gates.md" - }, - "operational_refs": [ - "reef:railiance/declarations/reef.yaml" - ], - "credential_handles": [ - "secret:railiance-platform/tenants/binky/qonto-api" - ], - "consumers": { - "potential": ["rapp-qonto"], - "actual": ["rapp-qonto"] - }, "resource_class": "self_managed_service", "status": "active", "management_model": "shared_capacity", "provider": {"name": "Railiance", "account_ref": null, "product_ref": "rail-knative", "provider_resource_id": "knative:rapp-qonto/rapp-qonto"}, diff --git a/data/resources/coulomb-social-production.json b/data/resources/coulomb-social-production.json index c8fc3d6..49b0271 100644 --- a/data/resources/coulomb-social-production.json +++ b/data/resources/coulomb-social-production.json @@ -1,26 +1,9 @@ { - "schema_version": "0.3", "record_scope": "inventory", + "schema_version": "0.2", "record_scope": "inventory", "id": "resource:tenant:coulomb:coulomb-social", "financial_entity_id": "entity:coulomb", "procuring_entity_id": "entity:railiance", "entity_gap": null, - "description": "Coulomb Social production deployment on reef-railiance. Railiance procures the runtime; Coulomb is the financial consumer.", - "decision": { - "status": "gap", - "chosen": "Live discovered tenant workload; no formal procurement decision in this repo", - "rejected": [], - "approved_by": null, - "approved_on": null, - "ref": "/home/worsch/coulomb-social/INTENT.md" - }, - "operational_refs": [ - "reef:railiance/declarations/reef.yaml" - ], - "credential_handles": [], - "consumers": { - "potential": ["coulomb-social"], - "actual": ["coulomb-social"] - }, "resource_class": "self_managed_service", "status": "active", "management_model": "shared_capacity", "provider": {"name": "Railiance", "account_ref": null, "product_ref": "coulomb-social", "provider_resource_id": "kubernetes:coulomb-social/deployment/coulomb-social"}, diff --git a/data/resources/hosteurope-railiance01.json b/data/resources/hosteurope-railiance01.json index cfed39b..5b57d9b 100644 --- a/data/resources/hosteurope-railiance01.json +++ b/data/resources/hosteurope-railiance01.json @@ -1,26 +1,9 @@ { - "schema_version": "0.3", "record_scope": "inventory", + "schema_version": "0.2", "record_scope": "inventory", "id": "resource:hosteurope:railiance01", "financial_entity_id": null, "procuring_entity_id": "entity:railiance", "entity_gap": "no allocation driver; cost remains a Railiance residual", - "description": "Host Europe virtual server railiance01. Capacity substrate for reef-railiance. Product SKU and booked price are still unknown.", - "decision": { - "status": "gap", - "chosen": "Live discovered host; commercial product and contract not yet recorded", - "rejected": [], - "approved_by": null, - "approved_on": null, - "ref": "docs/evidence/RESOURCE-WP-0003-initial-portfolio-discovery-2026-08-11.md" - }, - "operational_refs": [ - "reef:railiance/declarations/reef.yaml" - ], - "credential_handles": [], - "consumers": { - "potential": ["reef-railiance"], - "actual": ["reef-railiance"] - }, "resource_class": "compute_instance", "status": "active", "management_model": "provider_managed", "provider": {"name": "Host Europe", "account_ref": null, "product_ref": null, "provider_resource_id": null}, diff --git a/data/resources/railiance-forgejo.json b/data/resources/railiance-forgejo.json index 5c209d6..5e28f3a 100644 --- a/data/resources/railiance-forgejo.json +++ b/data/resources/railiance-forgejo.json @@ -1,26 +1,9 @@ { - "schema_version": "0.3", "record_scope": "inventory", + "schema_version": "0.2", "record_scope": "inventory", "id": "resource:railiance:forgejo", "financial_entity_id": null, "procuring_entity_id": "entity:railiance", "entity_gap": "no allocation driver; cost remains a Railiance residual", - "description": "Shared Forgejo source and package forge on reef-railiance. Allocation across consuming orgs is not yet modeled.", - "decision": { - "status": "gap", - "chosen": "Live discovered platform service; forge source-of-truth decision lives in railiance-apps", - "rejected": [], - "approved_by": null, - "approved_on": null, - "ref": "/home/worsch/railiance-apps/docs/forge-source-of-truth-decision.md" - }, - "operational_refs": [ - "reef:railiance/declarations/reef.yaml" - ], - "credential_handles": [], - "consumers": { - "potential": ["helix-forge", "coulomb-social", "railiance"], - "actual": ["helix-forge", "coulomb-social", "railiance"] - }, "resource_class": "shared_platform_service", "status": "active", "management_model": "self_managed", "provider": {"name": "Railiance", "account_ref": null, "product_ref": "forgejo-11.0.3", "provider_resource_id": "kubernetes:forgejo/deployment/forgejo-gitea"}, diff --git a/data/resources/reef-railiance-k3s.json b/data/resources/reef-railiance-k3s.json index d1fe492..8b1ea8c 100644 --- a/data/resources/reef-railiance-k3s.json +++ b/data/resources/reef-railiance-k3s.json @@ -1,39 +1,9 @@ { - "schema_version": "0.3", "record_scope": "inventory", + "schema_version": "0.2", "record_scope": "inventory", "id": "resource:railiance:reef-railiance:k3s", "financial_entity_id": null, "procuring_entity_id": "entity:railiance", "entity_gap": "no allocation driver; cost remains a Railiance residual", - "description": "Single-node k3s runtime on railiance01. Cost and consumption view of reef-railiance; not a copy of IPs or kubeconfig.", - "decision": { - "status": "gap", - "chosen": "Live discovered cluster; no formal procurement decision in this repo", - "rejected": [], - "approved_by": null, - "approved_on": null, - "ref": "/home/worsch/railiance-cluster/docs/rail-kubernetes-substrate-profile.md" - }, - "operational_refs": [ - "reef:railiance/declarations/reef.yaml" - ], - "credential_handles": [], - "consumers": { - "potential": [ - "rapp-postgres", - "rapp-qonto", - "rapp-openbao", - "coulomb-social", - "helix-forge", - "railiance-platform" - ], - "actual": [ - "rapp-postgres", - "rapp-qonto", - "coulomb-social", - "helix-forge", - "railiance-platform" - ] - }, "resource_class": "kubernetes_capacity", "status": "active", "management_model": "self_managed", "provider": {"name": "Railiance", "account_ref": null, "product_ref": "k3s", "provider_resource_id": "k3s://239.62.205.92.host.secureserver.net"}, diff --git a/docs/operational-reference-convention.md b/docs/operational-reference-convention.md index 4cba332..c6f8017 100644 --- a/docs/operational-reference-convention.md +++ b/docs/operational-reference-convention.md @@ -104,7 +104,7 @@ Both `ref` and the parsed fields must agree when both are present. ## What a resource-control resource then holds -Five facets, all first-class in inventory v0.3: +Five facets, all first-class in the forthcoming inventory v0.3: 1. **Description** — purpose and class; why this resource exists. 2. **Decision** — chosen option, approver, date, rejected alternatives diff --git a/schemas/resource-inventory.schema.json b/schemas/resource-inventory.schema.json index 421f443..c9a7f11 100644 --- a/schemas/resource-inventory.schema.json +++ b/schemas/resource-inventory.schema.json @@ -30,7 +30,7 @@ "additionalProperties": false, "required": ["status", "ref"], "properties": { - "status": {"enum": ["recommended", "approved", "rejected", "gap"]}, + "status": {"enum": ["recommended", "approved", "rejected"]}, "chosen": {"type": ["string", "null"]}, "rejected": {"type": "array", "items": {"type": "string"}}, "approved_by": {"type": ["string", "null"]}, diff --git a/tests/test_portfolio.py b/tests/test_portfolio.py index 5e8f94a..877033a 100644 --- a/tests/test_portfolio.py +++ b/tests/test_portfolio.py @@ -75,34 +75,9 @@ class PortfolioTest(unittest.TestCase): def test_v02_records_remain_valid(self): v02 = [r for _, r in self.records() if r.get("schema_version") == "0.2"] self.assertGreaterEqual(len(v02), 1) - self.assertTrue(all(r["record_scope"] == "example" for r in v02)) for record in v02: validate_record(record) - def test_live_inventory_is_v03_with_consumers(self): - live = [ - (path, record) - for path, record in self.records() - if record.get("record_scope") == "inventory" - ] - self.assertGreaterEqual(len(live), 7) - for path, record in live: - with self.subTest(path=path): - self.assertEqual(record["schema_version"], "0.3") - for facet in ( - "description", - "decision", - "operational_refs", - "credential_handles", - "consumers", - ): - self.assertIn(facet, record) - consumers = record["consumers"] - self.assertIn("potential", consumers) - self.assertIn("actual", consumers) - self.assertTrue(consumers["potential"]) - validate_record(record) - def test_unknown_commission_date_is_preserved(self): record = deepcopy(next(r for _, r in self.records() if r["status"] == "active")) record["lifecycle"]["commissioned_on"] = None diff --git a/tools/validate.py b/tools/validate.py index 30d5330..f5e2df0 100644 --- a/tools/validate.py +++ b/tools/validate.py @@ -50,12 +50,7 @@ def main() -> int: need |= v03 assert not need - resource.keys(), f"missing fields: {need - resource.keys()}" validate_record(resource) - live = [resource for resource in resources if resource.get("record_scope") == "inventory"] - assert live and all(resource.get("schema_version") == "0.3" for resource in live) - assert all( - "potential" in resource.get("consumers", {}) and "actual" in resource.get("consumers", {}) - for resource in live - ) + assert any(resource.get("schema_version") == "0.3" for resource in resources) operational_records = [load(str(path)) for path in Path("data/control-cycle").glob("*.json")] control_records += operational_records record_ids = {record["record_id"] for record in control_records} diff --git a/workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md b/workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md index 352f78f..82df55f 100644 --- a/workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md +++ b/workplans/RESOURCE-WP-0006-resource-object-and-reef-refs.md @@ -4,7 +4,7 @@ type: workplan title: "Resource object model and reef operational references" domain: financials repo: resource-control -status: finished +status: active owner: grok topic_slug: railiance created: "2026-08-14" @@ -101,7 +101,7 @@ the repo does. ```task id: RESOURCE-WP-0006-T03 -status: done +status: todo priority: high state_hub_task_id: "da959cf1-cbd2-492c-95ff-b9ab78c16697" ``` @@ -116,13 +116,6 @@ flows; attribute refs wait on `reef-storage`; credential handle = Done when no live record relies on undifferentiated `workload_ids` as the only consumer list. -Done 2026-08-15: all seven live inventory records are schema `0.3` with -the five facets. Discovered hosts and workloads use `decision.status: -gap` rather than a fake approval. Backup remains the only `approved` -decision. Consumers are first-class on every record; `workload_ids` is -no longer the only consumer list. Examples stay `0.2`. Formal -procurement write-ups for the six gap records are not this workplan. - ## T04 — Wire WP-0002 to the convention ```task