# Sprint 13 — PostFinance verified document, ledger and cost-basis import

## Scope

Sprint 13 adds a local-only, audited PostFinance import for the verified document ZIP and the separate account/portfolio overview. Real customer sources, raw extracted text, customer/account identifiers, complete source hashes, security identifiers and transaction details are not part of Git.

## Safety contract

- ZIP traversal, symlink, encrypted-entry, file-count, file-size, compression-size, extension and PDF gates run before parsing.
- Preview decodes, hashes and parses both original sources fully and performs no writes.
- Confirm requires explicit confirmation, decodes, hashes and parses original bytes again, verifies preview identity and database revision, then persists the batch atomically.
- Source ZIP, overview and contained PDFs are archived outside Git with `0700` directories and `0600` files.
- Documents are immutable and identified by original hash plus semantic business identity. Same bytes are idempotent; same business identity with different bytes is blocked.
- Batch, document links, snapshot, cash, positions, ledger events, components, cost-basis lots, canonical portfolio projections and audit are committed together.
- Confirm failure rolls back the database and removes newly created archive files.

## Financial model

The model keeps three source roles separate:

1. E-Finance cash account;
2. E-Trading depot;
3. E-Trading multi-currency cash attached to the depot.

Supported economic events are buys, sells, dividends, withholding taxes, fees, interest, internal transfers, FX metadata and non-cash corporate actions. Internal transfer legs share a transfer group and use canonical `activity_kind=internal_transfer`; they are not external income or expense.

Provider-reported average acquisition values and totals are stored exactly as snapshot facts. Calculated cost basis is derived only from imported acquisition/disposal lots and associated documented charges. If the source bundle does not prove the complete opening history, calculated basis remains `partial` instead of being inferred from market value.

The official account overview is persisted as a snapshot. It does not create synthetic trades. Latest positions, currency cash and the official account-value snapshot are projected once into the existing portfolio read model, while source-specific immutable tables retain provenance.

## API and UI

- `POST /api/postfinance/imports/preview`
- `POST /api/postfinance/imports/confirm`
- `GET /api/postfinance/summary`
- responsive page: `/portfolio/postfinance`

The page shows official totals, reconciliation, position-level provider versus calculated basis, currency cash, event counts and import history. Confirm is disabled for source conflicts or failed reconciliation.

## Verification

CI uses synthetic fixtures only. Coverage includes ZIP safety, complete snapshot reconciliation, preview side-effect freedom, confirm reparse, immutable rows, atomic persistence, rollback/archive behavior, account-role separation, canonical internal-transfer classification, cost-basis separation, conflict blocking and bundle/document/event idempotency.
