Bug: provider passed the WF UUID as Account.id. ensure_account looks up
existing accounts by (provider, providerAccountId=Account.id), so the
WF-UUID-as-providerAccountId would never match the manually-created
account (which has providerAccountId=U13279690), causing the pipeline
to create a duplicate WF account on every cron run.
Fix: Account.id is now the IBKR account number (U13279690) throughout.
The pipeline's _ensure_accounts() resolves it to the WF UUID via the
canonical (provider, providerAccountId) lookup; activities are remapped
before import. CLI no longer takes the WF UUID — derives it post-import
via a cheap idempotent ensure_account call for the reconciliation step.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Maps Trades (BUY/SELL) and CashTransactions (DIVIDEND, TAX, INTEREST, FEE,
DEPOSIT, WITHDRAWAL) from an IBKR Flex Activity Query to broker-sync
Activity objects. Adds canonical_symbol helper (LSE → .L suffix when
exchange=LSE* or currency=GBP). Exposes OpenPositions for the
reconciliation step that runs at the CLI layer.
Guards against wrong-account writes by checking
stmt.accountId == IBKR_ACCOUNT_ID_UPSTREAM before yielding any activities.
13 unit tests cover all the mappings + the mismatch guard.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>