|
1 | 1 | ## What's New |
2 | 2 |
|
3 | | -This release puts your **project's area hierarchy** at the center of every view. Work items, household items, pickers, budget summaries, and every embedded reference now surface the full area ancestor path (`House / Ground Floor / Kitchen`) as a breadcrumb, so you always know where a task, item, or cost belongs. Budget Sources gains inline expansion with multi-select mass-move, Budget Overview replaces the category breakdown with an expandable area tree and adds clickable summary tiles plus print-friendly output, and Vendors moves into the Settings section to match how the rest of the app is organized. |
| 3 | +This release sharpens the **Budget Overview** so every cost in your project is traceable to the source funding it. Every line in the Cost Breakdown now carries a colored source attribution badge, the **Available Funds** row expands into a per-source Cost / Payback / Net view, and clicking a source detail row toggles it on or off -- with the entire breakdown (totals, projections, and subsidy math) recalculated server-side and the selection persisted in the URL so you can bookmark, share, or refresh a filtered view. |
4 | 4 |
|
5 | 5 | ### What's new |
6 | 6 |
|
7 | | -**Area hierarchy, everywhere it matters** |
| 7 | +**Source attribution everywhere** |
8 | 8 |
|
9 | | -- Work items and household items display the full area ancestor path as a breadcrumb on list pages, detail pages, and create pages. |
10 | | -- Pickers (work item, household item, budget line) show the area as a secondary line under each result. |
11 | | -- Every place a work item is embedded -- diary entries, invoices, household item dependencies -- now includes the area breadcrumb for instant context. |
12 | | -- A shared `AreaBreadcrumb` component keeps the appearance consistent across the app. |
| 9 | +- Every leaf-level budget line in the Cost Breakdown shows a deterministic, color-coded badge for its financing source -- the same source always gets the same color across the table, between sessions, and in light and dark mode. |
| 10 | +- On desktop the badge shows the full source name; on mobile it collapses to a colored dot to keep rows compact. |
| 11 | +- A 10-slot palette guarantees consistent contrast in both themes; budget lines without a source assignment use a reserved "Unassigned" color. |
13 | 12 |
|
14 | | -**Smarter area filters** |
| 13 | +**Available Funds row redesign** |
15 | 14 |
|
16 | | -- The Area filter on Work Items and Household Items lists correctly matches every descendant when you pick a parent area, at any depth of nesting. |
17 | | -- A dedicated **No Area** option on both lists surfaces items that have not yet been assigned to any area. |
| 15 | +- Click the **Available Funds** row to expand it and see one row per financing source. |
| 16 | +- Each source row shows three numbers in dedicated columns: **Cost** (allocated against budget lines, perspective-aware), **Payback** (subsidy payback against lines funded from that source), and **Net** (remaining headroom after cost and payback). |
| 17 | +- It's the fastest way to spot which source is most depleted, which one is being subsidized, and which one still has slack. |
18 | 18 |
|
19 | | -**Budget Overview redesign** |
| 19 | +**Per-source filter** |
20 | 20 |
|
21 | | -- The cost breakdown is now grouped by **area hierarchy** instead of by category, with nested rows you can expand to drill into children and leaf-level budget lines. |
22 | | -- The old "Unassigned" bucket is renamed **No Area** to match the rest of the app. |
23 | | -- Every summary tile at the top of the page is clickable -- click a tile to instantly select the underlying budget lines that add up to that number. |
24 | | -- Full print styling: clean page margins, nested group boxes, inner item separators, and the app's chrome suppressed in print. `Cmd+P` / `Ctrl+P` produces a clean PDF or paper copy. |
| 21 | +- Click any source detail row to toggle that source on or off. The entire breakdown -- summary tiles, projected cost range, remaining budget, every nested area row -- recalculates against the visible set. |
| 22 | +- The selection is persisted in the URL as `?deselectedSources=<id>,<id>` so a filtered view can be bookmarked, shared, or reloaded without losing state. |
| 23 | +- Press **Escape** while a source row is focused to clear all deselections in one go. |
| 24 | +- A small "X of N selected" caption appears next to **Available Funds** while a filter is active. |
25 | 25 |
|
26 | | -**Budget Sources redesign** |
| 26 | +**Server-side filter pipeline** |
27 | 27 |
|
28 | | -- Click any financing source to expand it **inline** and see every budget line attached to it -- no navigation away. |
29 | | -- Budget lines are grouped into a hierarchical **area tree**, with dense columnar rows and horizontal dividers between work item groups. |
30 | | -- **Multi-select across groups** lets you tick budget lines spread across multiple areas and sources; the selection is preserved as you expand and collapse. |
31 | | -- A new **mass-move modal** reassigns the entire selection to a different source in a single operation. |
32 | | -- New API endpoints power this view: `GET /api/budget-sources/:sourceId/budget-lines` and `PATCH /api/budget-sources/:sourceId/budget-lines/move`. |
| 28 | +- The new filter is wired through to a single endpoint: `GET /api/budget/breakdown?deselectedSources=...`. |
| 29 | +- Subsidy payback math is computed against the filtered set on the server, so subsidies that no longer have qualifying budget lines drop out cleanly instead of double-counting. |
| 30 | +- Filter changes round-trip in a single request -- no client-side recomputation drift. |
33 | 31 |
|
34 | | -**Navigation** |
| 32 | +### Fixes |
35 | 33 |
|
36 | | -- **Vendors** has moved out of the Budget subnav into **Settings**. Vendor records are master data -- names, trades, contact info -- so they sit alongside Users, Areas, and Trades. Invoices stay in the Budget section because they are transactional. |
| 34 | +- Source detail rows stay visible even when every source is deselected, so the filter is never a dead-end. |
| 35 | +- Dark mode contrast and focus ring are corrected on the Cost Breakdown error banner. |
37 | 36 |
|
38 | | -**Reliability** |
| 37 | +### Tooling |
39 | 38 |
|
40 | | -- Reverse-proxy handling is tightened: with `TRUST_PROXY=true`, only the first proxy hop is trusted, and rate limiting uses a resilient client identifier that no longer can be spoofed by a user-supplied `X-Forwarded-For` header. No configuration change is needed to benefit -- upgrading is enough. |
41 | | - |
42 | | -**Tooling** |
43 | | - |
44 | | -- TypeScript is upgraded to **6.0** with `noUncheckedIndexedAccess` enabled across the codebase, catching a whole class of latent array-access bugs. |
45 | | -- Docker Scout comparisons against the previous stable tag are now part of the release pipeline. |
| 39 | +- The `Quality Gates` workflow now supports `workflow_dispatch`, making it easy to re-run gates manually during a promotion. |
46 | 40 |
|
47 | 41 | ### Breaking changes |
48 | 42 |
|
49 | | -None. Existing bookmarks, links, URLs, and data model are preserved. |
| 43 | +None. Existing bookmarks, links, URLs, and data model are preserved. The `?deselectedSources=` query parameter is purely additive -- omit it (or leave it empty) to get the unchanged behavior. |
50 | 44 |
|
51 | 45 | ### Migration notes |
52 | 46 |
|
53 | | -- **No database migration is required.** Area ancestor data is resolved on read -- every response that references a work item, household item, or budget line now includes the full ancestor chain automatically. Existing clients and integrations continue to work; they just see a richer payload. |
54 | | -- **Reverse-proxy users**: `TRUST_PROXY=true` still means "I am running behind a reverse proxy, please read the forwarded headers," so no setting needs to change. What changes is that the server now trusts only the first proxy hop and computes rate-limit keys in a way that cannot be spoofed by an external `X-Forwarded-For`. If you were previously relying on chained / multi-hop proxy headers being trusted all the way to the origin client, review your proxy topology -- see the [reverse proxy guide](https://steilerDev.github.io/cornerstone/getting-started/docker-setup#behind-a-reverse-proxy) for the current behavior. |
55 | | -- **Vendors menu move**: Vendors has moved from `Budget > Vendors` to `Settings > Vendors`. Direct URLs to individual vendor detail pages continue to resolve; only the top-level menu entry relocated. |
| 47 | +No database migration is required. The new filter parameter is server-validated and silently ignores unknown source IDs, so older clients that don't send the parameter continue to work without changes. |
0 commit comments