# Broker Parser Dry-Run Pipeline Pattern

Use this reference after the Import Wizard / Mapping Layer exists, when adding parser output to the review workflow for PostFinance, True Wealth, Raiffeisen, or similar broker/bank statements.

## Purpose

Turn broker/bank parser results into safe dry-run summaries and runtime-only review items. This phase must still avoid productive ledger, snapshot, holdings, or cash writes unless the user explicitly approves a later import phase.

## Sequencing and guardrails

1. Start with synthetic DOCX/XLSX fixtures that mimic real source structure.
2. Do not commit real broker/bank files, raw rows, quantities, market values, or generated runtime DBs.
3. Real files may only be read from runtime/temp for structural dry-runs; report aggregate counts and quality flags only.
4. Keep Import Wizard and review actions read-only by default.
5. Do not pivot into analytics modules such as Monte Carlo, backtesting, rebalancing, scores, projections, or heatmaps during import hardening.

## Parser behavior by source

### PostFinance DOCX/table parser

Extract candidates from DOCX table rows:

- product/name label
- quantity-present boolean, not quantity value in chat/docs
- currency
- market-value-present boolean
- account/depot context
- snapshot date when recognizable

Expected quality flags:

- `missing_isin`
- `missing_ticker`
- `snapshot_only`
- `cost_basis_uncertain`
- `market_value_legacy`
- `needs_manual_review`

### True Wealth DOCX/mixed-table parser

Extract:

- cash rows
- position-like rows
- portfolio/account context
- currency
- snapshot date when recognizable

Expected quality flags:

- `missing_isin`
- `missing_ticker`
- `snapshot_only`
- `cost_basis_uncertain`
- `missing_fx` for non-CHF rows without FX
- `needs_manual_review`

### Raiffeisen XLSX account/control parser

Extract:

- cash/account rows
- aggregate custody/investment rows

Rules:

- Treat Raiffeisen defensively as cash/control snapshot when detailed instrument fields are absent.
- Do not create instrument positions from aggregate-only rows.

Expected quality flags:

- `cash_snapshot_candidate`
- `aggregate_only`
- `missing_instrument_details`
- `needs_manual_review`

## Runtime-only review items

Add/maintain `broker_import_review_items` for row-level review data in the runtime DB only.

Fields:

- `review_item_id`
- `dry_run_id`
- `source_platform`
- `source_file_type`
- `source_row_ref`
- `row_hash`
- `source_label`
- `normalized_name`
- `detected_asset_class`
- `detected_currency`
- `detected_quantity_present`
- `detected_market_value_present`
- `isin`
- `ticker`
- `exchange`
- `mapped_instrument_id`
- `mapped_account_id`
- `quality_flags_json`
- `review_status`: open, mapped, ignored, blocked, resolved
- `reviewer_note`
- timestamps

Rules:

- Review item details are runtime-only and must not be written to Git fixtures/docs when they come from real files.
- In chat/reporting, output only aggregate counts and quality flag summaries.
- Manual mapping or status changes must require a non-empty note and create an audit-log entry.

## Generic dry-run pipeline

1. Parse source file.
2. Normalize candidates.
3. Attempt instrument mapping using existing mapping rules: ISIN primary; ticker+exchange fallback; name-only never auto-maps.
4. Attempt account mapping when account context exists.
5. Set quality flags.
6. Write `broker_import_dry_runs` aggregate summary.
7. Write `broker_import_review_items` row-level runtime review records.
8. Do not write `positions_snapshot`.
9. Do not write transactions, cash ledger, crypto holdings, or productive snapshots.
10. Return aggregate output: `rows_total`, `candidate_positions`, `candidate_cash_rows`, `mapped_positions`, `blocked_positions`, `review_items_created`, `warnings_count`, `errors_count`, `quality_flags_summary`.

## UI extensions

Import Wizard should show parser/dry-run summary, quality flag counts, runtime review items, and a visible link/path to Manual Review Queue. Productive commit buttons remain disabled in read-only mode.

Manual Review Queue should show review items with source, label, normalized name, asset class, currency, ISIN, ticker, exchange, mapped instrument/account, quality flags, and status. Prepare actions for adding identifiers, confirming mappings, ignoring with note, or resolving, but keep productive position creation disabled.

Data Quality Center should aggregate open review items by quality flag, including `missing_isin`, `missing_ticker`, `snapshot_only`, `cost_basis_uncertain`, `missing_fx`, `aggregate_only`, plus existing stale/missing price and alert lifecycle checks.

Global Safe Mode should be visible in the dashboard shell or Command Center: DB mode, write mode, last backup if known, Git-safety status if known, and reminder that real data lives outside Git. Default is read-only.

## Test matrix additions

Add tests for:

- synthetic PostFinance parser candidate detection and flags
- synthetic True Wealth parser candidate detection and flags
- synthetic Raiffeisen cash/control and aggregate-only detection
- dry-run summary creation
- review item creation
- no productive positions/ledger writes
- name-only rows stay review-gated
- Raiffeisen aggregate-only rows are blocked, not instrument positions
- Manual Review Queue loads review items
- Data Quality Center aggregates review flags
- default safe mode is read-only
- commit actions remain disabled
- audit log on review-item mapping/status change
- no real DOCX/XLSX/PDF files in the repo
- Git-safety remains OK
