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:
tegwick 2026-08-14 09:28:44 +02:00
parent 54dd45c926
commit 2c2a6073ff
63 changed files with 4662 additions and 69 deletions

View file

@ -0,0 +1,157 @@
{
"schema_version": "0.1",
"record_scope": "operational",
"case_id": "opt:platform-audit-storage:2026-08",
"case_type": "provider_switch",
"trigger": "procurement",
"review_period": "2026-08",
"created_at": "2026-08-14T00:00:00Z",
"resource_ids": [
"resource:platform:audit-storage"
],
"baseline": {
"option_id": "scaleway-standard-multi-az",
"label": "Scaleway Standard Multi-AZ object storage (nl-ams), provisional primary from due diligence",
"one_time_eur": 0,
"recurring_infrastructure_eur_month": 7.35,
"recurring_internal_labor_eur_month": 60,
"recurring_external_labor_eur_month": 0,
"utilization": {
"stored_gb": {
"provisioned": { "value": 457.968, "unit": "GB" },
"used": { "value": 457.968, "unit": "GB" }
}
},
"uncertainty": {
"level": "medium",
"notes": [
"Month-12 base-scenario figures from tools/cost_model.py, not a booked invoice",
"Elastic capacity: provisioned equals used by construction, so the ratio does not signal waste",
"Published list price; no account quote or committed discount"
]
},
"service_constraints": {
"retention_days": { "value": 30, "unit": "days" },
"target_rpo_minutes": { "value": 5, "unit": "minutes" }
},
"failure_domains": [
"provider:scaleway",
"region:nl-ams"
],
"exit_path": "Delete objects and buckets, revoke the scoped access key, close the project, and confirm removal; modelled exit cost EUR 243.83.",
"unknowns": []
},
"alternatives": [
{
"option_id": "hetzner-object-storage",
"label": "Hetzner Object Storage (nbg1), monthly base price including 1 TB storage and egress",
"one_time_eur": 0,
"recurring_infrastructure_eur_month": 6.49,
"recurring_internal_labor_eur_month": 90.0,
"recurring_external_labor_eur_month": 0,
"utilization": {
"stored_gb": {
"provisioned": { "value": 1000, "unit": "GB" },
"used": { "value": 457.968, "unit": "GB" }
}
},
"uncertainty": {
"level": "medium",
"notes": [
"Priced only within the included 1 TB quota; excess storage and egress rates are not published in the recorded source",
"The base scenario stays inside the quota, so the high scenario cannot be evaluated from this option"
]
},
"service_constraints": {
"retention_days": { "value": 30, "unit": "days" },
"target_rpo_minutes": { "value": 5, "unit": "minutes" }
},
"failure_domains": [
"provider:hetzner",
"region:nbg1"
],
"exit_path": "Delete objects and buckets, revoke the S3 credential, cancel the subscription; modelled exit cost EUR 240.00.",
"unknowns": []
},
{
"option_id": "host-europe-cloud-storage",
"label": "Host Europe Cloud Storage, same provider as the reef-railiance compute host",
"one_time_eur": null,
"recurring_infrastructure_eur_month": null,
"recurring_internal_labor_eur_month": 120,
"recurring_external_labor_eur_month": 0,
"utilization": {
"stored_gb": {
"provisioned": { "value": null, "unit": "GB" },
"used": { "value": 457.968, "unit": "GB" }
}
},
"uncertainty": {
"level": "high",
"notes": [
"Only a historical published price and service specification exists; current orderability for this account is unconfirmed",
"Co-located with railiance01, so a provider-level failure would remove the primary host and the backup copy together"
]
},
"service_constraints": {
"retention_days": { "value": 30, "unit": "days" },
"target_rpo_minutes": { "value": 5, "unit": "minutes" }
},
"failure_domains": [
"provider:host-europe"
],
"exit_path": null,
"unknowns": [
"current S3 orderability for this account (owner: human account authority via Host Europe support)",
"storage_eur_per_gb_month, monthly_minimum_eur, egress_eur_per_gb, operations_eur_per_month, support_eur_per_month",
"cancellation terms and minimum contract period",
"correlated-failure acceptance for same-provider placement (owner: human financial and risk authority)"
]
}
],
"decision": {
"state": "blocked_on_evidence",
"recommended_option_id": null,
"rationale": "This case exercises the optimization process against real cost-model output; it is not the procurement decision, which RESOURCE-WP-0002-T03 owns and human financial authority approves. Hetzner computes fully and is EUR 29.14 per month more expensive than the Scaleway baseline at month-12 base demand, driven by operator labour rather than storage price. Host Europe cannot be compared at all: its price, cancellation terms, and current orderability are unknown, and it shares a failure domain with the compute host it is meant to protect. No provider is recommended until Host Europe returns written account evidence.",
"approver": null,
"approved_on": null,
"delegated_to": []
},
"financial_handoff": {
"cost_attribution_key": "platform:audit-storage",
"sent": false,
"reference": null
},
"outcome": {
"feeds_forecast": [
"data/forecasts/platform-audit-storage-scaleway-base-2026-08.json"
],
"actual_refs": []
},
"evidence": [
{
"kind": "forecast",
"ref": "tools/cost_model.py base scenario month 12 over data/demand/platform-audit-storage.json",
"authority": "resource-control",
"observed_at": "2026-08-14"
},
{
"kind": "document",
"ref": "docs/evidence/RESOURCE-WP-0002-provider-due-diligence-2026-08-10.md",
"authority": "resource-control",
"observed_at": "2026-08-10"
},
{
"kind": "document",
"ref": "docs/evidence/RESOURCE-WP-0002-expanded-storage-comparison-2026-08-10.md",
"authority": "resource-control",
"observed_at": "2026-08-10"
},
{
"kind": "workplan",
"ref": "RESOURCE-WP-0002-T03",
"authority": "resource-control",
"observed_at": null
}
]
}

