## Findings ### Important 1. **A file replacement during an in-flight Preview can restore a stale Preview for different files.** The file inputs remain enabled while `actionLoading` is true. `selectFile()` clears the current Preview, but an earlier `doPreview()` response can subsequently assign its old result back to `preview.value`. Once the replacement finishes, the page can display old Preview IDs alongside the new payload and allow Confirm. The backend should reject the fingerprint mismatch, but the UI presents misleading approval state and turns a safety invariant into an error-path dependency. Disable file replacement during Preview/Confirm or bind responses to a payload/request generation. References: `frontend/src/pages/PostFinancePage.vue:46`, `:52`, `:172-196`, `:212-213` 2. **Strict browser MIME checks can reject valid files selected from iPadOS Files.** The client requires an exact non-empty `File.type`. Safari/iPadOS and document-provider files can report an empty or generic MIME type even when the extension and bytes are valid. Those files are rejected before the backend’s ZIP/PDF magic-byte validation runs, making the advertised iPad upload path unreliable. Treat browser MIME as advisory and submit a canonical MIME after extension/byte validation. Reference: `frontend/src/pages/PostFinancePage.vue:181-186` ### Moderate 3. **The new route’s open state is only read once, so navigation between the two PostFinance routes can show the wrong view.** Both routes render the same component, and `` is not keyed. Vue Router can reuse the component instance, but `showImport` is initialized from `initialImportOpen` only once and never watches later prop/route changes. Navigating `/portfolio/postfinance` → `/postfinance/imports/preview` may leave the import form closed; back-navigation can leave it open on the summary route. References: `frontend/src/router/index.ts:49-50`, `frontend/src/pages/PostFinancePage.vue:124`, `:139`, `frontend/src/components/AppLayout.vue:15` 4. **One global file generation counter makes the two independent file reads cancel each other.** Selecting the PDF while a large ZIP is still being converted increments `fileGeneration`; the ZIP completion is then discarded even though it is not a stale ZIP replacement. This is especially plausible with the newly accepted 50 MB ZIPs on an iPad. Use separate generations per file kind. References: `frontend/src/pages/PostFinancePage.vue:143`, `:172-196` 5. **Successful Confirm clears reactive payload state but leaves native file inputs populated.** Unlike `resetUpload()`, the success path does not clear `zipInput.value.value` or `overviewInput.value.value`. The labels show no selection, yet choosing the same files again may not emit `change`, forcing an otherwise unexplained reset or different-file selection. References: `frontend/src/pages/PostFinancePage.vue:199-208`, `:213` ## Checks - Focused frontend test: **3 passed** - Typecheck: **passed** - `git diff --check`: **passed** - No provider/import calls occur on render; mount performs only local health/runtime/summary GETs. - Confirm is deliberately gated by an explicit checkbox and backend `confirm_allowed`. - Files modified by review: **none**.