# Observed Crypto Balance Reconciliation Cockpit

Use when a crypto ledger has a trusted historical anchor but current wallet/exchange quantities and intervening activities are incomplete. The goal is to update the observable quantity basis without fabricating transactions or opening performance prematurely.

## State model

Keep three independent truths:

1. **Ledger anchor** — the last fully evidenced historical holdings snapshot.
2. **Observed endpoint** — a user-confirmed or import-confirmed current quantity set, append-only and timestamped.
3. **Activity/cashflow coverage** — whether all trades, rewards, fees, deposits, withdrawals, and internal transfers between those dates are reconciled.

An observed endpoint may replace the quantity basis used for present valuation. It does **not** prove the intervening ledger, cost basis, XIRR, TTWROR, or external cashflows.

## Data contract

- Store observed snapshots, wallet coverage, and snapshot items in append-only tables.
- A confirmed snapshot is immutable; corrections create a new snapshot/version.
- Bind Preview to the complete wallet/asset input, `as_of`, source mode, and current baseline through a fingerprint.
- Confirm revalidates the baseline under the write transaction and writes snapshot + items + audit atomically.
- Replay of the same confirmation returns the original identity and adds zero rows.
- Include every productive wallet/exchange in the coverage matrix, including empty/zero-balance entries.
- Never merge similarly named wallets without authoritative identity evidence.
- Redact addresses/account references from ordinary read models and tracked evidence.

A full-current snapshot should explicitly account for every productive wallet. If partial snapshots are supported, never silently treat absent wallet/asset rows as zero; carry forward only under an explicit, visible policy.

## Reconciliation semantics

For each wallet/asset show:

- anchor quantity;
- observed quantity;
- delta;
- activity-source coverage;
- balance-source coverage;
- unresolved reason.

A quantity delta is evidence of a mismatch, not evidence of a buy, sell, reward, fee, or external flow. Do not materialize an activity from the delta.

Internal transfers require two evidenced legs and an explicit durable pair relation. Match only when asset, quantity after evidenced fees, timing, source/destination identities, and source records make the pair unambiguous. Ambiguous candidates remain unpaired and visible.

## Valuation and performance gates

- Resolve current quantities from the latest confirmed observed snapshot; otherwise fall back to the ledger anchor.
- Keep `balance_as_of`, `price_as_of`, `snapshot_id`, and `balance_confirmed_current` separate in API contracts.
- Ordinary cockpit GET/render paths make zero provider calls.
- A current price applied to historical quantities is only an **unconfirmed estimate**, never an unrestricted “current portfolio value.”
- Put the qualification adjacent to every prominent value/KPI, not only in a lower reconciliation panel. Suggested wording: `Preis aktuell, Bestandsmengen per <date> – aktueller Portfoliowert nicht bestätigt.`
- Asset-row labels such as `price_status=Aktuell` must not imply quantity freshness; display quantity/balance freshness separately.
- Keep performance closed until activity, external cashflow, fee/reward, transfer, and endpoint coverage are complete for the selected period.

## Implementation sequence

1. Inventory the exact production schema, wallet count, holdings count, assets, last confirmed anchor, activity count, service/timer states, and integrity/FKs read-only.
2. Reuse existing wallet, import, transfer, valuation, audit, and Preview/Confirm machinery.
3. Add the smallest additive migration for immutable observed snapshots and explicit transfer pairs.
4. Centralize current-balance selection in one resolver and route every present-value reader/job through it.
5. Add coverage/template/reconciliation endpoints before UI work.
6. Build the cockpit with coverage, dates, unresolved differences, performance gate, and safe manual entry.
7. Test migration, Preview no-write, Confirm atomicity, replay zero-row delta, latest-snapshot selection, fallback anchor, provider-free GET, and closed performance.
8. Update all frontend mocks that mount a parent page; a newly mounted child API call can break unrelated mobile/page tests even when the feature test passes.
9. Run focused tests, full remote CI once on the frozen candidate, merge, and record the exact full merge SHA.
10. Backup production, migrate an isolated restore copy, compare all pre-existing table counts/digests, then perform the consent-gated stop/migrate/restart.
11. After startup readiness, verify schema/integrity/FKs, exact SHA, routes, repeated identical GETs, zero new snapshot/audit rows before user confirmation, UI status text, console errors, and timer states.

## Release evidence

Record only aggregate, non-sensitive evidence:

- old/new schema and migration count delta;
- integrity/FK result;
- unchanged pre-existing table counts/digest;
- new-table row counts before any business Confirm;
- wallet/coverage counts, not addresses;
- exact merge SHA and CI job conclusions;
- service state and readiness-aware health result;
- repeated GET equality and `render_provider_calls=false`;
- visible balance date, price date, unconfirmed-value warning, and closed performance reason.

## Pitfalls

- “No recorded activities” means missing coverage, not no real-world activity.
- Equal endpoint quantities do not prove no intervening transfers or adjustments.
- A green valuation number does not prove current quantities.
- Updating the interactive positions reader but not the scheduled valuation writer creates two quantity truths.
- Omitting zero-balance wallets makes completeness unknowable.
- A lower-page warning does not cure an unrestricted top-level `Crypto Gesamtwert` KPI.
- Immediate health probes can race service startup; inspect unit state/logs and retry readiness without rerunning migration.
- Do not use a delayed background completion notification as renewed consent for a previously blocked service/migration action.
