# Parser Private Fixture Gate Real bank statements contain personal financial data and are **never committed** to Git (`.gitignore` at the repo root covers this; keep fixture directories outside the repository). CI runs synthetic fixtures only. ## Contract - Synthetic parser inputs live with the backend tests and run in CI. - Real statement files stay in a local `PRIVATE_FIXTURES_DIR`, never in Git, never in shared storage without encryption. - The private suite runs explicitly, on the developer's machine: ```sh PRIVATE_FIXTURES_DIR=/secure/path/fixtures uv run pytest -m private_fixtures ``` (Exact marker/task names are finalized by the backend workstream; the entry point contract is `PRIVATE_FIXTURES_DIR` + a dedicated pytest marker.) ## Beta gate per adapter/contract An adapter may be declared beta-supported only when, against **private** fixtures: - [ ] at least two complete real periods of its contract parse successfully; - [ ] malformed file fails with stable diagnostics (no crash, no partial state); - [ ] oversized file is rejected by quotas before parsing; - [ ] duplicate statements produce identical parse results (hash-idempotent enqueue/apply); - [ ] overlapping periods produce expected duplicate candidates for review, not silent merges; - [ ] wrong-bank/encrypted/scanned (no text layer) files are detected and refused. Record the gate result per adapter version below. An adapter without a passed gate must not be enabled or advertised, even if synthetic tests pass (plan §"Основные риски и gates"). ## Gate status | Adapter / parser version | Private periods passed | Gate | | --- | --- | --- | | Alfa debit XLSX | — | **not passed** | | Alfa credit XLSX | — | **not passed** | | Ozon debit PDF | — | **not passed** | | Ozon credit PDF | — | **not passed** | | Rocketbank debit PDF | — | **not passed** | No adapter is currently gated. Bank layout drift resets the gate: it must create a new parser version and a review diff, never reinterpret historical data.