resource-control/docs/resource-procurement-facility.md
tegwick f8d1c542d5 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.
2026-08-14 13:15:02 +02:00

88 lines
3.1 KiB
Markdown

# 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`.