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
|
|
@ -0,0 +1,54 @@
|
|||
# PostgreSQL backup demand and cost model — 2026-08-10
|
||||
|
||||
## Observed baseline
|
||||
|
||||
A read-only query against `platform-pg-1` at `2026-08-10T15:54:12Z` measured
|
||||
39,573,871 bytes across connectable databases. `pg_stat_wal` reported
|
||||
19,744,568 bytes since `2026-08-10T13:37:53Z`, an extrapolated 0.208 GB/day.
|
||||
The cluster is less than one day old, so this is a seed observation rather than
|
||||
a representative trend. No credential value was read or recorded.
|
||||
|
||||
The governed requirements are a 30-day recovery window, daily physical base
|
||||
backup, continuous WAL archive, one monthly restore drill, and a complete exit
|
||||
calculation. The scenario inputs live in
|
||||
`data/demand/platform-audit-storage.json` and deliberately floor demand above
|
||||
the tiny initial observation:
|
||||
|
||||
| Scenario | Initial DB | Monthly growth | WAL/day | Restore egress | Labor/month |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| low | 1 GB | 5% | 0.25 GB | 1 GB | 0.5 h |
|
||||
| base | 5 GB | 10% | 1 GB | 5 GB | 1 h |
|
||||
| high | 20 GB | 20% | 5 GB | 20 GB | 2 h |
|
||||
|
||||
The conservative stored-byte formula is `30 × current database size + 30 ×
|
||||
daily WAL`. It does not claim compression savings. Operator labor is valued at
|
||||
€60/hour; provider-specific labor floors capture relative operational effort.
|
||||
The exit event adds full stored-byte egress plus four operator hours.
|
||||
|
||||
Run `make forecast` for all 12 months, scenarios, and providers. A `null` total
|
||||
is intentional: it means a required price is unknown and prevents an unknown
|
||||
from silently becoming free.
|
||||
|
||||
The catalog also includes self-managed Garage on 1–3 Host Europe/Hetzner VMs
|
||||
and managed AWS, Azure, Google Cloud, and STACKIT price points. See
|
||||
`RESOURCE-WP-0002-expanded-storage-comparison-2026-08-10.md` for assumptions
|
||||
and topology warnings.
|
||||
|
||||
Calculator rows split `monthly_infrastructure_eur` from
|
||||
`monthly_internal_labor_eur` and split internal setup labor from external setup
|
||||
services. The top-level `comparison_320gb` array provides a normalized running
|
||||
cost at 320 GB using the base request and restore pattern.
|
||||
|
||||
## Initial comparison
|
||||
|
||||
- Scaleway Standard Multi-AZ is fully calculable at €0.01606/GB-month, with
|
||||
75 GB/month free egress then €0.01/GB. Prices exclude tax.
|
||||
- Hetzner is calculable while usage remains inside its €6.49 monthly minimum,
|
||||
which includes 1 TB storage and 1 TB egress. Excess unit prices still need to
|
||||
be captured before high-growth or exit usage crosses the included quota.
|
||||
- Host Europe cannot be calculated until it confirms that the historical S3
|
||||
Cloud Storage product is currently orderable and supplies a current quote.
|
||||
|
||||
Because labor dominates this very small workload, selection should emphasize
|
||||
restore compatibility, independent failure domain, encryption, and exit proof
|
||||
before sub-euro storage differences.
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
# Expanded object-storage comparison — 2026-08-10
|
||||
|
||||
This adds self-managed S3-compatible storage and four large-cloud price points
|
||||
to the managed-provider comparison. All recurring totals include operator labor
|
||||
at €60/hour. Taxes are excluded. USD prices use the 2026-08-10 ECB reference
|
||||
rate of 1 EUR = 1.1555 USD.
|
||||
|
||||
## Self-managed reference architecture
|
||||
|
||||
Garage is the reference open-source implementation. It has an S3-compatible
|
||||
API and is designed for distributed deployments. Garage explicitly says its
|
||||
single-node quick-start has no redundancy and must not be used in production.
|
||||
CNPG/Barman compatibility remains a live preflight requirement.
|
||||
|
||||
The initial fixed-size estimates use locally attached storage:
|
||||
|
||||
- Host Europe: 8 vCPU, 16 GB RAM, 400 GB NVMe at €37.99/month including 19%
|
||||
VAT, normalized to €31.92 net per node. Network traffic is flat-rate.
|
||||
- Hetzner: CX53, 16 vCPU, 32 GB RAM, 320 GB local SSD at €29.49/month plus
|
||||
€0.50 IPv4, net per node. The June 2026 price adjustment is used.
|
||||
|
||||
Replication consumes the extra nodes; it does not multiply usable capacity.
|
||||
All nodes at one provider/location still share provider and site failure risk.
|
||||
|
||||
| Topology | Infrastructure/month | Internal labor/month | Running total at 320 GB | Internal setup | External setup | Usable ceiling | Assessment |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: | --- |
|
||||
| Host Europe, 1 node | €31.92 | 2 h / €120 | €151.92 | 8 h / €480 | not quoted | 400 GB | no redundancy; not production |
|
||||
| Host Europe, 2 nodes | €63.85 | 3 h / €180 | €243.85 | 12 h / €720 | not quoted | 400 GB | replicated, but poor failure/quorum shape |
|
||||
| Host Europe, 3 nodes | €95.77 | 4 h / €240 | €335.77 | 16 h / €960 | not quoted | 400 GB | production candidate; single provider/site risk |
|
||||
| Hetzner, 1 node | €30.09 | 2 h / €120 | €150.09 | 8 h / €480 | not quoted | 320 GB | no redundancy; not production |
|
||||
| Hetzner, 2 nodes | €60.18 | 3 h / €180 | €240.18 | 12 h / €720 | not quoted | 320 GB | replicated, but poor failure/quorum shape |
|
||||
| Hetzner, 3 nodes | €90.27 | 4 h / €240 | €330.27 | 16 h / €960 | not quoted | 320 GB | production candidate; single location risk |
|
||||
|
||||
These sizes cover the base scenario's first month (180 GB), but not its month
|
||||
12 estimate (458 GB). The calculator therefore returns `null` once the fixed
|
||||
capacity is exceeded. A larger Host Europe 800 GB node tier or Hetzner Volumes
|
||||
would be required; obtain account quotes before treating that expansion as a
|
||||
decision price. Hetzner also documents that its Volumes are already replicated
|
||||
across three physical servers, which means combining three Garage replicas with
|
||||
three replicated Volumes would buy nested redundancy at additional cost.
|
||||
|
||||
## Managed object-storage price points
|
||||
|
||||
Azure Blob and Google Cloud Storage are Barman-supported object stores but are
|
||||
not S3-compatible APIs. AWS and STACKIT are direct S3 API comparisons. The
|
||||
following table fixes stored volume at **320 GB**, uses the base request pattern
|
||||
(2,500 writes and 1,000 reads/month), and includes one 5 GB restore drill. This
|
||||
puts elastic per-GB products, Hetzner's bundled minimum, and Garage's fixed
|
||||
capacity on the same running-cost basis.
|
||||
|
||||
| Service | Infrastructure at 320 GB | Internal labor/month | Running total at 320 GB | Internal setup | External setup |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| Scaleway Standard Multi-AZ | €5.14 | 1 h / €60 | **€65.14** | none | €0 assumed |
|
||||
| Hetzner Object Storage | €6.49 | 1.5 h / €90 | **€96.49** | none | €0 assumed |
|
||||
| AWS S3 Standard, Frankfurt | €6.80 | 1.5 h / €90 | **€96.80** | 4 h / €240 | €0 assumed |
|
||||
| STACKIT Object Storage Premium-EU01 | €8.52 | 1.5 h / €90 | **€98.52** | 4 h / €240 | €0 assumed |
|
||||
| Google Cloud Storage Standard, Frankfurt | €6.05 | 2 h / €120 | **€126.05** | 6 h / €360 | €0 assumed |
|
||||
| Azure Blob Hot ZRS, Germany West Central | €6.72 | 2 h / €120 | **€126.72** | 6 h / €360 | €0 assumed |
|
||||
|
||||
Cloud request costs are negligible here; operator effort and egress assumptions
|
||||
matter more. Azure/GCP egress figures are explicit planning estimates rather
|
||||
than captured retail meters, so they must be refreshed in an account calculator
|
||||
before decision approval.
|
||||
|
||||
"Internal setup" values the federation's own implementation time at €60/hour.
|
||||
"External setup" means paid consulting, vendor professional services, or a
|
||||
contractor. No such service is assumed for managed self-service onboarding. It
|
||||
is **not quoted**, rather than zero, for Garage because an external security or
|
||||
operations review may be prudent and no scope or rate has been obtained.
|
||||
|
||||
The apparent difference between the earlier €62.89 Scaleway total and the
|
||||
normalized €5.14 infrastructure figure is reconciled in
|
||||
`docs/forecast-actual-control.md`: €62.89 is 180 GB infrastructure (€2.89) plus
|
||||
€60 labor, while €5.14 is infrastructure alone at 320 GB. The comparable 320 GB
|
||||
total is €65.14.
|
||||
|
||||
## Interpretation
|
||||
|
||||
Self-management does not win at this workload once even two hours/month of
|
||||
patching, monitoring, certificate handling, upgrades, disk replacement,
|
||||
capacity management, and restore support are valued. Three-node Garage costs
|
||||
roughly €330–€336/month plus €960 setup labor and still shares a provider/site
|
||||
failure domain. It may become attractive if the platform wants the capability
|
||||
for broader workloads, can amortize operations across them, or deliberately
|
||||
values open-source control above the cost difference.
|
||||
|
||||
For this backup alone, Scaleway remains the lowest modeled managed option.
|
||||
STACKIT is especially interesting as a sovereign three-AZ S3-compatible
|
||||
alternative: its documentation now states automatic replication across all
|
||||
three availability zones, versioning, lifecycle rules, server-side encryption,
|
||||
bucket policies, and Object Lock.
|
||||
|
||||
## Primary sources
|
||||
|
||||
- Host Europe VM pricing: https://www.hosteurope.de/Server/Virtual-Server/
|
||||
- Hetzner June 2026 pricing: https://docs.hetzner.com/general/infrastructure-and-availability/price-adjustment/
|
||||
- Hetzner Volume replication: https://docs.hetzner.com/cloud/volumes/overview/
|
||||
- Garage single-node warning: https://garagehq.deuxfleurs.fr/documentation/
|
||||
- AWS S3 price list: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonS3/current/eu-central-1/index.json
|
||||
- AWS egress/free allowance: https://aws.amazon.com/ec2/pricing/on-demand/
|
||||
- Azure retail pricing API: https://learn.microsoft.com/en-us/rest/api/cost-management/retail-prices/azure-retail-prices
|
||||
- Google Cloud Storage pricing: https://cloud.google.com/storage/pricing
|
||||
- STACKIT storage pricing: https://www.stackit.de/de/preise__trashed/cloud-services/iaas/stackit-storage/
|
||||
- STACKIT object-storage capabilities: https://docs.stackit.cloud/de/products/storage/object-storage/basics/introduction/
|
||||
- STACKIT network pricing: https://www.stackit.de/de/preise__trashed/cloud-services/iaas/stackit-network/
|
||||
- ECB daily FX rate: https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# Object-storage provider due diligence — 2026-08-10
|
||||
|
||||
Status vocabulary: `yes`, `no`, `unknown`, or `test`. `Test` means documentation
|
||||
is promising but the live CNPG/Barman preflight remains mandatory.
|
||||
|
||||
| Requirement | Host Europe Cloud Storage | Scaleway Standard Multi-AZ | Hetzner Object Storage |
|
||||
| --- | --- | --- | --- |
|
||||
| Currently orderable for account | unknown — written confirmation required | yes | yes |
|
||||
| S3-compatible HTTPS / SigV4 | unknown | yes / test | yes / test |
|
||||
| EU region considered | unknown | Amsterdam `nl-ams` | Nuremberg `nbg1` |
|
||||
| Different provider from reef-railiance | no | yes | yes |
|
||||
| Multi-AZ / availability | unknown | yes; 99.9% service availability | unknown; docs describe Ceph and infrastructure redundancy, not a quantified service SLA |
|
||||
| Published durability | unknown | 99.999999999% | unknown |
|
||||
| Scoped access key | unknown | yes; bucket policy test required | yes; key defaults to all project buckets, bucket policy required |
|
||||
| Private bucket | unknown | yes | yes |
|
||||
| Multipart/list/get/put/delete | unknown | yes / test | yes / test |
|
||||
| Versioning | unknown | yes | yes |
|
||||
| Lifecycle expiration | unknown | yes | yes |
|
||||
| Object lock | unknown | yes; cannot later disable | yes; enable at bucket creation |
|
||||
| TLS encryption | unknown | yes; enforceable by bucket policy | yes / test |
|
||||
| Encryption at rest | unknown | yes: SSE-ONE, SSE-C, or SSE-KMS | **no default**; SSE-C is documented |
|
||||
| Initial 100 GiB without long commitment | unknown | yes, usage-based | yes, hourly base billing |
|
||||
| Operations pricing | unknown | no separate request charge found; confirm invoice model | PUT/GET/DELETE free |
|
||||
| Storage / egress pricing | unknown | €0.01606/GB-month; 75 GB egress free, then €0.01/GB | €6.49 minimum includes 1 TB storage and 1 TB egress; excess prices still to capture |
|
||||
| Cancellation / support terms | unknown | contract review required | contract review required |
|
||||
| Provider status visibility | unknown | yes | yes |
|
||||
| CNPG 1.25/Barman compatibility | unknown | test | test |
|
||||
|
||||
## Evidence
|
||||
|
||||
- Host Europe Backup Storage supports FTP, SCP, SFTP, and rsync, so it is a
|
||||
secondary logical-copy candidate, not the primary Barman object store:
|
||||
https://www.hosteurope.de/faq/server/virtual-server/backup-storage/
|
||||
- Host Europe's S3 claim is currently only backed by an older specification:
|
||||
https://www.hosteurope.de/download/PVL/Preis_und_Leistungsverzeichnis_CloudStorage_1-0-1.pdf
|
||||
- Scaleway pricing: https://www.scaleway.com/en/pricing/storage/
|
||||
- Scaleway capabilities and durability:
|
||||
https://www.scaleway.com/en/object-storage/
|
||||
- Scaleway regions/lifecycle/multipart:
|
||||
https://www.scaleway.com/en/docs/object-storage/concepts/
|
||||
- Scaleway object lock:
|
||||
https://www.scaleway.com/en/docs/object-storage/how-to/use-object-lock/
|
||||
- Hetzner overview, endpoints, quotas, operations, and limits:
|
||||
https://docs.hetzner.com/storage/object-storage/overview/
|
||||
- Hetzner supported S3 actions and encryption limitation:
|
||||
https://docs.hetzner.com/storage/object-storage/supported-actions/
|
||||
- Hetzner encryption FAQ:
|
||||
https://docs.hetzner.com/storage/object-storage/faq/general/
|
||||
- CNPG 1.25 S3-compatible endpoint and lifecycle guidance:
|
||||
https://cloudnative-pg.io/docs/1.25/appendixes/object_stores/
|
||||
|
||||
## Blocking evidence requests
|
||||
|
||||
1. Host Europe: ask account support to confirm current orderability, endpoint,
|
||||
region, SigV4, supported API, versioning/lifecycle, encryption, durability,
|
||||
availability, price, support, and cancellation terms in writing.
|
||||
2. Scaleway and Hetzner: obtain account-visible contractual/support terms and
|
||||
confirm tax treatment. Capture Hetzner excess prices.
|
||||
3. Run a disposable live preflight for each finalist: private bucket, scoped
|
||||
positive and negative credentials, multipart CRUD, versioning/lifecycle,
|
||||
Barman empty-WAL-archive check, and deletion/exit behavior.
|
||||
|
||||
## Provisional conclusion
|
||||
|
||||
Host Europe is not selectable as primary while current S3 orderability is
|
||||
unknown. Hetzner fails the current acceptance requirement for provider-managed
|
||||
encryption at rest unless client-side/SSE-C custody is explicitly accepted.
|
||||
Scaleway Standard Multi-AZ is therefore the provisional primary, subject to a
|
||||
live Barman preflight, contract review, and human purchase approval. Hetzner
|
||||
remains a price comparator; Host Europe Backup Storage or the governed
|
||||
Nextcloud lane remains the independent logical-copy candidate.
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# RESOURCE-WP-0003 delegated evidence workplans — 2026-08-11
|
||||
|
||||
## Result
|
||||
|
||||
Every owned gap from the initial portfolio discovery now points to a live,
|
||||
repository-local work record. Resource-control retains the inventory,
|
||||
forecast, actual-observation, allocation, and optimization contract; source
|
||||
repositories retain authority for infrastructure and workload evidence; and
|
||||
fin-hub retains booked financial facts.
|
||||
|
||||
| Evidence owner | Workplan | State Hub workplan ID | Interface outcome |
|
||||
|---|---|---|---|
|
||||
| railiance-infra | `RAIL-HO-WP-0008` | `7122657f-87c8-46b5-a725-a1af1ba0af12` | Host identity, lifecycle, commercial and host-capacity evidence |
|
||||
| railiance-cluster | `RAIL-BS-WP-0014` | `ea6ec98a-0d65-4afa-b6c5-6e7ed34011ac` | Cluster capacity, utilization, storage/failure-domain and allocation evidence |
|
||||
| railiance-forge | `RAILIANCE-WP-0002` | `72f935a5-d921-48a4-96e4-2365556c7374` | Forgejo demand, utilization, labor/SLO and allocation evidence |
|
||||
| railiance-platform | `RAILIANCE-WP-0016` | `49084fb8-de63-4f32-a4a9-3a42d4e708ac` | apps-pg utilization, recovery, labor and consumer evidence |
|
||||
| coulomb-social | `CSOC-WP-0005` | `00de1578-6150-40d3-b193-e852666ed945` | Workload forecasts, observations, objectives and labor evidence |
|
||||
| rapp-qonto | `RAPP-QONTO-WP-0002` | `25b3b715-9a56-499e-a85c-a09ebd9bbb79` | Scale-to-zero usage, external service cost inputs and labor evidence |
|
||||
| fin-hub | `FIN-WP-0004-T04..T06` | `67b6de6c-4820-4478-9789-f50260204c27` | Budgets/constraints, forecast-to-actual loop and generalized attribution |
|
||||
|
||||
The authoritative machine-readable mapping is
|
||||
`data/portfolio-coverage-2026-08-11.json`. State Hub synchronization completed
|
||||
without failures. Its warnings concern pre-existing fleet prefix collisions,
|
||||
unregistered legacy task prefixes, and missing optional DoR metadata; none
|
||||
prevented registration of these plans.
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
# RESOURCE-WP-0003 fin-hub contract preflight
|
||||
|
||||
Date: 2026-08-11
|
||||
Resource-control task: `RESOURCE-WP-0003-T02`
|
||||
Fin-hub tasks: `FIN-WP-0004-T01`, `T02`, `T03`, `T07`, `T08`, `T09`
|
||||
Fin-hub commit: `0034330`
|
||||
|
||||
## Result
|
||||
|
||||
Resource-control accepts the authority and schema boundary in the joint v0.1
|
||||
contract. Fin-hub's remediation was reviewed against the timestamped
|
||||
assessment and its full suite passed:
|
||||
|
||||
```text
|
||||
46 passed, 1 third-party deprecation warning
|
||||
```
|
||||
|
||||
Resource-control's suite passed after adding its producer-owned schema,
|
||||
forecast exporter, booked-cost consumer validation, and reconciliation seam:
|
||||
|
||||
```text
|
||||
13 passed
|
||||
resource-control declarations: valid
|
||||
```
|
||||
|
||||
## Cross-repository check
|
||||
|
||||
The live immutable backup forecast
|
||||
`data/forecasts/platform-audit-storage-scaleway-base-2026-08.json` was processed
|
||||
through both implementations using:
|
||||
|
||||
- resource-control `tools/financial_exchange.py::forecast_records`; and
|
||||
- fin-hub `fin_hub.services.exchange::ingest_resource_forecast`.
|
||||
|
||||
Observed result:
|
||||
|
||||
```json
|
||||
{
|
||||
"producer_consumer_records": 12,
|
||||
"idempotent_store_rows": 12,
|
||||
"payloads_equal": true,
|
||||
"booked_cost_gate": "awaits attributable provider fact"
|
||||
}
|
||||
```
|
||||
|
||||
Replaying the same forecast did not add rows. All canonical record payloads
|
||||
matched, including IDs, periods, cost breakdown, attribution, assumptions, and
|
||||
provenance reference.
|
||||
|
||||
## Residual acceptance gate
|
||||
|
||||
This preflight proves the planning direction; it is not evidence of purchased
|
||||
storage or actual spend. `FIN-WP-0004-T05` remains waiting until
|
||||
`RESOURCE-WP-0002` produces a real provider financial fact attributable to
|
||||
`platform:audit-storage`. That round trip must then demonstrate:
|
||||
|
||||
1. exactly one authoritative booked fact in fin-hub;
|
||||
2. a non-ledger projection consumed by resource-control;
|
||||
3. a join to the immutable forecast and technical observation;
|
||||
4. infrastructure-cost variance with the financial fact ID preserved; and
|
||||
5. duplicate delivery and any correction leaving effective totals correct.
|
||||
|
||||
Synthetic records remain suitable for automated contract tests but cannot
|
||||
satisfy this operational gate.
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# RESOURCE-WP-0003 generalized control cycle — 2026-08-11
|
||||
|
||||
## Result
|
||||
|
||||
`RESOURCE-WP-0003-T05` generalized the backup-specific forecast-to-actual
|
||||
method into a provider-neutral portfolio contract.
|
||||
|
||||
The implementation consists of:
|
||||
|
||||
- `schemas/resource-control-cycle.schema.json` for immutable forecast and
|
||||
actual records;
|
||||
- `tools/control_cycle.py` for resource-neutral comparison and controlled
|
||||
variance attribution;
|
||||
- six paired examples covering storage, fixed cluster compute, and a hybrid
|
||||
shared PostgreSQL service;
|
||||
- tests for the three resource classes, immutable forecast binding, explicit
|
||||
cost attribution, and fail-closed data-quality handling;
|
||||
- updated operating guidance in `docs/forecast-actual-control.md`.
|
||||
|
||||
## Boundary with fin-hub
|
||||
|
||||
Actual records carry `booked_cost_refs`; resource-control does not reproduce
|
||||
the ledger fact. Fin-hub message `d33f2452-8dc6-4249-a3d2-84fda938103a`
|
||||
confirmed explicit `financial_fact_id -> resource_id` binding, budget and
|
||||
constraint signals, and generalized exchange health. The first operational
|
||||
backup round trip remains correctly gated on `RESOURCE-WP-0002` procurement;
|
||||
that does not invalidate these illustrative contract fixtures.
|
||||
|
||||
## Verification
|
||||
|
||||
- `make test`: 25 tests passed and declarations validated.
|
||||
- All three example pairs completed through `make control-cycle`.
|
||||
- `git diff --check`: clean.
|
||||
|
||||
The examples are intentionally marked illustrative. Their values must not be
|
||||
reported as actual consumption or booked cost.
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# RESOURCE-WP-0003 initial portfolio discovery
|
||||
|
||||
Date: 2026-08-11
|
||||
Task: `RESOURCE-WP-0003-T03`
|
||||
Coverage data: `data/portfolio-coverage-2026-08-11.json`
|
||||
|
||||
## Result
|
||||
|
||||
The first real portfolio slice contains seven inventory records:
|
||||
|
||||
| Resource | Owner | Role |
|
||||
| --- | --- | --- |
|
||||
| `resource:hosteurope:railiance01` | `railiance-infra` | provider compute host |
|
||||
| `resource:railiance:reef-railiance:k3s` | `railiance-cluster` | shared single-node Kubernetes runtime |
|
||||
| `resource:railiance:forgejo` | `railiance-forge` | Helix Forge source/package infrastructure |
|
||||
| `resource:railiance:apps-pg` | `railiance-platform` | shared application database service |
|
||||
| `resource:tenant:coulomb:coulomb-social` | `coulomb-social` | Coulomb reference-tenant application |
|
||||
| `resource:tenant:friendly:binky:rapp-qonto` | `rapp-qonto` | representative tenant workload |
|
||||
| `resource:platform:audit-storage` | `resource-control` | proposed backup storage |
|
||||
|
||||
Helix Forge does not itself operate production infrastructure; its repository
|
||||
scope explicitly delegates runtime operation. Its current infrastructure
|
||||
coverage is therefore the shared Forgejo service and its underlying cluster
|
||||
and host, not a fictional Helix Forge server.
|
||||
|
||||
## Live substrate observation
|
||||
|
||||
A read-only observation of `railiance01` and the reef-railiance Kubernetes API
|
||||
at `2026-08-11T09:05:25Z` confirmed:
|
||||
|
||||
- one Ready k3s control-plane/etcd node on `railiance01`;
|
||||
- 4 allocatable vCPU, approximately 15.62 GiB allocatable memory, 183.06 GiB
|
||||
allocatable ephemeral storage, and a 110-pod limit;
|
||||
- node usage of 564m CPU and 5,975 MiB memory at observation time;
|
||||
- a 192.69 GiB root filesystem, 66.77 GiB used;
|
||||
- active Forgejo and Coulomb Social deployments with one ready replica each;
|
||||
- active `apps-pg` with one ready CNPG instance and a 10 GiB volume;
|
||||
- a healthy `rapp-qonto` Knative Service with min-scale 0 and max-scale 1;
|
||||
- a continuously running Qonto egress proxy; and
|
||||
- all discovered persistent volumes using `local-path`, therefore sharing the
|
||||
host failure domain.
|
||||
|
||||
No credential values or secret-bearing resources were read or recorded.
|
||||
|
||||
## Source authority
|
||||
|
||||
- `railiance-cluster` owns the k3s runtime and publishes the substrate profile.
|
||||
- `railiance-apps` supplies current Forgejo and Coulomb Social deployment
|
||||
values; `railiance-forge` is the declared forge-operation owner.
|
||||
- `railiance-platform` owns the shared applications PostgreSQL definition.
|
||||
- `coulomb-social` owns tenant and application behavior.
|
||||
- `rapp-qonto` owns the Binky tenant binding, resource requests, Knative
|
||||
package, and runtime requirements.
|
||||
- the live operating system and Kubernetes API supplied timestamped capacity
|
||||
and workload-state evidence.
|
||||
|
||||
## Material findings
|
||||
|
||||
The portfolio currently has one physical/virtual host and one Kubernetes node.
|
||||
Compute, local persistent storage, databases, Forgejo, Coulomb Social, and the
|
||||
tenant workload therefore share one provider/host failure domain. The planned
|
||||
ThreePhoenix HA work remains backlog; the inventory does not describe its
|
||||
target three nodes as current capacity.
|
||||
|
||||
The active cluster has significant point-in-time headroom, but a single CPU and
|
||||
memory sample is not a utilization history and cannot support rightsizing.
|
||||
Commercial identifiers, booked server price, renewal dates, operations labor,
|
||||
and shared allocation methods remain unknown.
|
||||
|
||||
Each gap has an authoritative repository owner in the coverage data. Creating
|
||||
live delegated work records for those gaps is `RESOURCE-WP-0003-T04`; this
|
||||
discovery does not silently assign implementation through prose.
|
||||
|
||||
## Verification
|
||||
|
||||
```text
|
||||
20 tests passed
|
||||
resource-control declarations: valid
|
||||
all inventory relationships resolve
|
||||
git diff --check: pass
|
||||
```
|
||||
104
docs/evidence/RESOURCE-WP-0003-optimization-cases-2026-08-14.md
Normal file
104
docs/evidence/RESOURCE-WP-0003-optimization-cases-2026-08-14.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
# RESOURCE-WP-0003 optimization cases — 2026-08-14
|
||||
|
||||
## Result
|
||||
|
||||
`RESOURCE-WP-0003-T06` established the review cadence, the decision template,
|
||||
and a fail-closed evaluator for optimization cases, and validated the process
|
||||
against the backup case and one non-storage portfolio candidate.
|
||||
|
||||
The implementation consists of:
|
||||
|
||||
- `schemas/optimization-case.schema.json` — baseline and alternatives carry
|
||||
identical decision fields, so a comparison against an undescribed status quo
|
||||
is structurally impossible;
|
||||
- `tools/optimization.py` — comparison, payback, failure-domain delta, verdicts,
|
||||
and decision-state validation;
|
||||
- `data/optimization/platform-audit-storage-2026-08.json` — the storage case;
|
||||
- `data/optimization/reef-railiance-k3s-2026-08.json` — the non-storage case;
|
||||
- `docs/optimization-cases.md` — case types, decision template, cadence, and the
|
||||
loop that returns outcomes to the next forecast;
|
||||
- 25 tests in `tests/test_optimization.py`, plus schema and case checks in
|
||||
`tools/validate.py`.
|
||||
|
||||
## Decision fields
|
||||
|
||||
T06 requires every recommendation to show baseline, alternative, one-time cost,
|
||||
recurring infrastructure and labour cost, utilization, uncertainty,
|
||||
service-level constraints, failure domains, exit path, and expected payback.
|
||||
The schema requires all ten on every option, and the evaluator refuses to
|
||||
recommend while any is `null`. Payback is computed from one-time cost and
|
||||
realised monthly saving; it is never asserted.
|
||||
|
||||
Recurring cost is split into infrastructure, internal labour, and external
|
||||
labour. This is not cosmetic: in the storage case Hetzner has the lower
|
||||
infrastructure price (EUR 6.49 against EUR 7.35) and is still EUR 29.14 per
|
||||
month more expensive, entirely on operator hours. A comparison on unit price
|
||||
alone would have inverted the result.
|
||||
|
||||
## Fail-closed behaviour
|
||||
|
||||
One unknown anywhere in the compared pair makes the comparison
|
||||
`blocked_on_evidence`. Unknowns are `null` values plus a named `unknowns` list
|
||||
that attributes each gap to an owning repository or authority. The evaluator
|
||||
also refuses invalid decision states: a blocked case cannot be `proposed` or
|
||||
`approved`, a decided case must name `approver` and `approved_on`, and a case
|
||||
with no blockers cannot claim to be blocked.
|
||||
|
||||
`reject` is a cost verdict only. The three-node cluster option raises recurring
|
||||
cost by design and buys availability instead; that argument belongs to the
|
||||
deciding authority against a declared service objective, not to the calculator.
|
||||
|
||||
## Case 1 — `opt:platform-audit-storage:2026-08` (storage)
|
||||
|
||||
Baseline is Scaleway Standard Multi-AZ, the provisional primary from T02 due
|
||||
diligence, at month-12 base-scenario demand from `tools/cost_model.py`.
|
||||
|
||||
| Option | Recurring EUR/month | Verdict |
|
||||
|---|---|---|
|
||||
| Scaleway Standard Multi-AZ (baseline) | 67.35 | — |
|
||||
| Hetzner Object Storage | 96.49 | `reject` (+29.14) |
|
||||
| Host Europe Cloud Storage | unknown | `blocked_on_evidence` |
|
||||
|
||||
Host Europe is blocked on four named gaps: current S3 orderability for this
|
||||
account, five price fields, cancellation terms, and correlated-failure
|
||||
acceptance. It has no known exit path, and it shares `provider:host-europe`
|
||||
with the compute host the backup is meant to protect.
|
||||
|
||||
This case exercises the process against real cost-model output. It is
|
||||
deliberately **not** the procurement decision, which `RESOURCE-WP-0002-T03`
|
||||
owns and human financial authority approves. The case state is
|
||||
`blocked_on_evidence` and recommends nothing.
|
||||
|
||||
## Case 2 — `opt:reef-railiance-k3s:2026-08` (non-storage)
|
||||
|
||||
Baseline is the current single-node k3s on railiance01, with the live capacity
|
||||
observation from T03 discovery: 0.564 of 4 vCPU, 5.83 of 15.62 GiB, 66.77 of
|
||||
192.69 GiB root filesystem.
|
||||
|
||||
Utilization is genuinely low — 14 percent CPU, 37 percent memory — and that is
|
||||
a real rightsizing signal. Every comparison is nevertheless blocked, for two
|
||||
independent reasons the case records rather than works around:
|
||||
|
||||
1. The railiance01 booked price is unknown, so no option has a recurring cost,
|
||||
no saving exists, and no payback can be computed.
|
||||
2. The utilization figure is a single sample taken on 2026-08-11. Mean usage is
|
||||
not a sizing basis; peak load over a billing period is owed by
|
||||
`RAIL-BS-WP-0014`.
|
||||
|
||||
Both alternatives — a smaller single server and the RAIL-BS-WP-0007 three-node
|
||||
cluster — are recorded with their unknowns attributed to `railiance-infra`
|
||||
(`RAIL-HO-WP-0008`) and `railiance-cluster` (`RAIL-BS-WP-0014`).
|
||||
|
||||
A case that refuses to conclude is the correct output here, and it is a useful
|
||||
one: it names exactly which evidence would unblock a rightsizing decision, and
|
||||
it is visible in the portfolio report until that evidence arrives.
|
||||
|
||||
## Boundaries held
|
||||
|
||||
`resource-control` produced both cases and decided neither. Financial
|
||||
implications reach `fin-hub` through `financial_handoff` under
|
||||
`docs/fin-hub-resource-control-contract-v0.1.md`; neither case has sent one,
|
||||
because neither is approved. Implementation is delegated through
|
||||
`decision.delegated_to`, which names `railiance-infra` and `railiance-cluster`
|
||||
for the cluster case. `outcome.feeds_forecast` binds each case to the
|
||||
control-cycle records that will later show whether it was right.
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# RESOURCE-WP-0003 portfolio model v0.2
|
||||
|
||||
Date: 2026-08-11
|
||||
Task: `RESOURCE-WP-0003-T01`
|
||||
Schema: `schemas/resource-inventory.schema.json`
|
||||
|
||||
## Result
|
||||
|
||||
The inventory model is generalized from a storage purchase record into a
|
||||
managed-infrastructure portfolio record. Version 0.2 represents:
|
||||
|
||||
- provider-managed elastic storage;
|
||||
- self-managed services hosted on rented capacity;
|
||||
- Kubernetes or other shared capacity;
|
||||
- shared platform services; and
|
||||
- future compute, network, database, managed-service, and license records.
|
||||
|
||||
The existing proposed Scaleway backup resource was migrated as the only
|
||||
authoritative inventory record. The Garage, Kubernetes-capacity, and ingress
|
||||
records live under `examples/portfolio/`, carry `record_scope: example`, and
|
||||
contain explicit example evidence. They are schema proofs, not claims about
|
||||
live infrastructure.
|
||||
|
||||
## Model decisions
|
||||
|
||||
- Resource identity uses the stable `resource:` namespace independently of
|
||||
provider-native identifiers.
|
||||
- Lifecycle separates proposed, ordered, commissioning, active, suspended,
|
||||
retiring, retired, and rejected states.
|
||||
- Provider-managed, self-managed, and shared-capacity management models are
|
||||
explicit.
|
||||
- Capacity is a set of typed dimensions and distinguishes provisioned, usable,
|
||||
allocated, observed, limiting, and unknown values.
|
||||
- Ownership supports multiple workloads, optional tenant identity, and a
|
||||
dedicated, shared, or unattributed allocation mode.
|
||||
- Shared allocations require a driver and versioned method. Unknown allocation
|
||||
remains explicit rather than receiving an invented key.
|
||||
- Relationships express hosting, composition, dependency, replacement,
|
||||
capacity consumers, and backup placement without embedding another
|
||||
repository's graph authority.
|
||||
- Requirements and evidence carry their kind, reference, observation date,
|
||||
and authoritative source.
|
||||
- Exit path is mandatory for every resource class.
|
||||
|
||||
## Semantic controls
|
||||
|
||||
`tools/portfolio.py` adds controls not conveniently expressed as shape alone:
|
||||
|
||||
- valid lifecycle transitions;
|
||||
- ordered lifecycle dates;
|
||||
- commissioned dates for operational resources;
|
||||
- order evidence for operational provider-managed resources;
|
||||
- allocation-key and shared-driver consistency;
|
||||
- unique capacity metric/kind dimensions;
|
||||
- prevention of self-relationships; and
|
||||
- unmistakable example evidence.
|
||||
|
||||
Verification:
|
||||
|
||||
```text
|
||||
18 tests passed
|
||||
resource-control declarations: valid
|
||||
git diff --check: pass
|
||||
```
|
||||
|
||||
## Next use
|
||||
|
||||
`RESOURCE-WP-0003-T03` should now discover real portfolio records for Helix
|
||||
Forge, Coulomb Social, shared Railiance services, and one representative tenant
|
||||
workload. It must replace example assumptions with source evidence and preserve
|
||||
unknown values where authority is not yet available.
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# RESOURCE-WP-0003 portfolio reporting and cadence — 2026-08-14
|
||||
|
||||
## Result
|
||||
|
||||
`RESOURCE-WP-0003-T07` established the portfolio view and the operating cadence.
|
||||
|
||||
The implementation consists of:
|
||||
|
||||
- `tools/portfolio_report.py` — coverage, lifecycle, utilization, cost,
|
||||
renewals, risks, open optimization cases, and next actions, derived entirely
|
||||
from committed evidence;
|
||||
- `docs/portfolio-operating-cadence.md` — monthly observation, monthly report,
|
||||
quarterly calibration, pre-renewal review, and event-driven triggers, each
|
||||
with named inputs, consumers, and outputs;
|
||||
- `make portfolio-report`;
|
||||
- 22 tests in `tests/test_portfolio_report.py`, including a suite that renders
|
||||
the real committed portfolio rather than fixtures.
|
||||
|
||||
Nothing in the report is typed by hand. It reads `data/resources/`, the latest
|
||||
`data/portfolio-coverage-*.json`, and `data/optimization/`, and it re-validates
|
||||
every record it reads.
|
||||
|
||||
## Not forcing false precision
|
||||
|
||||
T07 requires reporting missing evidence and unapportioned cost rather than
|
||||
forcing false precision. Two decisions carry that requirement:
|
||||
|
||||
- **`known_monthly_spend_eur` is `null`, never `0`.** Six of seven resources
|
||||
carry no price evidence and no booked cost has arrived from `fin-hub`.
|
||||
Summing the one priced resource would report a portfolio spend roughly an
|
||||
order of magnitude below reality while looking authoritative. The field stays
|
||||
unknown, accompanied by a note stating how many resources are unpriced.
|
||||
- **Unattributed cost is a list of resources, not a spread.** Four resources
|
||||
have allocation mode `unattributed`. They are named, with the repository that
|
||||
owes the allocation driver; their cost is not divided across consumers by a
|
||||
plausible default.
|
||||
|
||||
Resources whose capacity cannot be measured appear in `utilization.unmeasured`
|
||||
with the reason, rather than being dropped from the ratios and thereby
|
||||
flattering the portfolio average.
|
||||
|
||||
## What the current report tells an operator
|
||||
|
||||
T07 is done when an operator can identify material spend, idle or saturated
|
||||
capacity, forecast error, approaching commitments, and the next evidence-backed
|
||||
action. Against the portfolio as committed on 2026-08-14:
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Material spend | **Unknown, explicitly.** Only the proposed backup storage carries price evidence; the rest waits on `RAIL-HO-WP-0008` and `FIN-WP-0004`. |
|
||||
| Idle capacity | `resource:hosteurope:railiance01` and `resource:railiance:reef-railiance:k3s`, idle on every measured metric at 14 percent CPU and 37 percent memory. Five resources are unmeasurable. |
|
||||
| Saturated capacity | None. |
|
||||
| Forecast error | **Not yet computable.** The control-cycle mechanism is proven on paired examples, but no operational actual observation exists, so no variance is reported and none is fabricated. |
|
||||
| Approaching commitments | None visible within 90 days — and the finding is that six active resources have **no** renewal or cancellation date at all, so no cancellation window can be respected. |
|
||||
| Next action | The `next_actions` list: seven delegated workplans, the booked-cost dependency on `fin-hub`, and six missing contract-date records, each addressed to its owner. |
|
||||
|
||||
## Structural risk surfaced
|
||||
|
||||
The risk section reports concentration mechanically rather than in prose: six of
|
||||
seven resources share `host:railiance01` and five share `cluster:reef-railiance`.
|
||||
That includes every workload the proposed backup storage exists to protect,
|
||||
which is the standing argument against same-provider placement recorded in
|
||||
`opt:platform-audit-storage:2026-08`. Thresholds are explicit in the tool —
|
||||
idle at or below 35 percent, saturated at or above 85 percent, renewal horizon
|
||||
90 days, failure-domain concentration above two resources.
|
||||
|
||||
## Boundaries held
|
||||
|
||||
The report reads; it does not write to any other repository. Every unknown it
|
||||
prints is attributed to the repository or authority that owns it, and the
|
||||
`next_actions` list is the message sent back to those owners on the monthly
|
||||
cadence. No booked financial fact is reproduced here; spend remains
|
||||
`fin-hub`'s authority under
|
||||
`docs/fin-hub-resource-control-contract-v0.1.md`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue