# Broker Mini-Import Regression and Safe Corrections

Use after the first productive broker/equity/ETF `initial_position_snapshot` import and before any broader import wave.

## Regression checks

Run aggregate-only checks; never echo real quantities, values, account balances, raw rows, or file contents.

Verify for each controlled mini-import:

- exactly the expected number of productive `transactions` rows exists
- `transaction_type = initial_position_snapshot`
- `source_type = broker_import_reviewed_snapshot`
- linked `execution_plan_id`, `review_item_id`, `instrument_id`, and `account_id` exist
- `quantity` is present and parseable with Python `Decimal`; never convert through float
- quality status is `warning`/`incomplete` when FX, cost basis, or market price is missing
- audit log exists for both execution and review-item status change
- execution plan status is `imported`
- review item status is `imported`
- direct `positions_snapshot` writes remain zero for the import
- no cash snapshots are created unless explicitly part of an approved cash import

## Re-import protection

Implementation should block both:

- same `execution_plan_id` / source ID / external transaction ID
- same source row hash when it would duplicate a reviewed broker snapshot

Tests should cover both paths with synthetic fixtures.

## Position calculation and data quality

Position/cash calculators must ignore voided rows (`is_voided=1`). For snapshot-only imports with missing FX/price/cost basis:

- calculate quantity/position existence from the ledger
- degrade data quality rather than inventing complete performance
- suppress precise Total Return CHF when required inputs are missing
- surface quality flags such as `missing_fx`, `missing_market_price`, `cost_basis_uncertain`, and `snapshot_only`

## Safe correction / reversal pattern

Never physically delete productive transactions.

Preferred model:

- Add transaction columns: `is_voided`, `voided_at`, `void_reason`, `voided_by`, `correction_of_transaction_id`, `correction_reason`.
- `void_transaction` must require a non-empty note, write an audit log, keep the original row, and create/update a data-quality alert such as `voided_transaction`.
- `correction_transaction` should be a new transaction linked to the old one via audit metadata; the old row remains visible.
- Position and cash calculations should ignore voided rows or explicitly mark them as non-active.

## Backup/restore regression

Before the next mini-import:

1. Create a runtime DB backup outside Git.
2. Verify backup checksum with `verify-backup`.
3. Restore to a separate test DB path, not the productive DB.
4. Confirm the restore succeeds and the productive DB is unchanged.
5. Run Git-safety after backup/restore/test activity.

## Optional next mini-import gate

Only after checks above pass, import exactly one remaining ready execution plan:

- backup first and verify it
- consume one `planned`/`ready` execution plan
- write one ledger `initial_position_snapshot`
- mark only that execution plan and review item imported
- leave other ready plans unchanged
- run aggregate checks, tests, Git-safety, and Git status

## Test coverage checklist

- duplicate execution-plan import blocked
- duplicate source-row-hash import blocked
- void/storno requires note
- void/storno writes audit
- voided transaction excluded from active position/cash calculation
- correction transaction audit link created
- missing FX snapshot remains warning/incomplete
- no fake precise Total Return when data is missing
- backup after import
- restore to separate test DB does not alter productive DB
- Git-safety OK
