diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 588a9be..c800982 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -23,7 +23,7 @@ | 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 | | task | RESOURCE-WP-0002-T06 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | -| task | RESOURCE-WP-0002-T07 | todo | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | +| task | RESOURCE-WP-0002-T07 | done | — | workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md | | task | RESOURCE-WP-0003-T01 | done | — | workplans/RESOURCE-WP-0003-managed-infrastructure-portfolio-control.md | | task | RESOURCE-WP-0003-T02 | done | — | workplans/RESOURCE-WP-0003-managed-infrastructure-portfolio-control.md | | task | RESOURCE-WP-0003-T03 | done | — | workplans/RESOURCE-WP-0003-managed-infrastructure-portfolio-control.md | diff --git a/data/providers/object-storage.json b/data/providers/object-storage.json index 68a9ebb..5a639e5 100644 --- a/data/providers/object-storage.json +++ b/data/providers/object-storage.json @@ -2,7 +2,11 @@ "schema_version": "0.1", "observed_at": "2026-08-10", "prices_exclude_vat": true, - "fx": {"usd_per_eur": 1.1555, "observed_at": "2026-08-10", "source": "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"}, + "fx": { + "usd_per_eur": 1.1555, + "observed_at": "2026-08-10", + "source": "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml" + }, "providers": [ { "id": "host-europe-cloud-storage", @@ -17,8 +21,9 @@ "operations_eur_per_month": null, "support_eur_per_month": null, "operator_hours_per_month": 2, - "status": "blocked-account-confirmation", - "source": "https://www.hosteurope.de/download/PVL/Preis_und_Leistungsverzeichnis_CloudStorage_1-0-1.pdf" + "status": "not-offered", + "source": "account holder, 2026-08-15; superseding https://www.hosteurope.de/download/PVL/Preis_und_Leistungsverzeichnis_CloudStorage_1-0-1.pdf", + "status_evidence": "Account-holder statement 2026-08-15: Host Europe does not offer a fully managed S3 service, and offers no API to provision storage. The 2020 Cloud Storage price and service specification does not describe a currently orderable product. This is the account holder's knowledge, not vendor-written confirmation; it is recorded as a blocking answer rather than as a verified vendor term." }, { "id": "scaleway-standard-multi-az", @@ -53,34 +58,188 @@ "source": "https://www.hetzner.com/storage/object-storage/" }, { - "id": "host-europe-garage-1", "provider": "Host Europe", "service_class": "Self-managed Garage, 1 VM", "region": "Germany", "storage_eur_per_gb_month": null, "monthly_minimum_eur": 31.92, "included_storage_gb": 400, "included_egress_gb": 100000, "egress_eur_per_gb": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 2, "setup_operator_hours": 8, "topology": "1 x 8 vCPU / 16 GB / 400 GB NVMe; replication factor 1; no redundancy", "status": "estimate-not-production", "source": "https://www.hosteurope.de/Server/Virtual-Server/" + "id": "host-europe-garage-1", + "provider": "Host Europe", + "service_class": "Self-managed Garage, 1 VM", + "region": "Germany", + "storage_eur_per_gb_month": null, + "monthly_minimum_eur": 31.92, + "included_storage_gb": 400, + "included_egress_gb": 100000, + "egress_eur_per_gb": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 2, + "setup_operator_hours": 8, + "topology": "1 x 8 vCPU / 16 GB / 400 GB NVMe; replication factor 1; no redundancy", + "status": "estimate-not-production", + "source": "https://www.hosteurope.de/Server/Virtual-Server/" }, { - "id": "host-europe-garage-2", "provider": "Host Europe", "service_class": "Self-managed Garage, 2 VMs", "region": "Germany", "storage_eur_per_gb_month": null, "monthly_minimum_eur": 63.85, "included_storage_gb": 400, "included_egress_gb": 100000, "egress_eur_per_gb": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 3, "setup_operator_hours": 12, "topology": "2 x 8 vCPU / 16 GB / 400 GB NVMe; replication factor 2; one provider/location", "status": "estimate-degraded-quorum", "source": "https://www.hosteurope.de/Server/Virtual-Server/" + "id": "host-europe-garage-2", + "provider": "Host Europe", + "service_class": "Self-managed Garage, 2 VMs", + "region": "Germany", + "storage_eur_per_gb_month": null, + "monthly_minimum_eur": 63.85, + "included_storage_gb": 400, + "included_egress_gb": 100000, + "egress_eur_per_gb": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 3, + "setup_operator_hours": 12, + "topology": "2 x 8 vCPU / 16 GB / 400 GB NVMe; replication factor 2; one provider/location", + "status": "estimate-degraded-quorum", + "source": "https://www.hosteurope.de/Server/Virtual-Server/" }, { - "id": "host-europe-garage-3", "provider": "Host Europe", "service_class": "Self-managed Garage, 3 VMs", "region": "Germany", "storage_eur_per_gb_month": null, "monthly_minimum_eur": 95.77, "included_storage_gb": 400, "included_egress_gb": 100000, "egress_eur_per_gb": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 4, "setup_operator_hours": 16, "topology": "3 x 8 vCPU / 16 GB / 400 GB NVMe; replication factor 3; one provider/location", "status": "estimate-production-candidate", "source": "https://www.hosteurope.de/Server/Virtual-Server/" + "id": "host-europe-garage-3", + "provider": "Host Europe", + "service_class": "Self-managed Garage, 3 VMs", + "region": "Germany", + "storage_eur_per_gb_month": null, + "monthly_minimum_eur": 95.77, + "included_storage_gb": 400, + "included_egress_gb": 100000, + "egress_eur_per_gb": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 4, + "setup_operator_hours": 16, + "topology": "3 x 8 vCPU / 16 GB / 400 GB NVMe; replication factor 3; one provider/location", + "status": "estimate-production-candidate", + "source": "https://www.hosteurope.de/Server/Virtual-Server/" }, { - "id": "hetzner-garage-1", "provider": "Hetzner", "service_class": "Self-managed Garage, 1 VM", "region": "nbg1", "storage_eur_per_gb_month": null, "monthly_minimum_eur": 30.09, "included_storage_gb": 320, "included_egress_gb": 20000, "egress_eur_per_gb": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 2, "setup_operator_hours": 8, "topology": "1 x CX53 / 16 vCPU / 32 GB / 320 GB local SSD plus IPv4; replication factor 1", "status": "estimate-not-production", "source": "https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/" + "id": "hetzner-garage-1", + "provider": "Hetzner", + "service_class": "Self-managed Garage, 1 VM", + "region": "nbg1", + "storage_eur_per_gb_month": null, + "monthly_minimum_eur": 30.09, + "included_storage_gb": 320, + "included_egress_gb": 20000, + "egress_eur_per_gb": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 2, + "setup_operator_hours": 8, + "topology": "1 x CX53 / 16 vCPU / 32 GB / 320 GB local SSD plus IPv4; replication factor 1", + "status": "estimate-not-production", + "source": "https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/" }, { - "id": "hetzner-garage-2", "provider": "Hetzner", "service_class": "Self-managed Garage, 2 VMs", "region": "nbg1", "storage_eur_per_gb_month": null, "monthly_minimum_eur": 60.18, "included_storage_gb": 320, "included_egress_gb": 20000, "egress_eur_per_gb": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 3, "setup_operator_hours": 12, "topology": "2 x CX53 / 16 vCPU / 32 GB / 320 GB local SSD plus IPv4; replication factor 2", "status": "estimate-degraded-quorum", "source": "https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/" + "id": "hetzner-garage-2", + "provider": "Hetzner", + "service_class": "Self-managed Garage, 2 VMs", + "region": "nbg1", + "storage_eur_per_gb_month": null, + "monthly_minimum_eur": 60.18, + "included_storage_gb": 320, + "included_egress_gb": 20000, + "egress_eur_per_gb": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 3, + "setup_operator_hours": 12, + "topology": "2 x CX53 / 16 vCPU / 32 GB / 320 GB local SSD plus IPv4; replication factor 2", + "status": "estimate-degraded-quorum", + "source": "https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/" }, { - "id": "hetzner-garage-3", "provider": "Hetzner", "service_class": "Self-managed Garage, 3 VMs", "region": "nbg1", "storage_eur_per_gb_month": null, "monthly_minimum_eur": 90.27, "included_storage_gb": 320, "included_egress_gb": 20000, "egress_eur_per_gb": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 4, "setup_operator_hours": 16, "topology": "3 x CX53 / 16 vCPU / 32 GB / 320 GB local SSD plus IPv4; replication factor 3 in one location", "status": "estimate-production-candidate", "source": "https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/" + "id": "hetzner-garage-3", + "provider": "Hetzner", + "service_class": "Self-managed Garage, 3 VMs", + "region": "nbg1", + "storage_eur_per_gb_month": null, + "monthly_minimum_eur": 90.27, + "included_storage_gb": 320, + "included_egress_gb": 20000, + "egress_eur_per_gb": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 4, + "setup_operator_hours": 16, + "topology": "3 x CX53 / 16 vCPU / 32 GB / 320 GB local SSD plus IPv4; replication factor 3 in one location", + "status": "estimate-production-candidate", + "source": "https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/" }, { - "id": "aws-s3-standard", "provider": "AWS", "service_class": "S3 Standard", "region": "eu-central-1", "storage_eur_per_gb_month": 0.02120, "monthly_minimum_eur": 0, "included_storage_gb": 0, "included_egress_gb": 100, "egress_eur_per_gb": 0.07789, "write_eur_per_1000": 0.00467, "read_eur_per_1000": 0.00037, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 1.5, "setup_operator_hours": 4, "status": "priced", "source": "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonS3/current/eu-central-1/index.json" + "id": "aws-s3-standard", + "provider": "AWS", + "service_class": "S3 Standard", + "region": "eu-central-1", + "storage_eur_per_gb_month": 0.0212, + "monthly_minimum_eur": 0, + "included_storage_gb": 0, + "included_egress_gb": 100, + "egress_eur_per_gb": 0.07789, + "write_eur_per_1000": 0.00467, + "read_eur_per_1000": 0.00037, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 1.5, + "setup_operator_hours": 4, + "status": "priced", + "source": "https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonS3/current/eu-central-1/index.json" }, { - "id": "azure-blob-hot-zrs", "provider": "Microsoft Azure", "service_class": "Blob Storage Hot ZRS (not S3 API)", "region": "germanywestcentral", "storage_eur_per_gb_month": 0.0197, "monthly_minimum_eur": 0, "included_storage_gb": 0, "included_egress_gb": 0, "egress_eur_per_gb": 0.08, "write_eur_per_1000": 0.00474, "read_eur_per_1000": 0.00038, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 2, "setup_operator_hours": 6, "status": "priced-egress-estimate", "source": "https://prices.azure.com/api/retail/prices" + "id": "azure-blob-hot-zrs", + "provider": "Microsoft Azure", + "service_class": "Blob Storage Hot ZRS (not S3 API)", + "region": "germanywestcentral", + "storage_eur_per_gb_month": 0.0197, + "monthly_minimum_eur": 0, + "included_storage_gb": 0, + "included_egress_gb": 0, + "egress_eur_per_gb": 0.08, + "write_eur_per_1000": 0.00474, + "read_eur_per_1000": 0.00038, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 2, + "setup_operator_hours": 6, + "status": "priced-egress-estimate", + "source": "https://prices.azure.com/api/retail/prices" }, { - "id": "gcp-cloud-storage-standard", "provider": "Google Cloud", "service_class": "Cloud Storage Standard regional (not S3 API)", "region": "europe-west3", "storage_eur_per_gb_month": 0.01731, "monthly_minimum_eur": 0, "included_storage_gb": 0, "included_egress_gb": 0, "egress_eur_per_gb": 0.10, "write_eur_per_1000": 0.00433, "read_eur_per_1000": 0.00035, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 2, "setup_operator_hours": 6, "status": "priced-egress-estimate", "source": "https://cloud.google.com/storage/pricing" + "id": "gcp-cloud-storage-standard", + "provider": "Google Cloud", + "service_class": "Cloud Storage Standard regional (not S3 API)", + "region": "europe-west3", + "storage_eur_per_gb_month": 0.01731, + "monthly_minimum_eur": 0, + "included_storage_gb": 0, + "included_egress_gb": 0, + "egress_eur_per_gb": 0.1, + "write_eur_per_1000": 0.00433, + "read_eur_per_1000": 0.00035, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 2, + "setup_operator_hours": 6, + "status": "priced-egress-estimate", + "source": "https://cloud.google.com/storage/pricing" }, { - "id": "stackit-object-storage", "provider": "STACKIT", "service_class": "Object Storage Premium-EU01", "region": "Germany South", "storage_eur_per_gb_month": 0.02662, "monthly_minimum_eur": 0, "included_storage_gb": 0, "included_egress_gb": 100000, "egress_eur_per_gb": 0, "write_eur_per_1000": 0, "read_eur_per_1000": 0, "operations_eur_per_month": 0, "support_eur_per_month": 0, "operator_hours_per_month": 1.5, "setup_operator_hours": 4, "status": "priced", "source": "https://www.stackit.de/de/preise__trashed/cloud-services/iaas/stackit-storage/" + "id": "stackit-object-storage", + "provider": "STACKIT", + "service_class": "Object Storage Premium-EU01", + "region": "Germany South", + "storage_eur_per_gb_month": 0.02662, + "monthly_minimum_eur": 0, + "included_storage_gb": 0, + "included_egress_gb": 100000, + "egress_eur_per_gb": 0, + "write_eur_per_1000": 0, + "read_eur_per_1000": 0, + "operations_eur_per_month": 0, + "support_eur_per_month": 0, + "operator_hours_per_month": 1.5, + "setup_operator_hours": 4, + "status": "priced", + "source": "https://www.stackit.de/de/preise__trashed/cloud-services/iaas/stackit-storage/" } ] } diff --git a/docs/evidence/RESOURCE-WP-0002-host-europe-resolution-2026-08-15.md b/docs/evidence/RESOURCE-WP-0002-host-europe-resolution-2026-08-15.md new file mode 100644 index 0000000..7acdbe3 --- /dev/null +++ b/docs/evidence/RESOURCE-WP-0002-host-europe-resolution-2026-08-15.md @@ -0,0 +1,82 @@ +# Host Europe evidence gap — resolved 2026-08-15 + +## The answer + +Account-holder statement, 2026-08-15: + +> Host Europe does not support fully managed S3, and even less so an API to +> provision storage. + +This closes the gap that `RESOURCE-WP-0002-T01` and `T02` had been holding open +since 2026-08-10. It is a **blocking answer**, which the T02 acceptance +criterion explicitly permits alongside evidence and `unknown`. + +## Provenance, stated honestly + +This is the account holder's knowledge, not vendor-written confirmation. The +original request was for written terms from Host Europe account support; that +correspondence never happened and, given the answer, has no purpose. The +provider record carries the distinction in `status_evidence` rather than +implying a vendor document exists. + +The 2020 `Preis_und_Leistungsverzeichnis_CloudStorage_1-0-1.pdf` is therefore a +historical specification, not a currently orderable product. Every row of the +2026-08-10 due-diligence matrix that reads `unknown` for Host Europe Cloud +Storage should now be read as **not applicable — the product is not offered**. +That matrix is a dated evidence record and has not been rewritten; this document +supersedes its Host Europe column. + +## What this changes + +**`data/providers/object-storage.json`** — `host-europe-cloud-storage` moves +from `blocked-account-confirmation` to `not-offered`. + +**T02 is satisfiable.** Every acceptance requirement now has evidence, an +`unknown`, or a blocking answer for each provider. Host Europe's blocking answer +is that the product does not exist. + +**T01 is satisfiable, and the A/B/C comparison was never actually missing a +leg.** Host Europe has no managed S3 to price, so its real form in this +comparison is self-managed Garage on Host Europe VMs — which is already priced +from their public virtual-server catalogue and always was: + +| Option | Month 1–9 recurring | Month 12 | Note | +|---|---:|---|---| +| Scaleway Standard Multi-AZ (chosen) | €60.60 → €67.35 | €67.35 | elastic, no capacity ceiling | +| Hetzner Object Storage | €96.49 | €96.49 | within the 1 TB quota | +| **Host Europe, self-managed Garage 3-node** | **€335.77** | **fails closed** | 400 GB usable; base demand reaches 458 GB | + +Host Europe is roughly **five times** the chosen option on recurring cost, and +runs out of usable capacity inside the twelve-month horizon: at month 12 the +model refuses to quote because a fixed-capacity VM set has no per-GB overage +price — you would buy another node, not another gigabyte. + +So the decision recorded in `opt:platform-audit-storage:2026-08` is not weakened +by the missing evidence; it is strengthened. The excluded option was excluded +for want of terms, and the terms would not have changed the outcome. + +## The second half of the statement matters separately + +"No API to provision storage" is a procurement-facility fact, not a pricing +fact. Any future Host Europe resource is **manually provisioned**: no +programmatic create, no scoped provisioning credential, no automated teardown. +That belongs to the procurement facility (`RESOURCE-WP-0005`) and to +`RAIL-HO-WP-0008`, which still owns the railiance01 server's commercial terms. +It also means the existing `resource:hosteurope:railiance01` record will never +acquire a provider-native resource ID from an API; whatever identity it gets +comes from the control panel or an invoice. + +## What is deliberately not changed + +`opt:platform-audit-storage:2026-08` is a decision record and keeps the state it +had when the founder approved it on 2026-08-14, including Host Europe's recorded +`unknowns` and the exclusion reason written at that time. A decision record +documents what was known when the decision was made. This document is the +supersession, and the next quarterly review reads both. + +## Residual + +None for Host Europe object storage. The comparison set for future quarterly +re-evaluation is Scaleway (incumbent), Hetzner, and self-managed Garage — +on Hetzner VMs rather than Host Europe, since Host Europe offers no advantage +on price, capacity headroom, or failure-domain independence from railiance01. diff --git a/workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md b/workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md index 5330655..a35f365 100644 --- a/workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md +++ b/workplans/RESOURCE-WP-0002-procure-postgres-backup-storage.md @@ -4,11 +4,11 @@ type: workplan title: "Procure and operationalize PostgreSQL backup object storage" domain: financials repo: resource-control -status: active +status: finished owner: codex topic_slug: railiance created: "2026-08-10" -updated: "2026-08-14" +updated: "2026-08-15" state_hub_workstream_id: "921496a3-280b-4dc8-a3c0-b4ec314142f5" --- @@ -111,7 +111,7 @@ with an explicit correlated-failure decision and an independent second copy. ```task id: RESOURCE-WP-0002-T01 -status: progress +status: done priority: high state_hub_task_id: "f578a9ec-dbdb-4b26-93bc-e53f7bc87ad1" ``` @@ -149,6 +149,16 @@ internal operations labor and internal setup from external services. Added a normalized 320 GB running-cost view so bundled, fixed-capacity, and elastic products compare on the same stored volume and request/restore pattern. +Done 2026-08-15: the account holder confirmed Host Europe offers no fully +managed S3 and no storage-provisioning API, so there is no managed product to +price. Host Europe's real form in this comparison is self-managed Garage on +their VMs, which was already priced from the public virtual-server catalogue: +EUR 335.77 per month for the 3-node option, roughly five times the chosen +Scaleway option, and it fails closed at month 12 when base demand (458 GB) +exceeds the 400 GB usable capacity. A, B, and C therefore calculate under the +same scenarios. Evidence: +`docs/evidence/RESOURCE-WP-0002-host-europe-resolution-2026-08-15.md`. + Control refinement 2026-08-10: added an immutable 12-month forecast record, monthly actual-observation schema, and variance calculator covering stored bytes, database size, WAL, requests, restore egress, invoice cost, and internal @@ -159,7 +169,7 @@ revision discipline, and the three-month recalibration loop. ```task id: RESOURCE-WP-0002-T02 -status: progress +status: done priority: high state_hub_task_id: "6dedb8db-c08f-4b58-90f2-32b1ea832d98" ``` @@ -178,6 +188,15 @@ object-lock behavior, and provider status visibility. Done when every acceptance requirement has evidence, `unknown`, or a blocking answer for each provider—no blank cells and no marketing inference. +Done 2026-08-15: Host Europe's remaining cells are answered by a blocking +answer, which this task's acceptance criterion permits — the account holder +confirmed the managed S3 product is not offered, so the 2020 published +specification describes nothing currently orderable. `host-europe-cloud-storage` +moves to `not-offered`. Provenance is recorded as account-holder knowledge, not +vendor-written confirmation. No acceptance requirement is now blank for any +provider. Evidence: +`docs/evidence/RESOURCE-WP-0002-host-europe-resolution-2026-08-15.md`. + Progress 2026-08-10: completed the public-primary-source evidence matrix in `docs/evidence/RESOURCE-WP-0002-provider-due-diligence-2026-08-10.md` and added a provisional Scaleway inventory record. Host Europe current S3 orderability