resource-control/tools/validate.py

167 lines
9.3 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Dependency-free validation for resource-control JSON declarations."""
import json
from pathlib import Path
from entities import REQUIRED_ENTITY_IDS, load_register, load_terms, require_entity, validate_register, validate_terms
from optimization import validate_case
from portfolio import validate_record
from portfolio_report import build as build_portfolio_report
feat: restate the backup case in ITC-CAP terms; add evidence basis; publish consumption-mode signal Three things. 1. CANON RESTATEMENT (info-tech-canon's ask after accepting our demand) data/capability/platform-audit-storage.json restates the backup case against ITC-CAP 0.2.0: requirement with profile, targets and the failure-domain constraint that decided the procurement; two provisions (data.object and data.backup); all four data.backup evidence hooks satisfied and measured; and consumption in native units — GB, hours, tokens — with unknown never zero. tools/capability.py reads their capabilities.yaml directly rather than copying it, so drift in either repo fails here. The requirement asks D5, the provision is D4, and the review reports below_requirement rather than inflating maturity. 2. EVIDENCE BASIS (tools/basis.py, docs/evidence-basis.md) Every value declares how it was obtained on an ordered scale: invoiced, measured, quoted, derived, projected, estimated, assumed, unknown. A derived value resolves to the weakest basis among its inputs, so precise arithmetic cannot launder weak assumptions. First application is a finding about our own biggest decision: the Scaleway vs Hetzner comparison, EUR 29.14/month stated to the cent, grades "indicative" — 1 of 4 load-bearing values evidenced, weakest "assumed". The direction is robust; the magnitude is a model output. The cheapest fix is recording real operator hours, not better arithmetic. 3. CONSUMPTION-MODE SIGNAL (railiance-platform RAILIANCE-WP-0017) settlement.py gains a consumption-mode command projecting statements into the signal they consume; make consumption-mode PERIOD=YYYY-MM publishes data/consumption-mode/current.json. Currently an empty list: no live charges for 2026-09, so no entity is restricted. Publishing the empty list makes that an assertion rather than an absence, which their contract distinguishes. The validator fails if the published signal is stale. 185 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 18:42:06 +02:00
from capability import load_canon, review as review_capability
from settlement import close_fixture, close_live, consumption_mode_signal
def load(path: str) -> dict:
return json.loads(Path(path).read_text())
def main() -> int:
demand = load("data/demand/platform-audit-storage.json")
providers = load("data/providers/object-storage.json")
schema = load("schemas/resource-inventory.schema.json")
observation_schema = load("schemas/monthly-resource-observation.schema.json")
planning_schema = load("schemas/planning-evidence.schema.json")
control_schema = load("schemas/resource-control-cycle.schema.json")
forecasts = [load(str(path)) for path in Path("data/forecasts").glob("*.json")]
resource_paths = list(Path("data/resources").glob("*.json"))
resource_paths += list(Path("examples/portfolio").glob("*.json"))
resources = [load(str(path)) for path in resource_paths]
control_records = [load(str(path)) for path in Path("examples/control-cycle").glob("*.json")]
assert demand["schema_version"] == providers["schema_version"] == "0.1"
assert demand["retention_days"] >= 30
assert set(demand["scenarios"]) == {"low", "base", "high"}
assert len({p["id"] for p in providers["providers"]}) == len(providers["providers"])
assert {"Host Europe", "Scaleway", "Hetzner", "AWS", "Microsoft Azure", "Google Cloud", "STACKIT"} <= {p["provider"] for p in providers["providers"]}
assert schema["$schema"].endswith("2020-12/schema")
assert observation_schema["$schema"].endswith("2020-12/schema")
assert planning_schema["$schema"].endswith("2020-12/schema")
assert control_schema["$schema"].endswith("2020-12/schema")
assert len(planning_schema["oneOf"]) == 5
for forecast in forecasts:
assert forecast["record_type"] == "forecast"
assert len({row["period"] for row in forecast["rows"]}) == len(forecast["rows"])
assert all(row["total_eur"] == round(row["infrastructure_eur"] + row["internal_labor_eur"], 2) for row in forecast["rows"])
assert set(schema["properties"]["schema_version"]["enum"]) == {"0.2", "0.3"}
required = set(schema["required"])
v03 = {"description", "decision", "operational_refs", "credential_handles", "consumers"}
for resource in resources:
need = set(required)
if resource.get("schema_version") == "0.3":
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
)
2026-08-14 09:36:57 +02:00
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}
assert len(record_ids) == len(control_records)
2026-08-14 09:36:57 +02:00
assert {record["resource_class"] for record in control_records} >= {"storage", "cluster_compute", "shared_platform_service"}
for record in control_records:
2026-08-14 09:36:57 +02:00
assert record["schema_version"] in {"0.1", "0.2"}
assert record["resource_id"].startswith("resource:")
costs = record["costs"]
2026-08-14 09:36:57 +02:00
components = [costs["infrastructure"], costs["internal_labor"], costs["external_labor"]]
if any(component is None for component in components):
# An unknown component makes the total unknown; it is never the sum
# of the parts that happen to be known.
assert record["schema_version"] == "0.2", "null costs require schema 0.2"
assert costs["total"] is None
else:
assert costs["total"] == round(sum(components), 2)
if record["record_type"] == "actual":
assert record["forecast_ref"] in record_ids
2026-08-14 09:36:57 +02:00
# Operational records assert real facts and must cite the authoritative
# repository evidence they came from.
for record in operational_records:
assert record["evidence"], f"{record['record_id']} cites no evidence"
assert record["uncertainty"]["notes"], f"{record['record_id']} states no uncertainty"
case_schema = load("schemas/optimization-case.schema.json")
assert case_schema["$schema"].endswith("2020-12/schema")
assert case_schema["properties"]["schema_version"]["const"] == "0.1"
cases = [load(str(path)) for path in Path("data/optimization").glob("*.json")]
assert len({case["case_id"] for case in cases}) == len(cases)
for case in cases:
assert not set(case_schema["required"]) - case.keys()
validate_case(case)
# The optimization process must be validated on the backup case and on at
# least one non-storage portfolio candidate (RESOURCE-WP-0003-T06).
case_resources = {rid for case in cases for rid in case["resource_ids"]}
assert "resource:platform:audit-storage" in case_resources
assert case_resources - {"resource:platform:audit-storage"}
report = build_portfolio_report(Path("."))
assert report["resource_count"] == len(resource_paths) - len(list(Path("examples/portfolio").glob("*.json")))
assert report["cost"]["known_monthly_spend_eur"] is None
assert report["next_actions"]
register_payload = load("data/entities/register.json")
terms_payload = load("data/terms/procurement-v0.1.json")
entities = validate_register(register_payload)
terms = validate_terms(terms_payload)
_, loaded_entities = load_register(Path("."))
assert loaded_entities.keys() == entities.keys()
assert list(entities) == list(REQUIRED_ENTITY_IDS) or set(entities) == set(REQUIRED_ENTITY_IDS)
assert terms["markup_rate"] == load_terms(Path("."))["markup_rate"]
try:
require_entity("entity:unknown")
raise AssertionError("unknown entity id must be rejected")
except ValueError as exc:
assert "unknown entity id" in str(exc)
entity_ids = {row["financial_entity_id"] for row in report["entities"]["entities"]}
assert entity_ids == set(REQUIRED_ENTITY_IDS)
assert report["entities"]["known_monthly_spend_eur"] is None
assert report["entities"]["unattributed_resources"]
live_statements = close_live(Path("."), "2026-08")
assert live_statements == []
fixture_dir = Path("examples/settlement")
ordinary = close_fixture(load(str(fixture_dir / "15.1-ordinary.json")), terms, entities)
assert len(ordinary) == 1
assert ordinary[0]["known_transfer_price_eur"] == "240.00"
planning = load("examples/planning/entity-forecast-transfer.json")
assert planning["transfer_price"] == "240.00"
assert planning["credit_headroom"] == "760.00"
assert planning["financial_entity_id"] == "entity:coulomb"
reef_view_schema = load("schemas/reef-view.schema.json")
assert reef_view_schema["$schema"].endswith("2020-12/schema")
inventory_ids = {resource["id"] for resource in resources if resource.get("record_scope") == "inventory"}
for path in Path("data/reefs").glob("*.json"):
view = load(str(path))
assert view["schema_version"] == "0.1"
assert view["declaration_ref"].startswith("reef:")
missing = [row["resource_id"] for row in view["resources"] if row["resource_id"] not in inventory_ids]
assert not missing, f"{path} cites unknown resources: {missing}"
if view["reef_id"] == "reef-railiance":
assert view["role"] == "compute_substrate"
assert any("reef-storage" in note for note in view.get("notes") or [])
if view["reef_id"] == "reef-storage":
assert view["role"] == "storage_substrate"
feat: restate the backup case in ITC-CAP terms; add evidence basis; publish consumption-mode signal Three things. 1. CANON RESTATEMENT (info-tech-canon's ask after accepting our demand) data/capability/platform-audit-storage.json restates the backup case against ITC-CAP 0.2.0: requirement with profile, targets and the failure-domain constraint that decided the procurement; two provisions (data.object and data.backup); all four data.backup evidence hooks satisfied and measured; and consumption in native units — GB, hours, tokens — with unknown never zero. tools/capability.py reads their capabilities.yaml directly rather than copying it, so drift in either repo fails here. The requirement asks D5, the provision is D4, and the review reports below_requirement rather than inflating maturity. 2. EVIDENCE BASIS (tools/basis.py, docs/evidence-basis.md) Every value declares how it was obtained on an ordered scale: invoiced, measured, quoted, derived, projected, estimated, assumed, unknown. A derived value resolves to the weakest basis among its inputs, so precise arithmetic cannot launder weak assumptions. First application is a finding about our own biggest decision: the Scaleway vs Hetzner comparison, EUR 29.14/month stated to the cent, grades "indicative" — 1 of 4 load-bearing values evidenced, weakest "assumed". The direction is robust; the magnitude is a model output. The cheapest fix is recording real operator hours, not better arithmetic. 3. CONSUMPTION-MODE SIGNAL (railiance-platform RAILIANCE-WP-0017) settlement.py gains a consumption-mode command projecting statements into the signal they consume; make consumption-mode PERIOD=YYYY-MM publishes data/consumption-mode/current.json. Currently an empty list: no live charges for 2026-09, so no entity is restricted. Publishing the empty list makes that an assertion rather than an absence, which their contract distinguishes. The validator fails if the published signal is stale. 185 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 18:42:06 +02:00
# Capability restatements bind to the live ITC-CAP catalog rather than a
# copy of it, so drift in either repository fails here.
canon = load_canon()
capability_records = [load(str(p)) for p in Path("data/capability").glob("*.json")]
assert capability_records, "no capability restatement present"
for record in capability_records:
report = review_capability(record, canon)
assert report["provisions"], f"{record['record_id']} declares no provision"
for provision in report["provisions"]:
# Unknown consumption must be named, never silently absent.
assert provision["consumption"]["count"] > 0
backup = next(
p for r in capability_records for p in review_capability(r, canon)["provisions"]
if p["capability"] == "data.backup"
)
assert backup["evidence"]["complete"], "the backup provision must satisfy every declared hook"
signal = consumption_mode_signal(close_live(Path("."), "2026-09"), "2026-09")
published = load("data/consumption-mode/current.json")
assert published == signal, "consumption-mode signal is stale; run make consumption-mode"
print("resource-control declarations: valid")
return 0
if __name__ == "__main__":
raise SystemExit(main())