## Findings No P0 findings. - **P1 — Account filter is ambiguous and fails open.** `src/jarvis_finance/api/routers/budget.py:264-278`, `src/jarvis_finance/services/household_financials.py:83-89`, `src/jarvis_finance/services/household_import.py:2262-2266` The canonical account filter uses mutable, non-unique account names. `budget_accounts.name` has no uniqueness constraint, so selecting one name includes every account sharing it; names containing commas cannot be represented. Unknown names silently return CHF 0.00 with `data_status=current`. Reproduced with two `"Household A"` accounts: the filtered cockpit included both accounts. **Fix:** expose and filter by stable opaque `budget_account_id`/token, validate every supplied token exists, reject unknown/duplicate-invalid selections with 422, and propagate the same IDs through drilldowns and pagination scope. - **P1 — Category drilldowns do not reconcile with valid refunds.** `src/jarvis_finance/services/household_cockpit.py:186-203`, `src/jarvis_finance/services/household_import.py:2267-2269` Category totals include valid refunds as negative expense effects, but generated drilldowns force `type=expense`, excluding those refund transactions. A CHF 100 expense plus linked CHF 10 refund produced a CHF 90 category, while its drilldown returned only the CHF 100 expense. The URL also filters by fuzzy category name rather than `category_id`, so duplicate/similar names can include unrelated categories. **Fix:** drill down using stable `category_id` and an effect-semantic filter that includes expenses/fees plus valid linked refunds; verify the drilldown’s summed expense effect equals the category total within CHF 0.01. - **P1 — Account-filtered budget remaining mixes incompatible scopes.** `src/jarvis_finance/services/household_cockpit.py:216-258`, especially `:230` and `:239-256` `get_budget_status_by_category()` supplies an all-account budget/forecast, while `actual` comes from account-filtered rows. The API then reports `remaining_chf = all-account budget - selected-account actual` and publishes it as a KPI. Reproduced: the same CHF 225 household budget became CHF 215 remaining for account A and CHF 125 for account B, neither representing a valid account budget. Only forecast scope is disclosed; budget/remaining scope is not. **Fix:** either add canonical account-level budget allocation, or return budget/remaining as unavailable when account filters are active. Do not publish a mixed-scope `budget_remaining_chf`; expose explicit scope/method for every budget field. - **P1 — Cockpit snapshot version is incomplete and not consistency-checked.** `src/jarvis_finance/services/household_cockpit.py:319-383`, `src/jarvis_finance/services/household_import.py:2175-2193` Cockpit `data_version` hashes only confirmed transactions, categories, and accounts. The response also depends on budget plans/planning inputs, transfer memberships, review candidates/counts, and settlement relations. Updating a budget plan changed `budget_chf` from CHF 225 to CHF 1,074 while `data_version` remained identical. The version is calculated only after all reads, so a concurrent write can also produce mixed old/new sections labeled with the final version. **Fix:** use a cockpit-specific snapshot revision covering every dependency, and execute all reads in one SQLite read transaction or compare the complete revision before and after assembly and return 409 on change. - **P1 — Open-review quality is global, date-unfiltered, and can still report `current`.** `src/jarvis_finance/services/household_cockpit.py:370-408` `get_household_review(limit=1)` supplies a global all-date count. Without an account filter, open reviews do not add any quality warning, so unresolved candidates excluded from financial totals can coexist with `data_status=current`. With account filters, the warning discloses only global account scope, not that the count also ignores the selected date range. **Fix:** compute a date-scoped review count under the canonical filter where reliable; mark monetary quality partial whenever unresolved in-scope rows are excluded. Where candidate account binding is unavailable, return an explicit global/unavailable quality scope rather than presenting the result as current. - **P2 — One cockpit request performs multiple unbounded full-dataset scans.** `src/jarvis_finance/services/household_cockpit.py:319-383`, `src/jarvis_finance/services/household_import.py:2175-2188`, `:2769-2942` The bounded date-range cockpit hashes every historical confirmed transaction, invokes the full review-page builder—which hashes numerous tables twice and builds groups/options despite needing one count—and runs full-year budget/planning services for each touched year. Latency therefore grows with all ledger/review history rather than the selected range. **Fix:** use persisted revision counters/change-log versions, a dedicated lightweight review-count query, and reuse scoped effect rows when invoking canonical budget services. ## Verification - Reviewed every backend/data diff, including both untracked files. - Focused suites: **131 passed**. - Deterministic probes reproduced the snapshot, duplicate-account, mixed-budget-scope, unknown-account, and refund-drilldown failures. - No private data or concrete new security vulnerability found. - **Files modified:** none. - Initial worktree `.venv` lacked pytest; used the available project-compatible pytest environment.