release: promote beta to main#1332
Merged
Merged
Conversation
…ot assigned (#1200) * fix(work-items): display vendor name in assignedTo column when user not assigned The assignedTo column on the work items list previously only displayed assigned user names, silently ignoring assigned vendors. Updated the column's render function to check assignedUser first, then fall back to assignedVendor, then show '—' if neither is set. Co-Authored-By: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com> * chore: update review metrics for PR #1200 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com>
…d error handling (#1203) The backup creation flow had multiple issues causing SQLITE_CANTOPEN errors: 1. Used system tar binary which is unavailable in DHI production image — replaced with Node.js tar package (pure JS, no system dependencies) 2. No pre-flight writability check on backup directory — added probe file test 3. SQLite backup and tar errors propagated as generic 500 — wrapped in new BackupFailedError with BACKUP_FAILED error code 4. DB snapshot was written to backup dir instead of data dir, so it was never included in the tar archive — corrected to write into data dir 5. Post-tar cleanup referenced wrong path — corrected to use dbSnapshotPath Fixes #1201 Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude backend-developer (Haiku) <noreply@anthropic.com>
* feat(backup): set sensible default for BACKUP_DIR - Add default value '/backups' to BACKUP_DIR configuration in config.ts - Create /backups directory in Docker deps stage for production stage copying - Copy /backups directory with correct node:node ownership in production stage - Declare /backups as a Docker VOLUME - Add cornerstone-backups volume to docker-compose.yml service - Add backup env vars to commented environment block in docker-compose.yml - Uncomment BACKUP_DIR with updated comment in .env.example Fixes #1199 Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> * refactor(backup): make backupDir required, clean up non-null assertions Make `backupDir` a required field in `AppConfig` since it now always has the '/backups' default. Remove non-null assertions in backups.ts and simplify guard conditions in backupService.ts to only check backupEnabled. Update tests to reflect the new defaults and remove the now-unreachable backupDir-undefined guard test. Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com> Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(backup): remove unreachable BACKUP_NOT_CONFIGURED tests With BACKUP_DIR defaulting to /backups, backupEnabled is always true when no env var is set. The 4 tests asserting 503 BACKUP_NOT_CONFIGURED for missing BACKUP_DIR now test an unreachable code path. Co-Authored-By: Claude qa-integration-tester (Haiku 4.5) <noreply@anthropic.com> * docs: update BACKUP_DIR default in CLAUDE.md env var table Reflects the new /backups default added in the previous commit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(e2e): mock 503 response in backup not-configured E2E test BACKUP_DIR now defaults to /backups, so the testcontainer always has backups enabled. The "not configured" E2E test must now mock the 503 API response instead of relying on the testcontainer not having BACKUP_DIR set. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com>
The CLA workflow fails on PRs with agent-authored commits because "Frontend Developer" and "Backend Developer" are not GitHub users and were not in the allowlist. The contributor-assistant action falls back to the git author name when GitHub login is null, so adding these names to the allowlist resolves the check. Fixes #1203 Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Metrics were being written to .claude/metrics/review-metrics.jsonl and as HTML comments on PR reviews. Remove both approaches entirely — no metrics are collected going forward. Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI test shards now collect coverage and a new Coverage Report job merges shard results into a single artifact (coverage-summary.json + coverage-final.json) retained for 30 days. A zero-dependency merge script (scripts/merge-coverage.mjs) handles the Istanbul JSON merging without adding nyc as a dependency. Agent policy changes prevent coverage regression: - dev-team-lead review now enforces test file parity (blocking) - qa-integration-tester must run --coverage locally before committing - e2e-test-engineer must verify route coverage inventory - Implementation checklist updated with parity + E2E route requirements Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
#1210) * fix(date-range-picker): prevent phase reset after start date selection The DateRangePicker was resetting to 'selecting-start' phase immediately after the user selected a start date. This occurred because the useEffect synced phase from props, and the parent DateFilter component did not call onChange for a complete range until both dates were selected. The fix introduces pendingStartDate internal state to track intermediate (uncommitted-to-parent) selection state. The problematic useEffect is replaced with a narrower version that only responds when the parent externally clears both values (startDate='' AND endDate=''). This way, the component doesn't lose its UI state during the two-phase selection flow until the parent explicitly resets. All internal uses of startDate (prop) that tracked the selection flow are now updated to use pendingStartDate instead. The startDate prop is now only used for initial view calculation and detecting external clear. Co-Authored-By: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com> * test(date-range-picker): add regression tests for phase-persistence fix (#1178) Cover the pendingStartDate internal state introduced by the fix: - Phase persists to selecting-end immediately after clicking start date within the same mounted instance (regression guard for issue #1178) - Hover range preview and dayDisabled class both use pendingStartDate rather than the startDate prop after a start-date click - Single-instance two-click flow: start → end without a prop update between clicks emits the correct onChange('start', 'end') call - Escape during selecting-end resets pendingStartDate and phase - Clicking before / on pendingStartDate during selecting-end handled - External clear (both props → '') resets phase via rerender - Partial prop update (only startDate changes) does NOT reset phase Update 'advances to selecting-end phase' test to verify phase within the same mounted instance instead of a separate render call. Rewrite 'when startDate prop changes... externally' to use rerender on a single component instance (correct test technique for the narrowed useEffect). Add integration test to DateFilter.test.tsx: single-instance two-click flow verifying DateFilter does not call onChange for partial selections and calls onChange once with full range format after second click. Fixes #1178 Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(date-range-picker): fix three props sync tests broken by narrowed useEffect The production fix narrowed the reset useEffect so it only fires when both startDate and endDate props are exactly ''. Three tests were written against the old behavior (phase derived from prop values on mount) and now fail: 1. 'when both startDate and endDate props are externally cleared to ""' — was mounting with non-empty props and asserting phase='end' before rerender; fixed by mounting with non-empty props, clicking a day to reach selecting-end internally, then rerendering with empty props so the useEffect fires. 2. 'when endDate prop is set externally, phase remains at selecting-end' — was asserting that mounting with only startDate set produces phase='end' (old behavior). Rewritten to assert that mounting with dates set produces phase='start' (new behavior: phase is internal-only). 3. Regression block 'external clear via rerender' — same root cause as (1); was mounting with non-empty props and asserting 'end' before rerender. Fixed with the same click-first pattern. Fixes #1178 Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * chore: trigger CI retry * fix(date-range-picker): restore useEffect branch for external startDate changes The narrowed useEffect only handled the clear case (both props empty), but also needs to handle when startDate changes externally from '' to a value (while endDate stays ''). This is needed for DateFilter integration where localFrom updates asynchronously via useEffect. Also fixes 3 test assertions that didn't account for the useState initial value being derived from the startDate prop. Co-Authored-By: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * chore: update review metrics for PR #1210 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com>
Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…2E (#1204) (#1211) * test(photos): add unit tests for usePhotos hook and photoApi client Adds 95%+ statement coverage for client/src/hooks/usePhotos.ts and client/src/lib/photoApi.ts. Tests cover loading/success/error states, uploadPhoto (XHR-based with progress tracking), deletePhoto (optimistic removal), updatePhoto (optimistic update), refresh, and all URL helper functions. Includes upload progress lifecycle, FormData construction, XHR event handling (load/error/abort), and entity change refetch. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(invoices): add unit and integration tests for invoice budget line service and standalone invoice routes Adds 95%+ coverage tests for three previously uncovered server files: - invoiceBudgetLineService.test.ts: unit tests for all 5 exported functions (list, create, update, delete, getForInvoice) with full error path coverage - invoiceBudgetLines.test.ts: integration tests for all 4 route handlers (GET/POST/PATCH/DELETE) via app.inject(), including auth, validation, 404, BudgetLineAlreadyLinkedError, and ItemizedSumExceedsInvoiceError scenarios - standaloneInvoices.test.ts: integration tests for GET /api/invoices (pagination, filtering by status/vendorId/amount/date/dueDate/q, all sortBy options) and GET /api/invoices/:invoiceId (cross-vendor lookup, budget lines) Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): add unit tests for milestone pages and invoices page Add Jest unit tests for zero-coverage client-side pages and API modules: - MilestonesPage: loading skeleton, populated data, error/empty states, actions menu, delete flow with confirmation modal, client-side filtering - MilestoneDetailPage: loading/404/error states, view mode, edit mode with form pre-fill and validation, save/cancel, delete confirmation, linked items display, unlink buttons - MilestoneCreatePage: form rendering, validation (title required, date required), successful submission with navigation, API error handling, submit button state - InvoicesPage: loading skeleton, populated data (invoice numbers, vendor names, summary cards), error state, empty state, create invoice modal with full validation flow, actions menu (view navigation), API client tests already existed Fixes #1204 Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): add unit tests for vendor/trade/area client utilities Add 95%+ coverage unit tests for 10 previously uncovered source files: API client layer: - areasApi.test.ts — fetchAreas, fetchArea, createArea, updateArea, deleteArea - tradesApi.test.ts — fetchTrades, fetchTrade, createTrade, updateTrade, deleteTrade - vendorContactsApi.test.ts — listVendorContacts, createVendorContact, updateVendorContact, deleteVendorContact - davTokensApi.test.ts — getDavTokenStatus, generateDavToken, revokeDavToken, getDavProfileUrl - timelineApi.test.ts — getTimeline Utility: - areaTreeUtils.test.ts — buildTree (depth-first ordering, sortOrder/alpha sort, cycle guard, orphan handling) React hooks: - useAreas.test.ts — CRUD lifecycle, loading/error states, refetch - useTrades.test.ts — CRUD lifecycle, loading/error states, refetch - useVendorContacts.test.ts — empty vendorId guard, optimistic updates, error propagation - useDavToken.test.ts — generate/revoke/clearNewToken lifecycle, status refresh Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): add page and API client unit tests for vendors, user management, household items, and work item budgets/milestones Adds five new test files targeting previously uncovered client-side code (Gap 4 + Gap 6): - client/src/lib/workItemBudgetsApi.test.ts (24 tests): fetchWorkItemBudgets, createWorkItemBudget, updateWorkItemBudget, deleteWorkItemBudget — validates URL construction, request bodies, response extraction, and error propagation. - client/src/lib/workItemMilestonesApi.test.ts (21 tests): getWorkItemMilestones, addRequiredMilestone, removeRequiredMilestone, addLinkedMilestone, removeLinkedMilestone — validates HTTP method, URL path with milestoneId, and error handling. - client/src/pages/VendorsPage/VendorsPage.test.tsx (20 tests): loading/data/error states, create vendor modal (validation, API call, error display), action menu, delete confirmation. - client/src/pages/UserManagementPage/UserManagementPage.test.tsx (23 tests): loading/data/error states, client-side filter, action menu (edit disabled for deactivated users), edit modal (pre-fill, validation, API call, cancel), deactivate modal (confirm, error). - client/src/pages/HouseholdItemsPage/HouseholdItemsPage.test.tsx (20 tests): loading/data/error states, action menu, delete confirmation with error handling, graceful degradation when vendor/category fetch fails. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): fix TypeScript duplicate property error in areaTreeUtils.test.ts The makeArea helper used an object literal that set `id` and `name` both explicitly and again via spread `...overrides`, triggering TS2783 (property specified more than once). Refactor to build defaults object first then merge. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): add unit and integration tests for photos service and route Adds 96 tests covering the server-side photo upload infrastructure: - photoService.test.ts (51 tests): unit tests for uploadPhoto, getPhoto, getPhotosForEntity, updatePhoto, reorderPhotos, deletePhoto, deletePhotosForEntity, and getPhotoFilePath. sharp is mocked via jest.unstable_mockModule to avoid native binary dependency. - photos.test.ts (45 tests): integration tests for all 8 photo route handlers using app.inject() with multipart form bodies, mock photoService, and real auth/session via buildApp(). Coverage achieved: - photoService.ts: 97.82% statements, 91.66% branches, 100% functions - photos.ts: 91.91% statements, 85.18% branches, 100% functions/lines (uncovered lines are unreachable auth guards inside route handlers) Part of #1204: close server-side coverage gaps. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * chore(memory): update qa agent memory with Gap 5 test patterns Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): fix TypeScript type errors and add server-side route/service tests Fix TypeScript type errors in three client test files: - HouseholdItemsPage.test.tsx: correct ApiClientError arg order (statusCode first), type jest.fn() mocks for useAreas createArea/updateArea/deleteArea methods - UserManagementPage.test.tsx: correct ApiClientError arg order, type jest.fn() mocks for refreshAuth/logout as () => Promise<void> - VendorsPage.test.tsx: correct ApiClientError arg order, type jest.fn() mocks for useTrades createTrade/updateTrade/deleteTrade methods Add 5 server-side integration/unit tests (Gap 4): - householdItemSubsidyPayback.test.ts (route): subsidy payback calculation endpoint - workItemMilestones.test.ts (route): work item milestone dependency routes - householdItemBudgetService.test.ts: HI budget line CRUD and calculations - householdItemWorkItemService.test.ts: HI-to-work-item association service - workItemMilestoneService.test.ts: work item milestone dependency service Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(coverage): fix HouseholdItemStatus enum values in workItemService test Replace invalid status values 'ordered', 'delivered', and 'cancelled' with valid HouseholdItemStatus enum values: 'purchased', 'arrived', 'scheduled'. HouseholdItemStatus = 'planned' | 'purchased' | 'scheduled' | 'arrived'. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(client): fix top-level await import crash in page component tests Move `await import()` into `beforeEach` using the established lazy-load pattern. Jest's --experimental-vm-modules runner does not support top-level await in test files. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(client): add invoiceBudgetLinesApi unit tests 33 tests covering fetchInvoiceBudgetLines, createInvoiceBudgetLine, updateInvoiceBudgetLine, and deleteInvoiceBudgetLine. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(e2e): add milestones E2E tests and page objects 3 POMs (MilestonesPage, MilestoneCreatePage, MilestoneDetailPage) and 50 test cases covering CRUD flows, responsive layout, dark mode, and smoke tests. Closes Gap 1 E2E coverage. Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(e2e): add invoices, settings/manage E2E tests and page objects - InvoicesPage + InvoiceDetailPage POMs with CRUD tests (list, create, detail, edit, delete, status filter, responsive, dark mode) - HouseholdItemEditPage POM for edit page coverage - Settings/Manage E2E tests covering all 4 tabs (Areas, Trades, Budget Categories, HI Categories) with CRUD, URL deep-linking, responsive - Agent memory updates Closes Gap 2 + Gap 6 E2E coverage. Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(client): fix DataTable dual-render and mock isolation issues in page tests Fix 39 failing tests across VendorsPage, UserManagementPage, and HouseholdItemsPage by addressing three root causes: 1. Missing preferencesApi mock — DataTable's useColumnPreferences hook calls listPreferences() on mount; without a mock the async failure caused repeated re-renders and cascading re-fetches (fetchVendors called 16×, listHouseholdItems 13×, listUsers 3×). 2. Unstable Map reference in useTableState mock — returning `filters: new Map()` inside the mock factory creates a new Map instance on every render, triggering infinite useEffect re-fetch loops in pages that include filters in their dependency array. Fixed by hoisting stable Map constants outside the mock factory. 3. DataTable dual-render (table rows + mobile cards) — getByText/ getByTestId throw "found multiple elements". Replaced with getAllByText/getAllByTestId throughout, and switched toHaveBeenCalledTimes(1) to toHaveBeenCalled() for the same reason. Also: use mockReset() instead of mockClear() in beforeEach to drain stale mockResolvedValueOnce queues from prior tests, and fix button-finder predicates to match actual translation output (t('vendors.buttons.create') = "Add Vendor"; modal footer button text is "Delete Item" not "Delete"). Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(client): fix duplicate-render and deferred-promise issues in page/hook tests Fix remaining test failures in MilestonesPage, MilestoneCreatePage, MilestoneDetailPage, InvoicesPage, and usePhotos: - MilestonesPage: delete modal confirm button text is "Delete Milestone" (from t('milestones.delete.delete')), not /^delete$/i; update regex to /delete milestone/i. Also apply getAllByText/getAllByTestId pattern for DataTable dual-render (table rows + mobile cards). - MilestoneCreatePage/MilestoneDetailPage: form validation tests use fireEvent.submit() instead of clicking the submit button to bypass native HTML required validation and let the JS handler run. Fix non-404 error tests to assert /not found/i since milestone stays null when fetch fails. Use getAllByText for /completed/i which appears in multiple elements. - InvoicesPage: apply getAllByText/getAllByTestId throughout for DataTable dual-render. Chain mockResolvedValue (not Once) for fetchAllInvoices in error state tests to handle possible re-fetch calls triggered by useTableState effect. Fix amount input label selector to /^amount/i. - usePhotos: use a deferred promise in the progress wrapper test so the upload does not resolve before the progress assertion runs. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(client): fix deferred-promise contamination in usePhotos and InvoicesPage usePhotos test 17: replaced immediate Promise.resolve() with a deferred promise to prevent upload resolution from flushing before the progress assertion, fixing the uploadProgress.get() = undefined failure and the result.current = null contamination in tests 18-32. InvoicesPage: switched modal tests from mockResolvedValueOnce to mockResolvedValue so useTableState-driven extra loadInvoices calls don't consume the only mock and cause DataTable error banners to appear alongside modal validation alerts. Fixed getByText/getByTestId → getAllByText/ getAllByTestId for DataTable dual-render duplicates. Changed user.type on number inputs to fireEvent.change for reliable controlled-input state. Fixes #1204 Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(client): fix areaTreeUtils sortOrder for deterministic ordering Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(server): fix additionalProperties test assertions for Fastify AJV behavior Fastify's AJV compiler is configured with removeAdditional=true by default, which strips unknown properties from request bodies and querystrings rather than rejecting them with 400. Three tests incorrectly expected 400 when sending unknown fields — corrected to expect the actual strip-and-succeed behavior. - invoiceBudgetLines: POST and PATCH tests with unknownField now expect 201/200 - standaloneInvoices: GET with unknownParam now expects 200 (param stripped) Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com> * test(server): fix householdItemBudgetService tests — add required budgetSourceId The service requires budgetSourceId on create. Added defaultSourceId to all create calls and fixed test assertions to match actual service behavior (budgetSourceId cannot be cleared). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(memory): update QA agent memory with test fix patterns * fix(e2e): correct milestone API response shape in helpers and smoke tests POST /api/milestones returns MilestoneDetail directly (no { milestone: {...} } wrapper), but createMilestoneViaApi() and Scenarios 4 & 5 were trying to read body.milestone.id, causing TypeError: Cannot read properties of undefined (reading 'id') when running against the real Docker container. Fix: read body.id directly (MilestoneDetail shape per API contract). Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.5) <noreply@anthropic.com> * fix(ci): rename coverage shard files to avoid merge collision Each test shard produces coverage/coverage-final.json. With merge-multiple, files overwrite each other. Rename to coverage-shard-N.json before upload so all shards survive download. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(e2e): fix area/trade delete selectors and Promise.race in invoice POM Area and trade delete buttons in ManagePage only have the text "Delete" with no aria-label containing the entity name. The tests were using `getByRole('button', { name: \`Delete \${areaName}\` })` which would never match. Fix: scope via the itemRow filtered by entity name, then target the "Delete" button within that row. Also replace Promise.race() with Promise.any() in InvoicesPage.waitForLoaded() to prevent the losing waitFor() calls from becoming dangling unhandled rejections after the race resolves, which could cause flaky failures in concurrent shard runs. Fixes #1204 Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.5) <noreply@anthropic.com> * chore(memory): update E2E agent memory with fix patterns --------- Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com>
chore: sync main into beta
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.34.1 to 4.35.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@3869755...c10b806) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.35.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/login-action](https://github.com/docker/login-action) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](docker/login-action@b45d80f...4907a6d) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 4.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 7.0.0 to 7.1.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](docker/build-push-action@d08e5c3...bcafcac) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [docker/scout-action](https://github.com/docker/scout-action) from 1.20.3 to 1.20.4. - [Release notes](https://github.com/docker/scout-action/releases) - [Commits](docker/scout-action@8910519...bacf462) --- updated-dependencies: - dependency-name: docker/scout-action dependency-version: 1.20.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 4.0.5 to 5.0.0. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](actions/deploy-pages@d6db901...cd2ce8f) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](actions/configure-pages@983d773...45bfe01) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 2.5.0 to 3.0.0. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](dependabot/fetch-metadata@21025c7...ffa630c) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…cted (#1241) (#1244) * test(work-items): add unit + integration tests for areaId CSV filter (#1241) Add 11 unit tests to listWorkItems() and 4 integration tests via app.inject() covering the new resolveAreaIds helper: - Single leaf / parent / root ID expansion - CSV of two non-adjacent IDs - CSV of parent + descendant (dedup) - Array input path - Empty string (filter skipped) - Unknown ID (0 results) - CSV with empty segments - Whitespace-only segments - All-whitespace CSV (filter skipped) - Route-level: parent→child hierarchy, CSV union, unknown ID, empty area Also extends insertTestArea() in workItems.test.ts to accept parentId. Fixes #1241 Co-Authored-By: Claude qa-integration-tester (Sonnet 4.6) <noreply@anthropic.com> * test(e2e): add E2E tests for work items area filter hierarchy and CSV (#1241) Validates the areaId filter bug fix: parent area selection now expands to include descendant work items, and CSV multi-area selection returns the union. Fixes #1241 Co-Authored-By: Claude e2e-test-engineer (Sonnet 4.6) <noreply@anthropic.com> * fix(work-items): accept CSV/array of area IDs in list filter (#1241) Adds a resolveAreaIds helper to workItemService that normalises the areaId filter value from either a comma-separated string or an array of strings into a proper array before building the SQL IN clause. Previously a single area ID passed as a plain string was treated as a scalar and the generated query returned zero results for parent areas. Fixes #1241 Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com> Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> * docs(api): document CSV/array support for work-items areaId filter Updates wiki submodule pointer to include API contract documentation for the areaId CSV/array filter parameter added in da67e29. Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com> Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> * test: fix time-bomb tests unmasked by date 2026-04-16 Two distinct time-bomb patterns fixed: 1. Calendar picker tests (DateRangePicker, DateFilter): Tests relied on the real system clock to determine which month the picker displays by default. Once the real date advanced past March 2026, assertions on specific day numbers (e.g. clicking "15" and expecting "2026-03-15") started failing because the picker now shows April 2026+. Fix: pin system time to 2026-03-15T12:00:00Z via jest.useFakeTimers in beforeAll/afterAll with doNotFake for async timers (setTimeout, setInterval, etc.) so React Testing Library's act/findBy* internals continue to work correctly. 2. Scheduler autoReschedule test (workItemService): The "allows updating both dates simultaneously" fixture used 2026-04-01/10 as target dates. The scheduler's "today floor" clamps not_started item start dates to today, so once the real date advanced past 2026-04-01 the update silently overwrote the provided dates. Fix: shift target dates to 2099-04-01/10, well beyond any realistic system clock advance. Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester (Sonnet 4.6) <noreply@anthropic.com> * fix(docker): ensure server/node_modules exists for production COPY The production stage does `COPY --from=deps /app/server/node_modules/ server/node_modules/`. When npm hoists all of @cornerstone/server's production dependencies to the root node_modules/, the workspace-local server/node_modules/ directory is never created and the COPY fails with "failed to calculate checksum ... /app/server/node_modules: not found". Create empty workspace node_modules directories in the deps stage right after `npm ci --omit=dev` so the subsequent COPYs succeed regardless of npm's hoisting decisions. Also covers client/ and shared/ defensively in case future Dockerfile edits add COPYs for those paths. Unblocks all open PRs (CI Docker build failing since ~20:44 UTC). Co-Authored-By: Claude product-architect (Sonnet 4.6) <noreply@anthropic.com> --------- Co-authored-by: Frontend Developer <frontend-developer@cornerstone.local> Co-authored-by: Claude qa-integration-tester (Sonnet 4.6) <noreply@anthropic.com> Co-authored-by: Frank Steiler <frank@steiler.de>
…nse (#1242) (#1252) * feat(budget): add area-grouped budget summaries to budget overview API Add areaSummaries array and unassignedSummary object to GET /api/budget/overview response. areaSummaries contains a flat list of all area nodes with planned/actual totals rolled up through the area hierarchy. unassignedSummary aggregates budget totals for work items with no area assignment. - shared/src/types/budgetOverview.ts: add AreaBudgetSummary interface, extend BudgetOverview with areaSummaries and unassignedSummary fields - shared/src/index.ts: export AreaBudgetSummary - server/src/services/budgetOverviewService.ts: implement area aggregation logic using getDescendantIds for subtree rollup; compute work item → area mappings; aggregate planned/actual amounts per area - wiki/API-Contract.md: update GET /api/budget/overview schema, JSON example, and documentation notes; add AreaBudgetSummary interface definition Fixes #1242 Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> * docs(api): bump wiki pointer for budget overview area summaries Fixes #1242 Co-Authored-By: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com> * test(budget-overview): add area aggregation tests + update fixtures Add 32 unit/integration tests covering all area budget summary spec scenarios. Update 7 client fixture files to include the new `areaSummaries: []` and `unassignedSummary: null` fields required by the updated BudgetOverview type. Fixes #1242 Co-Authored-By: Claude qa-integration-tester (Sonnet 4.6) <noreply@anthropic.com> --------- Co-authored-by: Frank Steiler <frank@steiler.de> Co-authored-by: Claude backend-developer (Haiku 4.5) <noreply@anthropic.com>
…1255) * chore(ci): remove CLA check and stale doc references The CLA workflow is optional (not a required status check on beta or main — branch rulesets require only Quality Gates / E2E Gates). As the sole contributor, the self-signed CLA provides no value. - Delete CLA.md, .github/workflows/cla.yml, .github/cla/signatures.json - Strip stale "+ CLA" mentions from /develop, /epic-close, /release skill docs * fix(milestones): bypass browser native validation to surface custom error banner HTML5 required on the title/targetDate inputs blocked form submission before the onSubmit handler could call setError(...), so the custom error banner (role=alert) never rendered. E2E Scenarios 6/7 on the milestone create page asserted on a null banner text and failed across desktop/tablet/mobile. Adding noValidate to both the create form and the detail-page edit form lets the JS validation handler run and populate the errorBanner as the tests expect. The required attribute stays for screen-reader hinting. * fix(subnav): drop misused list/listitem role overrides The SubNav component forced role='list' on the container <div> and role='listitem' on each NavLink. Overriding the default role of an <a> to 'listitem' makes it invisible to role=link accessibility queries, breaking several E2E tests that navigate via getByRole('link', ...) after the #1188 PageLayout refactor (invoices Budget subnav, settings subnav across desktop/tablet/mobile). Removing both role attributes lets NavLink expose its native anchor role. Update SubNav unit tests to assert link semantics accordingly. * test(e2e): fix broken locators and races exposed by recent CI - MilestonesPage.getMilestoneTitles: the cardCell class does not exist on DataTableCard (which uses cardRow/cardValue). Scope the card iterator to top-level .card children (class^='card_') and read the title from .cardValue. Fixes the 3 mobile milestones scenarios (API create, delete confirm, delete cancel). - invoices.spec.ts Scenario 2: pending summary count is returned from the same API response as the list, but a brief interleaving window after invoice creation causes the list render to show stale counts. Poll the summary count with expect.poll instead of a one-shot read. - invoices.spec.ts Scenario 7: DataTable renders both the desktop table and the mobile cards simultaneously and toggles visibility via CSS media queries. locator('.invoiceLink').first() picked the hidden desktop <a> on mobile. Add :visible so the currently shown link is clicked. - area-filter.spec.ts Scenario 1: the Area column is defaultVisible false, so its in-header Filter by Area button is never rendered. Drop the secondary assertion on the filter-button visibility; the core URL-based areaId filter behaviour is still fully validated. * test(e2e): tighten WorkItemsPage emptyState locator [class*=emptyState] can match unrelated elements with classes like emptyStateTitle/emptyStateDescription. Scope to the CSS-module-hashed prefix emptyState_ so only the EmptyState component wrapper is picked up. Aimed at the tablet filter-empty-state flake on shard 12. * test(e2e): update SubNav-dependent tests to use role=link After the SubNav role override was dropped, tests that relied on role=listitem on nav tabs need to use role=link. Covers: - budget/vendors.spec.ts (Vendors tab) - budget/budget-sources.spec.ts (Sources tab) - budget/budget-overview.spec.ts (four budget tabs) - budget/subsidy-programs.spec.ts (Subsidies tab) - admin/backup-restore.spec.ts (Backups tab) + remove outdated comment - i18n/i18n.spec.ts (Auftragnehmer tab) * test: scope SubNav link queries and fix invoice-create status default - MilestoneCreatePage.test.tsx: the back-link regex `/back|milestones/i` now collides with the SubNav Milestones tab (both role=link after the SubNav role override was dropped). Tighten to `/←\s*milestones/i`. - invoices.spec.ts Scenario 1 (Budget subnav tabs): scope getByRole('link', 'Overview') to the Budget <nav> landmark so it does not collide with the project-logo link's aria-label ("Go to project overview"). - invoices.spec.ts Scenario 2 (Create invoice pending count): the create form defaults status to 'quotation' now (previously 'pending'). Explicitly select 'pending' on the status select so the test's pending-summary assertion actually reflects the created invoice. - settings-manage.spec.ts: same scoping fix for Profile / Manage SubNav tabs. * test(milestones): narrow detail-page back-link regex Same collision as MilestoneCreatePage after the SubNav role change: the /back|milestones/i regex now matches both the header back link and the SubNav Milestones tab. Tighten to /←\s*milestones/i. * test: second-pass SubNav scoping fixes - MilestoneDetailPage.test.tsx (not-found state): the not-found branch renders without SubNav and uses 'milestones.detail.backLink' which translates to 'Back to Milestones', not the header-format arrow. Restore the broader 'back to milestones' regex for this case. - settings-manage.spec.ts (subnav test): add 'exact: true' so the 'Manage' link query does not collide with 'User Management' tab. --------- Co-authored-by: Frank Steiler <frank@steiler.de>
…maining color (#1335, #1336) (#1337) - Move Show lines / Edit / Delete into a single right-aligned action group in each source card's header row so they sit next to the label and badges (#1335) - Unify button padding so all three buttons share a consistent height; stretch edge-to-edge on mobile preserving 44px touch targets - Use the existing --color-danger-text-on-light token for the negative-remaining state so overspend is visible but not dominant (#1336) Fixes #1335 Fixes #1336 Co-authored-by: Frank Steiler <frank@steiler.de> Co-authored-by: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com>
Contributor
|
🎉 This PR is included in version 2.3.0-beta.55 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.1 to 4.35.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@c10b806...95e58e9) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.35.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](dependabot/fetch-metadata@ffa630c...25dd0e3) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-version: 3.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the dev-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [prettier](https://github.com/prettier/prettier) | `3.8.2` | `3.8.3` | | [stylelint](https://github.com/stylelint/stylelint) | `17.6.0` | `17.8.0` | | [typescript](https://github.com/microsoft/TypeScript) | `6.0.2` | `6.0.3` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.58.1` | `8.58.2` | | [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) | `5.6.6` | `5.6.7` | | [webpack](https://github.com/webpack/webpack) | `5.106.1` | `5.106.2` | Updates `prettier` from 3.8.2 to 3.8.3 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](prettier/prettier@3.8.2...3.8.3) Updates `stylelint` from 17.6.0 to 17.8.0 - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](stylelint/stylelint@17.6.0...17.8.0) Updates `typescript` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](microsoft/TypeScript@v6.0.2...v6.0.3) Updates `typescript-eslint` from 8.58.1 to 8.58.2 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.58.2/packages/typescript-eslint) Updates `html-webpack-plugin` from 5.6.6 to 5.6.7 - [Release notes](https://github.com/jantimon/html-webpack-plugin/releases) - [Changelog](https://github.com/jantimon/html-webpack-plugin/blob/main/CHANGELOG.md) - [Commits](jantimon/html-webpack-plugin@v5.6.6...v5.6.7) Updates `webpack` from 5.106.1 to 5.106.2 - [Release notes](https://github.com/webpack/webpack/releases) - [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md) - [Commits](webpack/webpack@v5.106.1...v5.106.2) --- updated-dependencies: - dependency-name: prettier dependency-version: 3.8.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: stylelint dependency-version: 17.8.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: typescript dependency-version: 6.0.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: typescript-eslint dependency-version: 8.58.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: html-webpack-plugin dependency-version: 5.6.7 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: webpack dependency-version: 5.106.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the prod-dependencies group with 2 updates: [ical-generator](https://github.com/sebbo2002/ical-generator) and [react-i18next](https://github.com/i18next/react-i18next). Updates `ical-generator` from 10.1.0 to 10.2.0 - [Release notes](https://github.com/sebbo2002/ical-generator/releases) - [Changelog](https://github.com/sebbo2002/ical-generator/blob/develop/CHANGELOG.md) - [Commits](sebbo2002/ical-generator@v10.1.0...v10.2.0) Updates `react-i18next` from 17.0.3 to 17.0.4 - [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md) - [Commits](i18next/react-i18next@v17.0.3...v17.0.4) --- updated-dependencies: - dependency-name: ical-generator dependency-version: 10.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-dependencies - dependency-name: react-i18next dependency-version: 17.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#1339) Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 3.0.0 to 3.1.1. - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Commits](actions/create-github-app-token@f8d387b...1b10c78) --- updated-dependencies: - dependency-name: actions/create-github-app-token dependency-version: 3.1.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…1341) Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 4.0.0 to 5.0.0. - [Release notes](https://github.com/actions/upload-pages-artifact/releases) - [Commits](actions/upload-pages-artifact@7b1f4a7...fc324d3) --- updated-dependencies: - dependency-name: actions/upload-pages-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Contributor
|
🎉 This PR is included in version 2.3.0-beta.56 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
…ge; group GH Actions updates (#1347) - Bump actions/setup-node to v6.4.0 (supersedes #1343) - Bump actions/upload-artifact to v7.0.1 (supersedes #1342) - Remove .github/workflows/dependabot-auto-merge.yml (no longer used) - Group all github-actions Dependabot updates into a single PR via `groups.github-actions` pattern `*` - Drop stale reference to dependabot-auto-merge.yml from CLAUDE.md Closes #1342 Closes #1343 Co-authored-by: Frank Steiler <frank@steiler.de>
Contributor
|
🎉 This PR is included in version 2.3.0-beta.57 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
…) (#1348) - Restructure source card so the bar chart and summary rows span the full card width; header line contains [name + badges] on the left and [Show lines] [Edit] [Delete] right-aligned on the right - Remove the now-unused .sourceInfo wrapper; .sourceRowHeader moves inside the view-mode fragment only - Restyle .expandToggle at rest to match the Edit button so the three header buttons read as one cohesive action group - Keep the primary-based active indicator on the expanded state - Add three DOM-structure regression tests Fixes #1346 Co-authored-by: Frank Steiler <frank@steiler.de> Co-authored-by: Claude dev-team-lead (Sonnet 4.6) <noreply@anthropic.com>
Contributor
|
🎉 This PR is included in version 2.3.0-beta.58 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
4 tasks
Refresh user-facing documentation to reflect the area-tree hierarchy rework, Budget Overview and Budget Sources redesigns, Vendors move into Settings, tightened reverse-proxy handling, and the TypeScript 6.0 upgrade included in the upcoming stable release. - docs/src: update work items, household items, budget, and getting-started guides to cover area breadcrumbs across the app, the "No Area" filter, the area-grouped Budget Overview with clickable tiles and print styling, the inline-expansion / multi-select / mass-move workflow on Budget Sources, and the narrower trustProxy behavior for reverse-proxy users. - docs/src/guides/budget/vendors-and-invoices.md: document the move of Vendors into the Settings section while invoices stay in Budget. - README.md: refresh the Features section (Work Items, Areas & Trades, Budget Management) without touching the protected NOTE block. - RELEASE_SUMMARY.md: rewrite for this release - area hierarchy, Budget Overview + Sources redesign, navigation, reliability, and TypeScript 6.0 tooling; note no database migration is required and describe the trustProxy behavior change for self-hosters. - .env.example: add a short note next to TRUST_PROXY explaining that only the first proxy hop is trusted and rate limiting is now spoof-resistant. Co-authored-by: Frank Steiler <frank@steiler.de> Co-authored-by: Claude docs-writer (Opus 4.6) <noreply@anthropic.com>
Contributor
|
🎉 This PR is included in version 2.3.0-beta.59 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release Summary
Standalone release promoting beta to main. The headline change is area tree hierarchy across the application — work items, household items, Budget Overview, and Budget Sources now surface the full area ancestry. Budget Sources gains inline expansion, multi-select mass-move, and clickable summary tiles. Budget Overview gains area-grouped cost breakdown and print styling. Vendors moves into the Settings section. TypeScript is upgraded to 6.0 with
noUncheckedIndexedAccessenabled.Changes
Features
Area tree hierarchy
feat(api): Include area ancestor path in work item and household item responses (feat(api): include area ancestor path in work item and household item responses #1249)feat(ui): AddAreaBreadcrumbshared component andSearchPickersecondary-line slot (feat(ui): add AreaBreadcrumb shared component and SearchPicker secondary-line slot #1257)feat(work-items): Display area tree on work item list, detail, and create pages (feat(work-items): display area tree on work item list, detail, and create pages #1262)feat(work-items): Display area tree in work item embeds and pickers (feat(work-items): display area tree in work item embeds and pickers #1270)feat(work-items): Include area breadcrumb on diary, invoice, household item work-item references (feat(diary): include area in diary entry source entity references #1271, feat(invoices): include area on invoice budget line work item references #1272, feat(household-items): include area on household item dependency predecessor summaries #1273) (feat(work-items): include area breadcrumb on diary, invoice, household item work-item references (#1271, #1272, #1273) #1299)feat(household-items): Display area tree on household item pages and pickers (feat(household-items): display area tree on household item pages and pickers #1275)feat(list-filters): Add "No Area" option to area filter on Work Items and Household Items lists (feat(list-filters): add "No Area" option to area filter on Work Items and Household Items lists #1277) (feat(list-filters): add "No Area" option to area filter on Work Items and Household Items lists (#1277) #1290)Budget Overview
feat(budget-overview): Add area-grouped budget summaries to API response (feat(budget-overview): add area-grouped budget summaries to API response #1242) (feat(budget-overview): add area-grouped budget summaries to API response (#1242) #1252)feat(budget-overview): Replace category breakdown with expandable area tree (feat(budget-overview): replace category breakdown with expandable area tree #1243) (feat(budget-overview): replace category breakdown with expandable area tree (#1243) #1256)feat(budget): Clickable tiles select all budget lines (Make tiles clickable for 'select all' in Budget Source line panel #1323) (feat(budget): clickable tiles select all budget lines (#1323) #1327)Budget Sources
feat(budget-sources):GET /api/budget-sources/:sourceId/budget-lines([Story] Backend: GET /api/budget-sources/:sourceId/budget-lines #1245) (feat(budget-sources): GET /api/budget-sources/:sourceId/budget-lines (#1245) #1251)feat(budget-sources):PATCH /api/budget-sources/:sourceId/budget-lines/move([Story] Backend: PATCH /api/budget-sources/:sourceId/budget-lines/move #1246) (feat(budget-sources): PATCH /api/budget-sources/:sourceId/budget-lines/move (#1246) #1258)feat(budget-sources): Inline expansion with grouped budget lines ([Story] Frontend: Inline expansion on Sources page with grouped budget lines #1247) (feat(budget-sources): inline expansion with grouped budget lines (#1247) #1263)feat(budget-sources): Multi-select and mass-move for budget lines ([Story] Frontend: Multi-select and mass-move dialog for budget lines #1248) (feat(budget-sources): multi-select and mass-move for budget lines (#1248) #1265)feat(budget-sources): Hierarchical area tree + dense columnar line rows (feat(budget-sources): hierarchical area tree + dense columnar line rows #1285)Navigation
feat(vendors): Move vendors to Settings section (feat(vendors): move vendors to settings section #1286)Fixes
Budget / Areas
fix(work-items): Area filter returns no results when parent area selected (fix(work-items): area filter returns no results when parent area selected #1241) (fix(work-items): area filter returns no results when parent area selected (#1241) #1244)fix(ui): Simplify area breadcrumb — drop compact tooltip and detail header (fix(ui): simplify area breadcrumb — drop compact tooltip and detail header #1282)fix(budget-sources): Stack lines panel below source info + add item links (fix(budget-sources): stack lines panel below source info + add item links #1269)fix(budget-overview): Group cost breakdown by area hierarchy instead of category (fix(budget-overview): group cost breakdown by area hierarchy instead of category #1276) (fix(budget-overview): group cost breakdown by area hierarchy instead of category (#1276) #1287)fix(budget-sources): Preserve selection state, restructure area header, fix nested tree (fix(budget-sources): preserve selection, restructure area header, nested tree #1296)fix(filters): Support arbitrary hierarchy depth inEnumFilter(fix(filters): hierarchical enum filter only renders two levels — must support arbitrary depth #1294) (fix(filters): support arbitrary hierarchy depth in EnumFilter (#1294) #1297)fix(budget-sources): Resolve area ancestor chain in budget-lines response (fix(budget-sources): resolve area ancestor chain in budget-lines response #1304)fix(budget): Cost breakdown table — indent nested rows and rename "Unassigned" to "No Area" (fix(budget): cost breakdown table — indent nested rows and rename "Unassigned" to "No Area" #1302)fix(budget-sources): Add horizontal divider between work item groups (Missing horizontal divider between work items in Budget Sources panel #1309) (fix(budget-sources): add horizontal divider between work item groups (#1309) #1311)fix(budget): Clean up source budget line panel with nested tinted cards (Clean up Budget Source item list: remove redundant 'under' labels and add visual grouping #1315) (fix(budget): clean up source budget line panel with nested tinted cards (#1315) #1316)Print
fix(budget): Implement print styling for Budget Overview page (fix(budget): implement print styling for Budget Overview page #1312)fix(budget): Polish print output for Budget Overview (fix(budget): polish print output for Budget Overview (#1317) #1318)fix(budget): Strengthen print area grouping and suppress AppShell scrollbar (fix(budget): strengthen print area grouping and suppress AppShell scrollbar (#1320) #1321)fix(budget): Print polish — page margins, title spacing, nested group boxes (fix(budget): print polish — page margins, title spacing, nested group boxes (#1325) #1326)fix(budget): Suppress browser print chrome and render inner item separators (fix(budget): suppress browser print chrome and render inner item separators (#1328) #1329)Server / Reliability
fix(server): Resilient rate-limit key + narrowertrustProxyfor reverse-proxy setups (fix(server): resilient rate-limit key + narrower trustProxy for reverse-proxy setups #1303)i18n
fix(i18n): Add missing translation keys and remove orphans ([bug] i18n translation coverage gaps — 24 missing keys and 3 orphans across en/de locales #1306) (fix(i18n): add missing translation keys and remove orphans (#1306) #1308)fix(i18n): Add missing German translations for Budget Sources line panel (fix(i18n): Budget Sources German translations and orphan cleanup (#1313) #1314)CI / Docker
fix(ci): Fixing Docker Scout compare action (fix(ci): Fixing Docker Scout compare action #1301)Chores / Refactoring
chore(ci): Remove CLA check and fix milestones E2E form validation (chore(ci): remove CLA check and fix milestones E2E form validation #1255)chore(deps): Upgrade TypeScript to 6.0 and refresh dev-dependencies (chore(deps): upgrade TypeScript to 6.0 and refresh dev-dependencies #1267)chore(server): Adopt TS 6using/Disposablefor test resource cleanup and migrate FK pragma (chore(server): adopt TS 6 using/Disposable for test cleanup and migrate FK pragma #1289)chore(types): EnablenoUncheckedIndexedAccessand fix unsafe array access (chore(types): enable noUncheckedIndexedAccess and fix unsafe array access #1330)ci(release): Add Docker Scout compare against latest tag (ci(release): add Docker Scout compare against latest tag #1298)chore(deps): Bumps for fastify, drizzle-orm, @fastify/static, production dependencies, and GitHub Actions (docker/login, docker/build-push, docker/scout, actions/configure-pages, actions/deploy-pages, github/codeql-action, dependabot/fetch-metadata)Tests / E2E
test(e2e): Add Playwright tests for budget source bar chart rework (Rework budget source bar chart: remove Allocated, add projected min/max range, restructure summary #1319) (test(e2e): add Playwright tests for budget source bar chart rework (#1319) #1322)fix(e2e): Stabilization fixes across budget-source, work-item-create, breadcrumb, and subnav tests (fix(e2e): stabilize budget-source and work-item-create tests after area-tree merges #1284, fix(e2e): drop Vendors from Budget subnav assertion #1293, fix(e2e): update budget overview subnav tabs after Vendors→Settings move #1305, fix(e2e): provide budgetSourceId in invoice-budget-line breadcrumb tests #1307, fix(e2e): stabilize failing tests from run 24666997830 #1331)Change Inventory
Backend (
server/,shared/) — 147 filesserver/src/routes/budgetSources.ts,server/src/routes/budgetSources.budgetLines.test.ts,server/src/routes/budgetSources.move.test.ts— budget-lines GET + move PATCHserver/src/services/areaService.ts,server/src/services/areaService.ancestors.test.ts,server/src/services/areaService.resolveAreaFilter.test.ts— area resolution helpersserver/src/routes/workItems.ts,server/src/routes/workItems.ancestors.test.tsserver/src/routes/householdItems.ts,server/src/routes/householdItems.ancestors.test.tsserver/src/routes/budgetOverview.ts,server/src/routes/budgetOverview.breakdown.test.tsserver/src/plugins/rateLimitPlugin.ts— resilient rate-limit keyserver/src/app.ts— narrowertrustProxyserver/src/plugins/config.ts— new env-var surfaceshared/src/types/area.ts,shared/src/types/budgetSource.ts,shared/src/types/workItem.ts,shared/src/types/householdItem.tsserver/src/db/disposables.ts—using/Disposablepatterntsconfig.base.json—noUncheckedIndexedAccess.test.tsfilesFrontend (
client/) — 247 filesclient/src/components/AreaBreadcrumb/— breadcrumb componentclient/src/components/MassMoveModal/— mass-move modalclient/src/pages/BudgetOverviewPage/— area-grouped breakdown, print stylingclient/src/components/CostBreakdownTable/— nested rows, area groupingclient/src/components/BudgetSummaryCard/,client/src/components/SourceUtilizationCard/— clickable tile filtersclient/src/pages/BudgetSourcesPage/— hierarchical tree, dense columnar rowsclient/src/components/SourceBudgetLinePanel/— multi-select, mass-move, nested cards, item linksclient/src/pages/WorkItemsPage/,client/src/pages/WorkItemDetailPage/,client/src/pages/WorkItemCreatePage/client/src/pages/HouseholdItemsPage/,client/src/pages/HouseholdItemDetailPage/client/src/components/WorkItemPicker/,client/src/components/HouseholdItemPicker/client/src/components/DataTable/filters/EnumFilter.tsx— arbitrary hierarchy depth, "No Area" sentinelclient/src/components/Sidebar/,client/src/components/SubNav/— Vendors under Settingsclient/src/i18n/en/andclient/src/i18n/de/— new keys, orphan cleanup, glossary additionsE2E Tests (
e2e/) — 45 filese2e/tests/budget/budget-overview-print.spec.ts— print stylinge2e/tests/budget/budget-source-lines.spec.ts,e2e/tests/budget/budget-source-move.spec.ts,e2e/tests/budget/budget-sources.spec.tse2e/tests/work-items/work-item-breadcrumb.spec.ts,work-item-embeds-breadcrumb.spec.ts,no-area-filter.spec.tse2e/tests/household-items/household-item-breadcrumb.spec.ts,household-item-dep-breadcrumb.spec.ts,no-area-filter.spec.tse2e/tests/diary/diary-source-entity-breadcrumb.spec.tse2e/tests/invoices/invoice-budget-line-area-breadcrumb.spec.tsDocs / Config / CI
.github/workflows/release.yml— Docker Scout compareDockerfile,docker-compose.yml— build updates.env.example— new env surfaceCLAUDE.md,CLA.md,.gitignore— project doc updatespackage.json,package-lock.json, all workspacepackage.jsonfiles — TS 6.0 and dep bumps.claude/— agent memory, agent definitions, skills, implementation checklistManual Validation Checklist
Area tree hierarchy
/work-items— each row shows the full area ancestor breadcrumb/household-itemslist and a detail page — area breadcrumb renders correctlyBudget Overview
/budget/overview— cost breakdown is grouped by area, not category; nested rows are indented; "No Area" bucket replaces "Unassigned"Budget Sources
/budget/sources— each row expands inline to show grouped budget linesNavigation
/vendorsURLs still resolve or redirect correctlyReliability / Infrastructure
X-Forwarded-Forspoof surface);trustProxyis narrowedRegressions to spot-check
Testing
docker pull steilerdev/cornerstone:betadocker pull steilerdev/cornerstone:pr-<pr-number>(available after CI runs)