feat: migrate live inventory to five-facet 0.3 and close WP-0006
All seven data/resources records now carry description, decision, reef/secret refs, and potential vs actual consumers. Discovered resources use decision.status: gap. Validators require live inventory to be 0.3. WP-0006 T03 done; workplan finished.
This commit is contained in:
parent
6e57a65360
commit
dafc812daa
11 changed files with 165 additions and 11 deletions
|
|
@ -1,10 +1,27 @@
|
|||
{
|
||||
"schema_version": "0.2",
|
||||
"schema_version": "0.3",
|
||||
"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",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,28 @@
|
|||
{
|
||||
"schema_version": "0.2", "record_scope": "inventory",
|
||||
"schema_version": "0.3", "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"},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
{
|
||||
"schema_version": "0.2", "record_scope": "inventory",
|
||||
"schema_version": "0.3", "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"},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
{
|
||||
"schema_version": "0.2", "record_scope": "inventory",
|
||||
"schema_version": "0.3", "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},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
{
|
||||
"schema_version": "0.2", "record_scope": "inventory",
|
||||
"schema_version": "0.3", "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"},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,39 @@
|
|||
{
|
||||
"schema_version": "0.2", "record_scope": "inventory",
|
||||
"schema_version": "0.3", "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"},
|
||||
|
|
|
|||
|
|
@ -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 the forthcoming inventory v0.3:
|
||||
Five facets, all first-class in inventory v0.3:
|
||||
|
||||
1. **Description** — purpose and class; why this resource exists.
|
||||
2. **Decision** — chosen option, approver, date, rejected alternatives
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
"additionalProperties": false,
|
||||
"required": ["status", "ref"],
|
||||
"properties": {
|
||||
"status": {"enum": ["recommended", "approved", "rejected"]},
|
||||
"status": {"enum": ["recommended", "approved", "rejected", "gap"]},
|
||||
"chosen": {"type": ["string", "null"]},
|
||||
"rejected": {"type": "array", "items": {"type": "string"}},
|
||||
"approved_by": {"type": ["string", "null"]},
|
||||
|
|
|
|||
|
|
@ -75,9 +75,34 @@ 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
|
||||
|
|
|
|||
|
|
@ -50,7 +50,12 @@ def main() -> int:
|
|||
need |= v03
|
||||
assert not need - resource.keys(), f"missing fields: {need - resource.keys()}"
|
||||
validate_record(resource)
|
||||
assert any(resource.get("schema_version") == "0.3" for resource in resources)
|
||||
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
|
||||
)
|
||||
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}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ type: workplan
|
|||
title: "Resource object model and reef operational references"
|
||||
domain: financials
|
||||
repo: resource-control
|
||||
status: active
|
||||
status: finished
|
||||
owner: grok
|
||||
topic_slug: railiance
|
||||
created: "2026-08-14"
|
||||
|
|
@ -101,7 +101,7 @@ the repo does.
|
|||
|
||||
```task
|
||||
id: RESOURCE-WP-0006-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "da959cf1-cbd2-492c-95ff-b9ab78c16697"
|
||||
```
|
||||
|
|
@ -116,6 +116,13 @@ 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue