Harden resource cost evidence contract
This commit is contained in:
parent
080f756fff
commit
00343307fd
22 changed files with 1623 additions and 130 deletions
133
history/2026-08-11-resource-control-review-fin-wp-0004.md
Normal file
133
history/2026-08-11-resource-control-review-fin-wp-0004.md
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# Resource-control review of fin-hub results
|
||||
|
||||
Date: 2026-08-11
|
||||
Reviewer: `resource-control` / Codex
|
||||
Reviewed repository: `fin-hub`
|
||||
Reviewed commits: `d2b9bc4^..2895077`
|
||||
Primary workplans: `FIN-WP-0002`, `FIN-WP-0004`, `RESOURCE-WP-0003`
|
||||
State: changes requested before accepting the v0.1 exchange contract
|
||||
|
||||
## Conclusion
|
||||
|
||||
The fin-hub result is directionally strong, but the v0.1 resource-cost
|
||||
exchange contract is not yet ready for approval. Its authority matrix correctly
|
||||
separates booked financial facts in fin-hub from resource identity, technical
|
||||
usage, allocation evidence, forecasts, and optimization in resource-control.
|
||||
The client-attribution and engagement-margin work is a useful foundation.
|
||||
|
||||
Accounting-integrity and schema gaps remain. In particular, existing reports
|
||||
can combine incompatible currencies and environments, changed CSV imports can
|
||||
duplicate booked cost, and the SQLAlchemy and SQLite engagement-price paths do
|
||||
not enforce the same invariants. The exchange envelopes also need exact money,
|
||||
correction, and record-type semantics before implementation.
|
||||
|
||||
Verification on 2026-08-10:
|
||||
|
||||
- fin-hub worktree was clean at review time;
|
||||
- `uv run pytest -q` passed: 33 tests, one dependency deprecation warning;
|
||||
- a diagnostic reproduced EUR and USD service rows being combined into one
|
||||
EUR-labelled total.
|
||||
|
||||
## Findings and implementation pointers
|
||||
|
||||
| Severity | Finding | Required task |
|
||||
| --- | --- | --- |
|
||||
| High | Service reporting groups by `service_id` and month without preserving currency and environment dimensions. | `FIN-WP-0004-T07` |
|
||||
| High | CSV import identity is based on path and mtime; a changed or forced import appends the same booked rows again. | `FIN-WP-0004-T08` |
|
||||
| Medium | SQLAlchemy and SQLite engagement-price paths enforce different attribution, currency, amount, period, and revision invariants. | `FIN-WP-0004-T09` |
|
||||
| Medium | Booked-cost envelope does not define net, tax, gross, credit, refund, correction, decimal precision, or rounding relationships. | `FIN-WP-0004-T02` |
|
||||
| Medium | The common planning envelope's single `amount` is insufficient for infrastructure, labor, setup, usage, allocation, and savings evidence. | `FIN-WP-0004-T03` |
|
||||
| Low | fin-hub's canonical `INTENT.md` does not yet express booked-cost authority, client reporting, or the resource-control boundary. | `FIN-WP-0004-T01` |
|
||||
| Low | Workplan lifecycle language and frontmatter status disagree. | `FIN-WP-0004-T01` |
|
||||
|
||||
`FIN-WP-0004-T05` remains the acceptance gate: the first round trip must prove
|
||||
that a cost is booked once, projected to resource-control, joined to technical
|
||||
evidence, and returned as planning or variance evidence without becoming a
|
||||
second financial fact.
|
||||
|
||||
## Detailed findings
|
||||
|
||||
### 1. Currency and environment mixing
|
||||
|
||||
`src/fin_hub/coupling/ops_hub.py` keys service buckets only by `service_id`
|
||||
and monthly totals only by month. A diagnostic with a EUR production row and a
|
||||
USD development row for the same service produced one EUR-labelled total.
|
||||
|
||||
Service aggregation must use at least:
|
||||
|
||||
```text
|
||||
service_id × environment × currency
|
||||
month × currency
|
||||
```
|
||||
|
||||
Unattributed and attributed reports must expose the same dimensional rules and
|
||||
reconciliation totals.
|
||||
|
||||
### 2. Duplicate booked cost on changed imports
|
||||
|
||||
`src/fin_hub/services/ledger.py` treats `(source_path, source_mtime)` as import
|
||||
identity and inserts every row from every newly observed file version. This is
|
||||
file-delivery deduplication, not financial-fact idempotency. A corrected file or
|
||||
forced import can inflate burn, attributed cost, and margin.
|
||||
|
||||
Each booked row needs a stable `financial_fact_id`, source-document and
|
||||
source-line identity, content fingerprint, and explicit append-only
|
||||
correction/reversal relationship. Duplicate delivery must leave totals
|
||||
unchanged.
|
||||
|
||||
### 3. Divergent engagement-price invariants
|
||||
|
||||
The SQLite command path validates attribution components, period, currency,
|
||||
non-negative amount, source, and the current revision. The SQLAlchemy
|
||||
`EngagementPrice` model does not enforce equivalent rules and can persist a key
|
||||
that disagrees with its dimensions or an invalid price/revision state.
|
||||
|
||||
Both persistence paths should use the same domain validator and database
|
||||
constraints, with concurrency-safe uniqueness for the current price basis.
|
||||
|
||||
### 4. Monetary contract semantics
|
||||
|
||||
The booked-cost schema must define whether credits are signed, whether gross
|
||||
equals net plus tax, where discounts apply, how refunds/reversals work, how
|
||||
unknown tax is represented, and which precision and rounding rule applies.
|
||||
Exchange money should use decimal strings or integer minor units, not binary
|
||||
floating-point numbers.
|
||||
|
||||
### 5. Record-specific planning schemas
|
||||
|
||||
The common envelope may stay small, but `forecast`, `allocation`, `usage`,
|
||||
`optimization`, and `commitment_candidate` each need a concrete schema.
|
||||
Infrastructure cost, internal labor, external services, setup cost, recurring
|
||||
cost, technical units, allocation shares and residual, and expected savings
|
||||
must not be overloaded into one ambiguous `amount`.
|
||||
|
||||
### 6. Canonical intent and lifecycle alignment
|
||||
|
||||
`INTENT.md` should reciprocate the boundary already recorded in
|
||||
resource-control: fin-hub owns booked financial facts, budgets, commitments,
|
||||
burn, runway, and viability signals; it consumes resource-control projections
|
||||
without becoming authoritative for resource identity or technical allocation.
|
||||
|
||||
The workplan should no longer describe itself as proposed after its
|
||||
frontmatter is active. Joint review remains incomplete until these review
|
||||
results are incorporated and linked by both repositories.
|
||||
|
||||
## Decisions recommended for v0.1
|
||||
|
||||
- Keep client and infrastructure attribution identifiers in distinct,
|
||||
versioned namespaces under one common envelope.
|
||||
- Native service and workload identity stays with its owning repository.
|
||||
Resource-control may issue an explicitly scoped portfolio surrogate only
|
||||
where no native authority exists.
|
||||
- Rename resource-control `actual` records to `usage_observation` or
|
||||
`cost_observation`; reserve “booked actual” for fin-hub facts.
|
||||
- Each producer owns its outbound schema. The shared contract pins compatible
|
||||
versions and reconciliation rules; transport is selected after the backup
|
||||
round trip validates the model.
|
||||
|
||||
## Approval condition
|
||||
|
||||
Approve the authority boundary in principle. Keep `FIN-WP-0004-T01` in
|
||||
progress until the contract incorporates this assessment. Do not mark the
|
||||
v0.1 exchange accepted until `FIN-WP-0004-T02`, `T03`, `T07`, `T08`, and `T09`
|
||||
are complete and `T05` demonstrates an idempotent reconciled round trip.
|
||||
Loading…
Add table
Add a link
Reference in a new issue