feat(portfolio): complete RESOURCE-WP-0003 T06 optimization cases and T07 reporting
T06: optimization-case schema, fail-closed evaluator, cadence and decision template. Every option including the baseline must present all ten decision fields; one unknown blocks the comparison. Validated on the storage case (Hetzner computes and loses to Scaleway by EUR 29.14/month on operator labour; Host Europe blocks on four named gaps) and on the non-storage reef-railiance k3s rightsizing case (low utilization is real, but nothing is costable while the railiance01 price is unknown). T07: portfolio report over coverage, lifecycle, utilization, cost, renewals, risks, open cases, and next actions, derived only from committed evidence. Portfolio spend is reported null rather than as a partial sum, unattributed cost is a named list rather than a spread, and unmeasurable resources are reported rather than dropped. RESOURCE-WP-0003 is finished; both cases remain blocked_on_evidence against live delegated records in other repositories. RESOURCE-WP-0002 is untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
54dd45c926
commit
2c2a6073ff
63 changed files with 4662 additions and 69 deletions
43
schemas/monthly-resource-observation.schema.json
Normal file
43
schemas/monthly-resource-observation.schema.json
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://coulomb.social/resource-control/monthly-resource-observation.schema.json",
|
||||
"title": "Monthly resource forecast or technical usage observation",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["schema_version", "record_type", "workload", "cost_attribution_key", "provider_id", "created_at", "rows"],
|
||||
"properties": {
|
||||
"schema_version": {"const": "0.1"},
|
||||
"record_type": {"enum": ["forecast", "usage_observation"]},
|
||||
"workload": {"type": "string"},
|
||||
"cost_attribution_key": {"type": "string"},
|
||||
"provider_id": {"type": "string"},
|
||||
"created_at": {"type": "string", "format": "date-time"},
|
||||
"scenario": {"type": ["string", "null"]},
|
||||
"forecast_ref": {"type": ["string", "null"]},
|
||||
"rows": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["period", "database_gb", "stored_gb", "wal_gb", "restore_egress_gb", "write_requests", "read_requests", "infrastructure_eur", "internal_labor_hours", "internal_labor_eur", "total_eur"],
|
||||
"properties": {
|
||||
"period": {"type": "string", "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$"},
|
||||
"database_gb": {"type": "number", "minimum": 0},
|
||||
"stored_gb": {"type": "number", "minimum": 0},
|
||||
"wal_gb": {"type": "number", "minimum": 0},
|
||||
"restore_egress_gb": {"type": "number", "minimum": 0},
|
||||
"write_requests": {"type": "integer", "minimum": 0},
|
||||
"read_requests": {"type": "integer", "minimum": 0},
|
||||
"infrastructure_eur": {"type": "number", "minimum": 0},
|
||||
"internal_labor_hours": {"type": "number", "minimum": 0},
|
||||
"internal_labor_eur": {"type": "number", "minimum": 0},
|
||||
"total_eur": {"type": "number", "minimum": 0},
|
||||
"backup_success_pct": {"type": ["number", "null"], "minimum": 0, "maximum": 100},
|
||||
"restore_rto_minutes": {"type": ["number", "null"], "minimum": 0},
|
||||
"max_rpo_minutes": {"type": ["number", "null"], "minimum": 0},
|
||||
"evidence": {"type": "array", "items": {"type": "string"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
206
schemas/optimization-case.schema.json
Normal file
206
schemas/optimization-case.schema.json
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://coulomb.social/resource-control/optimization-case.schema.json",
|
||||
"title": "Resource optimization case",
|
||||
"description": "An evidence-backed comparison between a baseline resource arrangement and one or more alternatives. Every option must present the same decision fields; unknown values are null and are reported as blocking evidence gaps rather than assumed.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"record_scope",
|
||||
"case_id",
|
||||
"case_type",
|
||||
"trigger",
|
||||
"review_period",
|
||||
"created_at",
|
||||
"resource_ids",
|
||||
"baseline",
|
||||
"alternatives",
|
||||
"decision",
|
||||
"evidence"
|
||||
],
|
||||
"properties": {
|
||||
"schema_version": { "const": "0.1" },
|
||||
"record_scope": {
|
||||
"description": "operational cases assert real facts; illustrative cases exist only to exercise the mechanism.",
|
||||
"enum": ["operational", "illustrative"]
|
||||
},
|
||||
"case_id": { "type": "string", "pattern": "^opt:[a-z0-9][a-z0-9:._-]+$" },
|
||||
"case_type": {
|
||||
"enum": [
|
||||
"rightsizing",
|
||||
"consolidation",
|
||||
"commitment",
|
||||
"renewal",
|
||||
"migration",
|
||||
"retirement",
|
||||
"provider_switch"
|
||||
]
|
||||
},
|
||||
"trigger": {
|
||||
"enum": ["cadence", "renewal", "variance", "incident", "request", "procurement"]
|
||||
},
|
||||
"review_period": { "type": "string", "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$" },
|
||||
"created_at": { "type": "string", "format": "date-time" },
|
||||
"resource_ids": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": { "type": "string", "pattern": "^resource:" }
|
||||
},
|
||||
"baseline": { "$ref": "#/$defs/option" },
|
||||
"alternatives": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/option" }
|
||||
},
|
||||
"decision": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["state", "recommended_option_id", "rationale", "approver", "approved_on", "delegated_to"],
|
||||
"properties": {
|
||||
"state": {
|
||||
"description": "blocked_on_evidence until every decision field of the compared options is known; proposed once the case computes; then approved or rejected by the named authority.",
|
||||
"enum": ["blocked_on_evidence", "proposed", "approved", "rejected", "superseded"]
|
||||
},
|
||||
"recommended_option_id": { "type": ["string", "null"] },
|
||||
"rationale": { "type": "string", "minLength": 1 },
|
||||
"approver": {
|
||||
"description": "Named human or repository authority. Null while the case is not yet decided.",
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"approved_on": { "type": ["string", "null"], "format": "date" },
|
||||
"delegated_to": {
|
||||
"description": "Repositories that own any approved implementation. resource-control never implements.",
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"financial_handoff": {
|
||||
"description": "What is sent to fin-hub when the case is approved.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["cost_attribution_key", "sent"],
|
||||
"properties": {
|
||||
"cost_attribution_key": { "type": ["string", "null"] },
|
||||
"sent": { "type": "boolean" },
|
||||
"reference": { "type": ["string", "null"] }
|
||||
}
|
||||
},
|
||||
"outcome": {
|
||||
"description": "Closes the loop: which control-cycle records will show whether the case was right.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["feeds_forecast", "actual_refs"],
|
||||
"properties": {
|
||||
"feeds_forecast": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true
|
||||
},
|
||||
"actual_refs": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/evidence_ref" }
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"measurement": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["value", "unit"],
|
||||
"properties": {
|
||||
"value": { "type": ["number", "null"] },
|
||||
"unit": { "type": "string", "minLength": 1 }
|
||||
}
|
||||
},
|
||||
"utilization": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["provisioned", "used"],
|
||||
"properties": {
|
||||
"provisioned": { "$ref": "#/$defs/measurement" },
|
||||
"used": { "$ref": "#/$defs/measurement" }
|
||||
}
|
||||
},
|
||||
"evidence_ref": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["kind", "ref", "authority"],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": ["telemetry", "quote", "contract", "invoice", "forecast", "workplan", "document", "decision"]
|
||||
},
|
||||
"ref": { "type": "string", "minLength": 1 },
|
||||
"authority": { "type": "string", "minLength": 1 },
|
||||
"observed_at": { "type": ["string", "null"], "format": "date" }
|
||||
}
|
||||
},
|
||||
"option": {
|
||||
"description": "Baseline and alternatives carry identical decision fields so they compare on equal terms. A null cost or utilization value means unknown, never zero.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"option_id",
|
||||
"label",
|
||||
"one_time_eur",
|
||||
"recurring_infrastructure_eur_month",
|
||||
"recurring_internal_labor_eur_month",
|
||||
"recurring_external_labor_eur_month",
|
||||
"utilization",
|
||||
"uncertainty",
|
||||
"service_constraints",
|
||||
"failure_domains",
|
||||
"exit_path",
|
||||
"unknowns"
|
||||
],
|
||||
"properties": {
|
||||
"option_id": { "type": "string", "minLength": 1 },
|
||||
"label": { "type": "string", "minLength": 1 },
|
||||
"one_time_eur": { "type": ["number", "null"], "minimum": 0 },
|
||||
"recurring_infrastructure_eur_month": { "type": ["number", "null"], "minimum": 0 },
|
||||
"recurring_internal_labor_eur_month": { "type": ["number", "null"], "minimum": 0 },
|
||||
"recurring_external_labor_eur_month": { "type": ["number", "null"], "minimum": 0 },
|
||||
"utilization": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#/$defs/utilization" }
|
||||
},
|
||||
"uncertainty": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["level", "notes"],
|
||||
"properties": {
|
||||
"level": { "enum": ["low", "medium", "high"] },
|
||||
"notes": { "type": "array", "items": { "type": "string" } }
|
||||
}
|
||||
},
|
||||
"service_constraints": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#/$defs/measurement" }
|
||||
},
|
||||
"failure_domains": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true
|
||||
},
|
||||
"exit_path": { "type": ["string", "null"] },
|
||||
"unknowns": {
|
||||
"description": "Named blocking evidence gaps, each attributable to an owning repository or authority.",
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
schemas/planning-evidence.schema.json
Normal file
101
schemas/planning-evidence.schema.json
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://coulomb.social/resource-control/planning-evidence.schema.json",
|
||||
"title": "Resource-control planning evidence v0.1",
|
||||
"oneOf": [
|
||||
{"$ref": "#/$defs/forecast"},
|
||||
{"$ref": "#/$defs/usage_observation"},
|
||||
{"$ref": "#/$defs/allocation"},
|
||||
{"$ref": "#/$defs/optimization"},
|
||||
{"$ref": "#/$defs/commitment_candidate"}
|
||||
],
|
||||
"$defs": {
|
||||
"money": {"type": "string", "pattern": "^(0|[1-9][0-9]*)\\.[0-9]{2}$"},
|
||||
"common": {
|
||||
"type": "object",
|
||||
"required": ["schema_version", "record_type", "record_id", "resource_id", "period_start", "period_end", "source_evidence", "created_at"],
|
||||
"properties": {
|
||||
"schema_version": {"const": "0.1"},
|
||||
"record_type": {"enum": ["forecast", "usage_observation", "allocation", "optimization", "commitment_candidate"]},
|
||||
"record_id": {"type": "string", "minLength": 1},
|
||||
"revision_of": {"type": ["string", "null"]},
|
||||
"resource_id": {"type": "string", "pattern": "^resource:"},
|
||||
"service_id": {"type": ["string", "null"]},
|
||||
"workload_id": {"type": ["string", "null"]},
|
||||
"tenant_id": {"type": ["string", "null"]},
|
||||
"environment": {"type": ["string", "null"]},
|
||||
"cost_attribution_key": {"type": ["string", "null"]},
|
||||
"period_start": {"type": "string", "format": "date"},
|
||||
"period_end": {"type": "string", "format": "date"},
|
||||
"source_evidence": {"type": "array", "items": {"type": "string"}},
|
||||
"created_at": {"type": "string", "format": "date-time"}
|
||||
}
|
||||
},
|
||||
"cost_breakdown": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["infrastructure", "internal_labor", "external_services", "setup", "other"],
|
||||
"properties": {
|
||||
"infrastructure": {"$ref": "#/$defs/money"},
|
||||
"internal_labor": {"$ref": "#/$defs/money"},
|
||||
"external_services": {"$ref": "#/$defs/money"},
|
||||
"setup": {"$ref": "#/$defs/money"},
|
||||
"other": {"$ref": "#/$defs/money"}
|
||||
}
|
||||
},
|
||||
"forecast": {
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/common"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["currency", "scenario", "forecast_version", "costs", "assumptions"],
|
||||
"properties": {
|
||||
"record_type": {"const": "forecast"},
|
||||
"currency": {"type": "string", "pattern": "^[A-Z]{3}$"},
|
||||
"scenario": {"enum": ["low", "base", "high"]},
|
||||
"forecast_version": {"type": "string", "minLength": 1},
|
||||
"costs": {"$ref": "#/$defs/cost_breakdown"},
|
||||
"uncertainty": {"type": ["string", "null"]},
|
||||
"assumptions": {"type": "array", "items": {"type": "string"}}
|
||||
}
|
||||
}
|
||||
],
|
||||
"unevaluatedProperties": false
|
||||
},
|
||||
"usage_observation": {
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/common"},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["measures"],
|
||||
"properties": {
|
||||
"record_type": {"const": "usage_observation"},
|
||||
"measures": {"type": "array", "items": {"type": "object", "additionalProperties": false, "required": ["name", "value", "unit"], "properties": {"name": {"type": "string"}, "value": {"type": "string"}, "unit": {"type": "string"}}}}
|
||||
}
|
||||
}
|
||||
],
|
||||
"unevaluatedProperties": false
|
||||
},
|
||||
"allocation": {
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/common"},
|
||||
{"type": "object", "required": ["currency", "financial_fact_ids", "method", "allocated_amount", "shares", "residual_share"], "properties": {"record_type": {"const": "allocation"}, "currency": {"type": "string", "pattern": "^[A-Z]{3}$"}, "financial_fact_ids": {"type": "array", "minItems": 1, "items": {"type": "string"}}, "method": {"type": "string"}, "allocated_amount": {"$ref": "#/$defs/money"}, "shares": {"type": "array"}, "residual_share": {"type": "string"}}}
|
||||
],
|
||||
"unevaluatedProperties": false
|
||||
},
|
||||
"optimization": {
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/common"},
|
||||
{"type": "object", "required": ["currency", "baseline", "alternative", "one_time_cost", "expected_period_savings", "assumptions"], "properties": {"record_type": {"const": "optimization"}, "currency": {"type": "string", "pattern": "^[A-Z]{3}$"}, "baseline": {"$ref": "#/$defs/cost_breakdown"}, "alternative": {"$ref": "#/$defs/cost_breakdown"}, "one_time_cost": {"$ref": "#/$defs/money"}, "expected_period_savings": {"$ref": "#/$defs/money"}, "assumptions": {"type": "array", "items": {"type": "string"}}}}
|
||||
],
|
||||
"unevaluatedProperties": false
|
||||
},
|
||||
"commitment_candidate": {
|
||||
"allOf": [
|
||||
{"$ref": "#/$defs/common"},
|
||||
{"type": "object", "required": ["currency", "setup_cost", "recurring_cost", "cadence", "term_start", "approval_status"], "properties": {"record_type": {"const": "commitment_candidate"}, "currency": {"type": "string", "pattern": "^[A-Z]{3}$"}, "setup_cost": {"$ref": "#/$defs/money"}, "recurring_cost": {"$ref": "#/$defs/money"}, "cadence": {"enum": ["monthly", "quarterly", "annual", "one_time"]}, "term_start": {"type": "string", "format": "date"}, "term_end": {"type": ["string", "null"], "format": "date"}, "approval_status": {"const": "candidate"}}}
|
||||
],
|
||||
"unevaluatedProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
85
schemas/resource-control-cycle.schema.json
Normal file
85
schemas/resource-control-cycle.schema.json
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://coulomb.social/resource-control/resource-control-cycle.schema.json",
|
||||
"title": "Immutable resource forecast or actual observation",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["schema_version", "record_id", "record_type", "resource_id", "resource_class", "period", "created_at", "usage_proxies", "capacity", "costs", "allocation", "service_constraints", "evidence"],
|
||||
"properties": {
|
||||
"schema_version": {"const": "0.1"},
|
||||
"record_id": {"type": "string", "minLength": 1},
|
||||
"record_type": {"enum": ["forecast", "actual"]},
|
||||
"resource_id": {"type": "string", "pattern": "^resource:"},
|
||||
"resource_class": {"enum": ["storage", "vm", "cluster_compute", "shared_platform_service", "managed_service", "other"]},
|
||||
"period": {"type": "string", "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$"},
|
||||
"created_at": {"type": "string", "format": "date-time"},
|
||||
"scenario": {"enum": ["low", "base", "high", "observed"]},
|
||||
"forecast_ref": {"type": ["string", "null"]},
|
||||
"revision_of": {"type": ["string", "null"]},
|
||||
"usage_proxies": {
|
||||
"type": "object",
|
||||
"minProperties": 1,
|
||||
"additionalProperties": {"$ref": "#/$defs/measurement"}
|
||||
},
|
||||
"capacity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["model", "provisioned", "used"],
|
||||
"properties": {
|
||||
"model": {"enum": ["fixed", "elastic", "hybrid"]},
|
||||
"provisioned": {"type": "object", "additionalProperties": {"$ref": "#/$defs/measurement"}},
|
||||
"used": {"type": "object", "additionalProperties": {"$ref": "#/$defs/measurement"}}
|
||||
}
|
||||
},
|
||||
"costs": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["currency", "infrastructure", "internal_labor", "external_labor", "total"],
|
||||
"properties": {
|
||||
"currency": {"const": "EUR"},
|
||||
"infrastructure": {"type": "number", "minimum": 0},
|
||||
"internal_labor": {"type": "number", "minimum": 0},
|
||||
"external_labor": {"type": "number", "minimum": 0},
|
||||
"total": {"type": "number", "minimum": 0},
|
||||
"booked_cost_refs": {"type": "array", "items": {"type": "string"}, "uniqueItems": true}
|
||||
}
|
||||
},
|
||||
"allocation": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["method", "driver", "method_version", "unattributed_eur"],
|
||||
"properties": {
|
||||
"method": {"type": "string", "minLength": 1},
|
||||
"driver": {"type": "string", "minLength": 1},
|
||||
"method_version": {"type": "string", "minLength": 1},
|
||||
"unattributed_eur": {"type": "number", "minimum": 0}
|
||||
}
|
||||
},
|
||||
"service_constraints": {"type": "object", "additionalProperties": {"$ref": "#/$defs/measurement"}},
|
||||
"uncertainty": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["level", "notes"],
|
||||
"properties": {
|
||||
"level": {"enum": ["low", "medium", "high"]},
|
||||
"notes": {"type": "array", "items": {"type": "string"}}
|
||||
}
|
||||
},
|
||||
"variance_attribution": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"enum": ["demand", "provider_price", "allocation", "labor", "model", "data_quality"]}
|
||||
},
|
||||
"evidence": {"type": "array", "minItems": 1, "items": {"type": "string"}}
|
||||
},
|
||||
"$defs": {
|
||||
"measurement": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["value", "unit"],
|
||||
"properties": {
|
||||
"value": {"type": "number", "minimum": 0},
|
||||
"unit": {"type": "string", "minLength": 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
schemas/resource-inventory.schema.json
Normal file
136
schemas/resource-inventory.schema.json
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://coulomb.social/resource-control/resource-inventory.schema.json",
|
||||
"title": "Railiance managed-infrastructure portfolio resource v0.2",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["schema_version", "record_scope", "id", "resource_class", "status", "management_model", "provider", "service", "location", "capacity", "ownership", "cost", "lifecycle", "relationships", "requirements", "evidence"],
|
||||
"properties": {
|
||||
"schema_version": {"const": "0.2"},
|
||||
"record_scope": {"enum": ["inventory", "example"]},
|
||||
"id": {"type": "string", "pattern": "^resource:[a-z0-9][a-z0-9:_-]+$"},
|
||||
"resource_class": {"enum": ["compute_instance", "storage", "network", "kubernetes_capacity", "database", "managed_service", "self_managed_service", "shared_platform_service", "license"]},
|
||||
"status": {"enum": ["proposed", "ordered", "commissioning", "active", "suspended", "retiring", "retired", "rejected"]},
|
||||
"management_model": {"enum": ["provider_managed", "self_managed", "shared_capacity"]},
|
||||
"provider": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["name", "account_ref", "product_ref", "provider_resource_id"],
|
||||
"properties": {
|
||||
"name": {"type": "string", "minLength": 1},
|
||||
"account_ref": {"type": ["string", "null"]},
|
||||
"product_ref": {"type": ["string", "null"]},
|
||||
"provider_resource_id": {"type": ["string", "null"]}
|
||||
}
|
||||
},
|
||||
"service": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["name", "service_id", "class", "capacity_model"],
|
||||
"properties": {
|
||||
"name": {"type": "string", "minLength": 1},
|
||||
"service_id": {"type": ["string", "null"]},
|
||||
"class": {"type": "string", "minLength": 1},
|
||||
"capacity_model": {"enum": ["elastic", "fixed", "shared", "licensed", "unknown"]}
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["region", "country", "failure_domains", "residency"],
|
||||
"properties": {
|
||||
"region": {"type": ["string", "null"]},
|
||||
"country": {"type": ["string", "null"], "pattern": "^[A-Z]{2}$"},
|
||||
"failure_domains": {"type": "array", "items": {"type": "string"}},
|
||||
"residency": {"type": ["string", "null"]}
|
||||
}
|
||||
},
|
||||
"capacity": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["metric", "value", "unit", "kind", "observed_at"],
|
||||
"properties": {
|
||||
"metric": {"type": "string", "minLength": 1},
|
||||
"value": {"type": ["number", "null"], "minimum": 0},
|
||||
"unit": {"type": "string", "minLength": 1},
|
||||
"kind": {"enum": ["provisioned", "usable", "limit", "allocated", "observed", "unknown"]},
|
||||
"observed_at": {"type": ["string", "null"], "format": "date"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ownership": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["owner", "environment", "workload_ids", "tenant_id", "allocation"],
|
||||
"properties": {
|
||||
"owner": {"type": "string", "minLength": 1},
|
||||
"environment": {"type": "string", "minLength": 1},
|
||||
"workload_ids": {"type": "array", "items": {"type": "string"}},
|
||||
"tenant_id": {"type": ["string", "null"]},
|
||||
"allocation": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["mode", "cost_attribution_key", "driver", "method_version"],
|
||||
"properties": {
|
||||
"mode": {"enum": ["dedicated", "shared", "unattributed"]},
|
||||
"cost_attribution_key": {"type": ["string", "null"]},
|
||||
"driver": {"type": ["string", "null"]},
|
||||
"method_version": {"type": ["string", "null"]}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cost": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["currency", "tax_status", "billing_model", "commitment_ref", "price_evidence"],
|
||||
"properties": {
|
||||
"currency": {"type": ["string", "null"], "pattern": "^[A-Z]{3}$"},
|
||||
"tax_status": {"enum": ["included", "excluded", "unknown", "not_applicable"]},
|
||||
"billing_model": {"type": "string", "minLength": 1},
|
||||
"commitment_ref": {"type": ["string", "null"]},
|
||||
"price_evidence": {"type": ["string", "null"]}
|
||||
}
|
||||
},
|
||||
"lifecycle": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["proposed_on", "ordered_on", "commissioned_on", "renews_on", "cancel_by", "retired_on", "exit_path"],
|
||||
"properties": {
|
||||
"proposed_on": {"type": ["string", "null"], "format": "date"},
|
||||
"ordered_on": {"type": ["string", "null"], "format": "date"},
|
||||
"commissioned_on": {"type": ["string", "null"], "format": "date"},
|
||||
"renews_on": {"type": ["string", "null"], "format": "date"},
|
||||
"cancel_by": {"type": ["string", "null"], "format": "date"},
|
||||
"retired_on": {"type": ["string", "null"], "format": "date"},
|
||||
"exit_path": {"type": "string", "minLength": 1}
|
||||
}
|
||||
},
|
||||
"relationships": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["type", "resource_id"],
|
||||
"properties": {
|
||||
"type": {"enum": ["depends_on", "hosted_on", "part_of", "provides_capacity_to", "replaces", "backed_up_to"]},
|
||||
"resource_id": {"type": "string", "pattern": "^resource:"}
|
||||
}
|
||||
}
|
||||
},
|
||||
"requirements": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["kind", "ref"],
|
||||
"properties": {"kind": {"enum": ["service_objective", "security", "residency", "recovery", "retention", "performance", "other"]}, "ref": {"type": "string", "minLength": 1}}
|
||||
}
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object", "additionalProperties": false,
|
||||
"required": ["kind", "ref", "observed_at", "authority"],
|
||||
"properties": {
|
||||
"kind": {"enum": ["provider", "contract", "telemetry", "workload", "decision", "test", "example"]},
|
||||
"ref": {"type": "string", "minLength": 1},
|
||||
"observed_at": {"type": ["string", "null"], "format": "date"},
|
||||
"authority": {"type": "string", "minLength": 1}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue