feat: operational resource procurement facility

Implement RESOURCE-WP-0005: entity register, V0.1 terms parameters,
entity association on inventory and planning records, transfer-price
and credit-state arithmetic, monthly settlement, and entity views on
the portfolio report. Live close emits nothing until delivered cost
is known. Handoffs are FIN-WP-0006 and RAILIANCE-WP-0017.
This commit is contained in:
tegwick 2026-08-14 13:15:02 +02:00
parent 325a505980
commit f8d1c542d5
37 changed files with 1316 additions and 28 deletions

View file

@ -38,6 +38,24 @@ Fin-hub owns its outbound `BookedCostEvidence` executable schema. This
repository validates the contract fields and arithmetic it consumes, but does
not redefine financial authority.
## Internal settlement (RESOURCE-WP-0005)
`schemas/settlement-statement.schema.json` is the outbound shape for proposed
internal transfer charges. It is planning/settlement evidence, not a booked
fact. Join keys added by the facility:
- `financial_entity_id` (`entity:…`)
- `procuring_entity_id` (V0.1: `entity:railiance`)
- `period`, `terms_version`
A recognized internal payment, when it exists, is a fin-hub booked fact
joined by `financial_fact_id` + entity + period. resource-control never
clears outstanding from its own statement.
The consumption-mode signal (`open` | `restricted`, remaining transfer-price
allowance) is published for Railiance operations. It is not a fin-hub
budget. Handoff workplans: `FIN-WP-0006`, `RAILIANCE-WP-0017`.
## Acceptance boundary
The 12-row `platform:audit-storage` forecast can complete an idempotent

View file

@ -42,7 +42,7 @@ reason, rather than being silently omitted from the ratios.
| Rhythm | When | Inputs | Consumers | Output |
|---|---|---|---|---|
| **Monthly observation** | First week, for the closed month | Monthly actual records from delegated telemetry; booked costs from `fin-hub` | resource-control | `tools/control_cycle.py` variance per resource; a new optimization case where variance is attributed to demand, price, or allocation rather than data quality |
| **Monthly settlement** | With the observation, once entity association is live | Per-entity usage, delivered cost, transfer prices under `docs/TermsOfResourceProcurement.md`; recognized payments from `fin-hub` | consuming financial entities; Railiance operations; `fin-hub` | One settlement statement and credit-state evaluation (`open` or `restricted`) per consuming entity |
| **Monthly settlement** | With the observation | Per-entity usage, delivered cost, transfer prices under `docs/TermsOfResourceProcurement.md`; recognized payments from `fin-hub` | consuming financial entities; Railiance operations; `fin-hub` | `make settlement PERIOD=YYYY-MM`; empty output if nothing is known to settle. Runbook: `docs/resource-procurement-facility.md` |
| **Monthly portfolio report** | With the observation | Resource records, coverage, optimization cases | Human operator; owning repositories | `make portfolio-report`; the `next_actions` list is re-sent to the repositories named in it |
| **Quarterly calibration** | End of quarter | Three months of variance | resource-control; `fin-hub` | Forecast revisions per `docs/forecast-actual-control.md` — revisions, never overwrites; refreshed provider prices in every open case |
| **Pre-renewal review** | At least 60 days before the earliest `renews_on` or `cancel_by` | Contract evidence, utilization, open cases | Human financial authority | A `renewal` case, decided while cancellation is still possible |

View file

@ -0,0 +1,88 @@
# Resource procurement facility — operator runbook
Status: operational V0.1 (RESOURCE-WP-0005)
Terms: `docs/TermsOfResourceProcurement.md`
Parameters: `data/terms/procurement-v0.1.json`
Entities: `data/entities/register.json`
This is the monthly close for internal transfer prices. It does not book
spend, move money, or throttle a cluster.
## Monthly close
1. Close technical actuals for month `M` (`docs/portfolio-operating-cadence.md`).
2. Pull booked provider cost and any recognized internal payments from
`fin-hub`. If none exist, payment recognition stays `unknown`.
3. Run:
```text
make test
make settlement PERIOD=YYYY-MM
make portfolio-report
```
4. `make settlement` prints one JSON statement per consuming entity that
has a charge, credit, interest, or open balance. An empty array means
there was nothing to settle — not a zero bill.
5. Send the statements and the consumption-mode signal to `fin-hub` and
Railiance operations. Do not post them as booked spend here.
Statement date defaults to the first calendar day of `M+1`. Due date is
that date plus 10 calendar days. Interest is 5 % per year, simple monthly,
on overdue outstanding only.
## What is unknown without bank accounts
- `account_ref` on every entity is `null`. Pay-from / pay-to are present
as nulls, not invented.
- Recognized payments are `unknown` until `fin-hub` projects a payment
fact. Do not clear a balance from a chat message.
- Live `make settlement PERIOD=2026-08` emits `[]` because no control-cycle
actual has a known delivered-cost total and a consuming entity. That is
the correct answer.
## Human waiver
A limit change, interest waiver, or temporary unrestricted window is a
dated decision by human financial authority. Record it as evidence and
change the entity's `credit_limit_eur` in the register, or add a
successor terms file. Do not edit historical statements.
## Failure modes and owners
| Failure | Owner |
| --- | --- |
| Missing entity or untagged cost object | `resource-control` |
| Wrong transfer-price arithmetic | `resource-control` |
| Booked provider amount, tax, recognized payment | `fin-hub` |
| Restricted entity still consuming above allowance | Railiance platform / procurement |
| Bank account missing | Human financial authority |
| Parameter change (markup, limit, interest) | Human financial authority; new terms version |
## Consumption-mode signal
Railiance operations consumes:
```json
{
"schema_version": "0.1",
"record_type": "consumption_mode",
"financial_entity_id": "entity:coulomb",
"period": "2026-08",
"consumption_mode": "open",
"new_transfer_charges_allowed_eur": null,
"terms_version": "0.1"
}
```
`restricted` plus a non-null allowance is the only signal that should
refuse new orders or elastic usage. Committed provider contracts are
flagged, not cancelled (Terms OQ-2).
## Transfer-charge projection to fin-hub
`resource-control` publishes settlement statements as proposed charges.
Join keys: `financial_entity_id`, `period`, `resource_id`,
`terms_version`. A later booked internal settlement in `fin-hub` must
reference the statement, not replace it. See
`docs/fin-hub-resource-control-contract-v0.1.md`.