View file

@ -0,0 +1,200 @@
{
"schema_version": "0.1",
"record_scope": "operational",
"case_id": "opt:reef-railiance-k3s:2026-08",
"case_type": "rightsizing",
"trigger": "cadence",
"review_period": "2026-08",
"created_at": "2026-08-14T00:00:00Z",
"resource_ids": [
"resource:railiance:reef-railiance:k3s",
"resource:hosteurope:railiance01"
],
"baseline": {
"option_id": "railiance01-single-node",
"label": "Current single-node k3s on the Host Europe railiance01 server (4 vCPU, 15.62 GiB)",
"one_time_eur": 0,
"recurring_infrastructure_eur_month": null,
"recurring_internal_labor_eur_month": null,
"recurring_external_labor_eur_month": 0,
"utilization": {
"cpu": {
"provisioned": { "value": 4, "unit": "vCPU" },
"used": { "value": 0.564, "unit": "vCPU" }
},
"memory": {
"provisioned": { "value": 15.62, "unit": "GiB" },
"used": { "value": 5.83, "unit": "GiB" }
},
"root_filesystem": {
"provisioned": { "value": 192.69, "unit": "GiB" },
"used": { "value": 66.77, "unit": "GiB" }
}
},
"uncertainty": {
"level": "high",
"notes": [
"Capacity and usage are a single live observation on 2026-08-11, not a utilization history",
"A one-off sample cannot distinguish steady-state headroom from a quiet moment; peak and growth are unknown",
"The server carries Helix Forge, Coulomb Social, rapp-qonto, and shared platform services, so downsizing headroom is shared, not per-workload"
]
},
"service_constraints": {
"nodes": { "value": 1, "unit": "count" },
"pod_limit": { "value": 110, "unit": "count" }
},
"failure_domains": [
"provider:host-europe",
"host:railiance01",
"cluster:reef-railiance"
],
"exit_path": "Provision replacement capacity, restore or redeploy the cluster and stateful services, switch DNS and ingress, verify workloads, then cancel and erase the server.",
"unknowns": [
"railiance01 product, booked monthly price, tax treatment, and renewal or cancellation dates (owner: railiance-infra, RAIL-HO-WP-0008)",
"cluster operations labour hours per month (owner: railiance-cluster, RAIL-BS-WP-0014)",
"requested-versus-used capacity history and peak load (owner: railiance-cluster, RAIL-BS-WP-0014)",
"declared service objectives for the workloads sharing the node (owner: workload repositories)"
]
},
"alternatives": [
{
"option_id": "smaller-single-server",
"label": "Consolidate onto a smaller Host Europe server sized to observed usage plus headroom",
"one_time_eur": null,
"recurring_infrastructure_eur_month": null,
"recurring_internal_labor_eur_month": null,
"recurring_external_labor_eur_month": 0,
"utilization": {
"cpu": {
"provisioned": { "value": null, "unit": "vCPU" },
"used": { "value": 0.564, "unit": "vCPU" }
},
"memory": {
"provisioned": { "value": null, "unit": "GiB" },
"used": { "value": 5.83, "unit": "GiB" }
}
},
"uncertainty": {
"level": "high",
"notes": [
"No target instance can be sized without peak-load history; observed mean usage is not a sizing basis",
"Migration requires a full cluster rebuild and stateful restore, so one-time labour is material and unmeasured",
"Retains the single-host failure domain the baseline already carries"
]
},
"service_constraints": {
"nodes": { "value": 1, "unit": "count" }
},
"failure_domains": [
"provider:host-europe",
"host:railiance01",
"cluster:reef-railiance"
],
"exit_path": null,
"unknowns": [
"Host Europe server catalogue, sizes, and prices available to this account (owner: railiance-infra, RAIL-HO-WP-0008)",
"peak CPU and memory over a full billing period, required to size the target (owner: railiance-cluster, RAIL-BS-WP-0014)",
"one-time migration labour and workload downtime budget (owner: railiance-cluster)"
]
},
{
"option_id": "threephoenix-ha-cluster",
"label": "Three-node HA cluster per RAIL-BS-WP-0007, removing the single-host failure domain",
"one_time_eur": null,
"recurring_infrastructure_eur_month": null,
"recurring_internal_labor_eur_month": null,
"recurring_external_labor_eur_month": 0,
"utilization": {
"cpu": {
"provisioned": { "value": null, "unit": "vCPU" },
"used": { "value": 0.564, "unit": "vCPU" }
},
"memory": {
"provisioned": { "value": null, "unit": "GiB" },
"used": { "value": 5.83, "unit": "GiB" }
}
},
"uncertainty": {
"level": "high",
"notes": [
"This option raises recurring cost by design; it is justified by availability, not by saving, and payback is the wrong test for it",
"Node count and placement are owned by RAIL-BS-WP-0007, not by this case"
]
},
"service_constraints": {
"nodes": { "value": 3, "unit": "count" }
},
"failure_domains": [
"provider:host-europe",
"cluster:reef-railiance"
],
"exit_path": null,
"unknowns": [
"per-node infrastructure price and whether nodes span independent failure domains (owner: railiance-cluster, RAIL-BS-WP-0014)",
"operations labour for a multi-node cluster versus a single node (owner: railiance-cluster)",
"declared availability objective that would justify the added recurring cost (owner: workload repositories)",
"replicated-storage requirement created by removing local-path storage (owner: railiance-cluster)"
]
}
],
"decision": {
"state": "blocked_on_evidence",
"recommended_option_id": null,
"rationale": "Observed utilization is genuinely low: 14 percent of CPU, 37 percent of memory, and 35 percent of the root filesystem on a single sample. That is a real rightsizing signal, and it is not sufficient to act on. No option can be costed because the railiance01 booked price is unknown, so no saving, no payback, and no comparison between downsizing and the HA alternative can be computed. The case stays open and blocked against the named delegated workplans rather than producing a rightsizing recommendation from a mean-usage sample.",
"approver": null,
"approved_on": null,
"delegated_to": [
"railiance-infra",
"railiance-cluster"
]
},
"financial_handoff": {
"cost_attribution_key": null,
"sent": false,
"reference": null
},
"outcome": {
"feeds_forecast": [
"examples/control-cycle/cluster-forecast.json"
],
"actual_refs": []
},
"evidence": [
{
"kind": "telemetry",
"ref": "kubernetes:reef-railiance/node/239.62.205.92.host.secureserver.net@2026-08-11T09:05:25Z",
"authority": "reef-railiance Kubernetes API",
"observed_at": "2026-08-11"
},
{
"kind": "telemetry",
"ref": "ssh:railiance01 host capacity observation 2026-08-11T09:05:25Z",
"authority": "railiance01 operating system",
"observed_at": "2026-08-11"
},
{
"kind": "document",
"ref": "docs/evidence/RESOURCE-WP-0003-initial-portfolio-discovery-2026-08-11.md",
"authority": "resource-control",
"observed_at": "2026-08-11"
},
{
"kind": "workplan",
"ref": "RAIL-HO-WP-0008",
"authority": "railiance-infra",
"observed_at": null
},
{
"kind": "workplan",
"ref": "RAIL-BS-WP-0014",
"authority": "railiance-cluster",
"observed_at": null
},
{
"kind": "workplan",
"ref": "RAIL-BS-WP-0007",
"authority": "railiance-cluster",
"observed_at": null
}
]
}