Harden resource cost evidence contract
This commit is contained in:
parent
080f756fff
commit
00343307fd
22 changed files with 1623 additions and 130 deletions
|
|
@ -1,7 +1,9 @@
|
|||
# Fin-hub ↔ resource-control authority contract v0.1
|
||||
|
||||
Status: draft for joint review
|
||||
Owners: `fin-hub` / `resource-control`
|
||||
Status: authority boundary reviewed; v0.1 implementation acceptance pending
|
||||
|
||||
Owners: `fin-hub` / `resource-control`
|
||||
|
||||
Workplans: `FIN-WP-0004-T01`, `RESOURCE-WP-0003-T02`
|
||||
|
||||
## Boundary
|
||||
|
|
@ -51,6 +53,19 @@ identifier and consumers preserve it byte-for-byte.
|
|||
exchange also carries `financial_fact_id`, period, currency, and provenance;
|
||||
every technical exchange carries its record ID and resource/workload context.
|
||||
|
||||
## Identifier decisions
|
||||
|
||||
- Client and infrastructure attribution identifiers remain distinct,
|
||||
versioned namespaces under this common envelope.
|
||||
- Native service/workload identity stays with its owning repository;
|
||||
resource-control may issue a clearly scoped portfolio surrogate only when no
|
||||
native authority exists.
|
||||
- `usage_observation` is the technical observation record. “Booked actual” is
|
||||
reserved for fin-hub financial facts.
|
||||
- Each producer owns its outbound schema. This contract pins compatible
|
||||
versions and reconciliation; transport is selected after the backup round
|
||||
trip.
|
||||
|
||||
## Fin-hub → resource-control: booked-cost evidence
|
||||
|
||||
Minimum envelope:
|
||||
|
|
@ -61,17 +76,24 @@ Minimum envelope:
|
|||
"record_type": "booked_cost",
|
||||
"financial_fact_id": "opaque",
|
||||
"correction_of": null,
|
||||
"adjustment_kind": "charge",
|
||||
"source_type": "provider_invoice",
|
||||
"source_document_id": "opaque",
|
||||
"source_line_id": "opaque",
|
||||
"content_fingerprint": "sha256",
|
||||
"provider": "opaque-provider-id",
|
||||
"provider_account_ref": null,
|
||||
"accounting_period": "YYYY-MM",
|
||||
"service_period_start": "YYYY-MM-DD",
|
||||
"service_period_end": "YYYY-MM-DD",
|
||||
"currency": "EUR",
|
||||
"net_amount": 0,
|
||||
"tax_amount": 0,
|
||||
"gross_amount": 0,
|
||||
"credit_amount": 0,
|
||||
"net_amount": "10.00",
|
||||
"discount_amount": "0.00",
|
||||
"tax_status": "known",
|
||||
"tax_amount": "1.90",
|
||||
"gross_amount": "11.90",
|
||||
"adjustment_amount": "0.00",
|
||||
"effective_amount": "11.90",
|
||||
"resource_id": null,
|
||||
"service_id": null,
|
||||
"workload_id": null,
|
||||
|
|
@ -87,6 +109,15 @@ Delivery is idempotent on `financial_fact_id`. Corrections append a new record
|
|||
with `correction_of`; consumers retain both and calculate the effective value.
|
||||
Unknown attribution stays null and remains visible in reconciliation.
|
||||
|
||||
Money uses decimal strings at two fractional digits, ISO 4217 currency, and
|
||||
round-half-even. `net_amount`, `discount_amount`, and `gross_amount` are
|
||||
non-negative. When tax is known, `gross = net - discount + tax`; unknown tax is
|
||||
represented by `tax_status: unknown` and `tax_amount: null` without inventing a
|
||||
net/tax split. `adjustment_amount` is signed and `effective = gross +
|
||||
adjustment`; credits, refunds, and reversals require a negative adjustment and
|
||||
an explicit predecessor. The executable schema is
|
||||
`fin_hub.schemas.exchange.BookedCostEvidence`.
|
||||
|
||||
## Resource-control → fin-hub: planning and allocation evidence
|
||||
|
||||
Minimum common envelope:
|
||||
|
|
@ -94,7 +125,7 @@ Minimum common envelope:
|
|||
```json
|
||||
{
|
||||
"schema_version": "0.1",
|
||||
"record_type": "forecast|allocation|usage|optimization|commitment_candidate",
|
||||
"record_type": "forecast|allocation|usage_observation|optimization|commitment_candidate",
|
||||
"record_id": "opaque",
|
||||
"revision_of": null,
|
||||
"resource_id": "resource:opaque",
|
||||
|
|
@ -106,20 +137,28 @@ Minimum common envelope:
|
|||
"period_start": "YYYY-MM-DD",
|
||||
"period_end": "YYYY-MM-DD",
|
||||
"currency": "EUR",
|
||||
"scenario": "low|base|high|observed",
|
||||
"amount": 0,
|
||||
"uncertainty": null,
|
||||
"method": "versioned method identifier",
|
||||
"assumptions": [],
|
||||
"source_evidence": [],
|
||||
"created_at": "RFC3339 timestamp"
|
||||
}
|
||||
```
|
||||
|
||||
Record-specific schemas add usage units, allocation drivers and shares,
|
||||
service constraints, or optimization-case economics. Delivery is idempotent
|
||||
on `record_id`; revisions are append-only. Fin-hub stores these as planning or
|
||||
analytical evidence and never in its booked-cost ledger.
|
||||
The common envelope deliberately has no generic `amount`. Executable,
|
||||
record-specific schemas in `fin_hub.schemas.exchange` define:
|
||||
|
||||
- `ForecastEvidence`: scenario/version, uncertainty, assumptions, and separate
|
||||
infrastructure, internal-labor, external-service, setup, and other costs;
|
||||
- `UsageObservation`: named decimal measures with explicit units and no booked
|
||||
cost semantics;
|
||||
- `AllocationEvidence`: referenced financial facts, method, allocated amount,
|
||||
target shares, and explicit residual that must reconcile to one;
|
||||
- `OptimizationEvidence`: baseline/alternative breakdown, one-time cost, and
|
||||
expected period savings; and
|
||||
- `CommitmentCandidate`: setup/recurring cost, cadence, term, and immutable
|
||||
candidate approval status.
|
||||
|
||||
Delivery is idempotent on `record_id`; revisions are append-only and must
|
||||
reference the current record of the same type. Fin-hub stores these in
|
||||
`planning_evidence`, never in its booked-cost ledger.
|
||||
|
||||
## Reconciliation invariants
|
||||
|
||||
|
|
@ -135,13 +174,10 @@ analytical evidence and never in its booked-cost ledger.
|
|||
6. Missing joins, unknown tax semantics, and unattributed residuals are
|
||||
observable data-quality states, not zero values.
|
||||
|
||||
## Review questions
|
||||
## Acceptance status
|
||||
|
||||
- Should client attribution keys and infrastructure allocation keys share one
|
||||
namespaced grammar, or remain explicitly separate formats?
|
||||
- Which repository assigns `service_id` and `workload_id` where no workload
|
||||
repository already owns them?
|
||||
- Does resource-control's `actual` record type mean technical observation only,
|
||||
or should it be renamed to prevent confusion with fin-hub booked actuals?
|
||||
- Which transport and schema registry become canonical for v0.1 after the
|
||||
authority matrix is accepted?
|
||||
Resource-control accepted the authority boundary in principle on 2026-08-11.
|
||||
The review is preserved at
|
||||
`history/2026-08-11-resource-control-review-fin-wp-0004.md`. Contract v0.1 is
|
||||
not accepted until the implementation-integrity tasks and reconciled backup
|
||||
round trip pass.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue