this derivation will be built: /nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv building '/nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv' horae-browser-checks> initdb: warning: enabling "trust" authentication for local connections horae-browser-checks> initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb. horae-browser-checks> waiting for server to start.... done horae-browser-checks> server started horae-browser-checks> 2026-10-12T20:51:35.846635Z INFO horae: Running migrations... horae-browser-checks> 2026-10-12T20:51:35.974567Z INFO horae: Migrations complete. horae-browser-checks> 2026-10-12T20:51:35.986267Z INFO horae::seed: Seeding demo data… horae-browser-checks> 2026-10-12T20:51:36.005317Z INFO horae::seed: Seed complete. horae-browser-checks> 2026-10-12T20:51:36.006179Z INFO horae::seed: time_entries: 10 rows horae-browser-checks> 2026-10-12T20:51:36.006307Z INFO horae::seed: clients: 2 rows horae-browser-checks> PASS: archived own timer labels survive without granting catalog or global-rate access horae-browser-checks> PASS: catalog/rate grants never enable unlinked or archived tasks for a new timer; valid start/stop persists horae-browser-checks> PASS: rail popovers accept clicks and release the resize handle after closing horae-browser-checks> PASS: scoped project list/detail expose workflow labels without directory access, private notes or rates horae-browser-checks> PASS: edit and managed-project revocation remove current UI authority without legacy Administrator fallback horae-browser-checks> PASS: inactive-account and changed-policy responses clear retained detail; retry recovers only the original binding horae-browser-checks> PASS: keyboard manager removal preserves archived membership and withheld money/notes at desktop and narrow widths horae-browser-checks> PASS: staged project task archive/restore, undo, cancellation and running-timer rejection preserve hidden configuration and restrictions horae-browser-checks> PASS: financial read grants display disabled values and ordinary saves preserve stored fields horae-browser-checks> PASS: explicit zero, cost reset and lost-acknowledgement replay preserve exact original intent horae-browser-checks> PASS: current-authority revocation discards old editor state; explicit reload restores a fresh authorized form horae-browser-checks> PASS: an explicit hours-only budget edit preserves inactive hidden money and recorded history horae-browser-checks> PASS: scoped report paging, totals, four individual reports, four nested breakdowns, filtered exports, stale/invalid states and policy binding; Chromium 148.0.7778.96 horae-browser-checks> ✔ permissions: pending navigation preserves history until the request is resolved (4.099607ms) horae-browser-checks> ✔ permissions: dirty navigation requires an explicit discard (0.85127ms) horae-browser-checks> ✔ client: pending navigation preserves history until the request is resolved (1.745972ms) horae-browser-checks> ✔ client: dirty navigation requires an explicit discard (0.723829ms) horae-browser-checks> ✔ invoice: pending navigation preserves history until the request is resolved (0.787455ms) horae-browser-checks> ✔ invoice: dirty navigation requires an explicit discard (0.662892ms) horae-browser-checks> ✔ project: pending navigation preserves history until the request is resolved (0.669252ms) horae-browser-checks> ✔ project: dirty navigation requires an explicit discard (0.634011ms) horae-browser-checks> ✔ timesheet: pending navigation preserves history until the request is resolved (0.730955ms) horae-browser-checks> ✔ timesheet: dirty navigation requires an explicit discard (0.810148ms) horae-browser-checks> ✔ permissions: scroll-only replacements preserve Dioxus coordinates without prompting (0.693319ms) horae-browser-checks> ✔ timesheet: scroll-only replacements preserve Dioxus coordinates without prompting (0.585071ms) horae-browser-checks> ✔ the legacy project opt-in and explicit release keep working (0.768148ms) horae-browser-checks> ℹ tests 13 horae-browser-checks> ℹ suites 0 horae-browser-checks> ℹ pass 13 horae-browser-checks> ℹ fail 0 horae-browser-checks> ℹ cancelled 0 horae-browser-checks> ℹ skipped 0 horae-browser-checks> ℹ todo 0 horae-browser-checks> ℹ duration_ms 22.409425 horae-browser-checks> ✔ store acknowledgement precedes a load from a new execution (3.766488ms) horae-browser-checks> ✔ identical store is idempotent; another request cannot replace it (1.50457ms) horae-browser-checks> ✔ clear requires the exact stored record and is idempotent (2.794228ms) horae-browser-checks> ✔ storage errors never acknowledge a mutation or erase a request (1.961909ms) horae-browser-checks> ✔ size limit counts UTF-8 bytes on both reads and writes (2.648239ms) horae-browser-checks> ✔ other requesters and unrelated browser records are untouched (1.832873ms) horae-browser-checks> ℹ tests 6 horae-browser-checks> ℹ suites 0 horae-browser-checks> ℹ pass 6 horae-browser-checks> ℹ fail 0 horae-browser-checks> ℹ cancelled 0 horae-browser-checks> ℹ skipped 0 horae-browser-checks> ℹ todo 0 horae-browser-checks> ℹ duration_ms 22.164259 horae-browser-checks> Permission recovery browser: Chromium 148.0.7778.96 horae-browser-checks> PASS: canonical People separates read scope, Administrator editing and legacy roles without legacy reads horae-browser-checks> PASS: editor reload rejects a changed session and recovers only for the original requester horae-browser-checks> PASS: real person save survives lost response/reload and replays exactly one receipt horae-browser-checks> PASS: account changes isolate tab recovery; same-user reauthentication and restored authority recover the template horae-browser-checks> PASS: a deleted template is recovered from its exact receipt without recreating it horae-browser-checks> PASS: real permission history supports empty state, keyboard details, stable paging, deleted profiles, refresh/revocation and canonical access horae-browser-checks> PASS: storage refusal prevents sends; acknowledged self-demotion cleanup issues no second mutation horae-browser-checks> PASS: Export: semantics, keyboard, focus return, backdrop and short viewport horae-browser-checks> PASS: Add entry: semantics, keyboard, focus return, backdrop and short viewport horae-browser-checks> PASS: + Add row: semantics, keyboard, focus return, backdrop and short viewport horae-browser-checks> PASS: pending save blocks dismissal; failure preserves input and allows retry horae-browser-checks> PASS: row deletion is atomic after a stale-client lock and supports retry horae-browser-checks> PASS: move failure is visible and reconciles with saved data horae-browser-checks> PASS: resize failure is visible and reconciles with saved data horae-browser-checks> PASS: reorder failure is visible and reconciles with saved data horae-browser-checks> PASS: lost response failure is visible and reconciles with saved data horae-browser-checks> PASS: historical move works without current tracking choices horae-browser-checks> PASS: historical resize works without current tracking choices horae-browser-checks> PASS: historical reorder works without current tracking choices horae-browser-checks> PASS: day-view timer failure is visible horae-browser-checks> PASS: project scope includes zero-entry active teammates without exposing unrelated hours horae-browser-checks> PASS: changing person and browser history reload the correct sheet, including an empty teammate horae-browser-checks> PASS: Day and Week edits carry the selected owner and preserve hidden work horae-browser-checks> PASS: delegated creation uses the selected person and eligible project/task horae-browser-checks> PASS: delegated Calendar drawing, day movement and resizing persist exact minutes horae-browser-checks> PASS: delegated untimed moves and order inversions persist the complete ordered entry set horae-browser-checks> PASS: delegated modal and Week row deletion preserve unrelated hours and requester timer horae-browser-checks> PASS: revocation between click and commit rejects the write and preserves the draft/data horae-browser-checks> PASS: delegated timer leaves the requester timer alone and requires restored tracking eligibility horae-browser-checks> PASS: only the owner can use terminal recovery after losing project assignment horae-browser-checks> Timesheet read failed: 403 http://127.0.0.1:8093/api/load_timesheet_page16386063561583833955 horae-browser-checks> PASS: relationship revocation removes the selected sheet without falling back to own data horae-browser-checks> PASS: header actions, supported metrics and labelled native budget progress horae-browser-checks> PASS: design heading, compact row typography and inline project type horae-browser-checks> PASS: filtered empty state resets search, scope and client horae-browser-checks> PASS: narrow/short layouts, keyboard row actions and export formats horae-browser-checks> PASS: loading spend is unavailable until the read completes horae-browser-checks> PASS: failed spend is unavailable; retry restores real amounts horae-browser-checks> PASS: configured monthly consumption replaces lifetime spend only after loading horae-browser-checks> PASS: keyboard-accessible scope breakdown exposes overruns without layout overflow horae-browser-checks> PASS: failed configured budget never falls back to lifetime figures horae-browser-checks> PASS: empty-state guidance and action visibility for admin horae-browser-checks> PASS: empty-state guidance and action visibility for manager horae-browser-checks> PASS: empty-state guidance and action visibility for member horae-browser-checks> PASS: shared Menu, Combobox, empty-state and navigation-icon defaults are unchanged horae-browser-checks> PASS: /clients header at 320px horae-browser-checks> PASS: /clients header at 390px horae-browser-checks> PASS: /clients header at 768px horae-browser-checks> PASS: /clients header at 1280px horae-browser-checks> PASS: /clients header at 1440px horae-browser-checks> PASS: /projects header at 320px horae-browser-checks> PASS: /projects header at 390px horae-browser-checks> PASS: /projects header at 768px horae-browser-checks> PASS: /projects header at 1280px horae-browser-checks> PASS: /projects header at 1440px horae-browser-checks> PASS: /invoices header at 320px horae-browser-checks> PASS: /invoices header at 390px horae-browser-checks> PASS: /invoices header at 768px horae-browser-checks> PASS: /invoices header at 1280px horae-browser-checks> PASS: /invoices header at 1440px horae-browser-checks> PASS: /reports header at 320px horae-browser-checks> PASS: /reports header at 390px horae-browser-checks> PASS: /reports header at 768px horae-browser-checks> PASS: /reports header at 1280px horae-browser-checks> PASS: /reports header at 1440px horae-browser-checks> PASS: /admin/users header at 320px horae-browser-checks> PASS: /admin/users header at 390px horae-browser-checks> PASS: /admin/users header at 768px horae-browser-checks> PASS: /admin/users header at 1280px horae-browser-checks> PASS: /admin/users header at 1440px horae-browser-checks> PASS: /approvals header at 320px horae-browser-checks> PASS: /approvals header at 390px horae-browser-checks> PASS: /approvals header at 768px horae-browser-checks> PASS: /approvals header at 1280px horae-browser-checks> PASS: /approvals header at 1440px horae-browser-checks> PASS: /settings header at 320px horae-browser-checks> PASS: /settings header at 390px horae-browser-checks> PASS: /settings header at 768px horae-browser-checks> PASS: /settings header at 1280px horae-browser-checks> PASS: /settings header at 1440px horae-browser-checks> PASS: /admin/importers header at 320px horae-browser-checks> PASS: /admin/importers header at 390px horae-browser-checks> PASS: /admin/importers header at 768px horae-browser-checks> PASS: /admin/importers header at 1280px horae-browser-checks> PASS: /admin/importers header at 1440px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 320px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 390px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 768px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 1280px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 1440px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 320px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 390px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 768px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 1280px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 1440px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 320px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 390px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 768px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 1280px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 1440px horae-browser-checks> PASS: project names and badges stay within aligned columns; scrolling to last-row actions opens editing horae-browser-checks> PASS: small-screen timesheet pager, date picker and view controls remain usable horae-browser-checks> PASS: admin subnavigation and its content remain reachable on mobile horae-browser-checks> PASS: day strip scrolls to Sunday and long entry labels do not cover actions horae-browser-checks> CHECK: late popover initialization restores missing focus without overriding deliberate focus horae-browser-checks> PASS: late popover initialization restores missing focus without overriding deliberate focus horae-browser-checks> CHECK: content reflow preserves an open menu while deliberate scrolling still dismisses it horae-browser-checks> PASS: content reflow preserves an open menu while deliberate scrolling still dismisses it horae-browser-checks> CHECK: first and last project-row actions are initially visible and clickable horae-browser-checks> PASS: first and last project-row actions are initially visible and clickable horae-browser-checks> CHECK: menu keyboard, disabled items, outside click and repeated opening horae-browser-checks> PASS: menu keyboard, disabled items, outside click and repeated opening horae-browser-checks> CHECK: scroll and resize dismiss without leaving stale menus or focus horae-browser-checks> PASS: scroll and resize dismiss without leaving stale menus or focus horae-browser-checks> CHECK: short-screen menu scrolls internally and supports reverse Tab and Space horae-browser-checks> PASS: short-screen menu scrolls internally and supports reverse Tab and Space horae-browser-checks> CHECK: filter and calendar menus keep their callbacks and survive route changes horae-browser-checks> PASS: filter and calendar menus keep their callbacks and survive route changes horae-browser-checks> CHECK: Timesheet keeps the shared calendar and week selection behavior horae-browser-checks> PASS: Timesheet keeps the shared calendar and week selection behavior horae-browser-checks> PASS: mobile content width, keyboard toggle, Escape/focus restoration and navigation close horae-browser-checks> PASS: short mobile viewport reaches account navigation and preserves desktop collapse state horae-browser-checks> PASS: desktop drag width survives mobile and breakpoint transitions horae-browser-checks> PASS: keyboard selection, mixed/select-all states and Actions count horae-browser-checks> PASS: search, status and client changes clear selection horae-browser-checks> PASS: keyboard selection/confirmation and no document overflow in both themes at three widths horae-browser-checks> PASS: cancel/focus, failure retry, pending guard and archive/reactivate confirmation horae-browser-checks> PASS: oversized selection cannot submit and members have no bulk controls horae-browser-checks> PASS: real atomic archive/reactivate, anonymous/member/inactive denial, manager/admin and safe retries horae-browser-checks> PASS: bulk success restores focus and recovers the list without stale actions horae-browser-checks> PASS: bulk pending restores focus and recovers the list without stale actions horae-browser-checks> PASS: bulk pending-navigation restores focus and recovers the list without stale actions horae-browser-checks> PASS: bulk failure restores focus and recovers the list without stale actions horae-browser-checks> PASS: client activation failure remains visible with form closed, open and cancelled horae-browser-checks> PASS: successful form save preserves action error; real status retry clears it and refreshes the row horae-browser-checks> PASS: archive failure survives menu dismissal; shared edit failure preserves input and safely retries horae-browser-checks> PASS: failed team removal preserves the draft, safely retries and can be restored through the shared editor horae-browser-checks> PASS: initial catalog/draft failures show loading and recovery without rendering or saving an empty replacement horae-browser-checks> PASS: design typography, section spacing, quiet dividers and theme-aware task information horae-browser-checks> PASS: project types retain native keyboard selection and the designed icon/option-card states horae-browser-checks> PASS: searchable client selection, pending/error recovery and explicit/inherited currency horae-browser-checks> PASS: client default-rate currency rejects relabelling, preserves failed input and permits compatible edits horae-browser-checks> PASS: task and teammate searches handle pending results, keyboard selection, duplicates and retry horae-browser-checks> PASS: real client, team, task restrictions, billing and invoice defaults survive reload horae-browser-checks> PASS: all invoice-default errors identify and focus their field, preserve input and recover at three widths horae-browser-checks> PASS: basic-field rejections retain values, link visible errors and restore focus at three widths horae-browser-checks> PASS: failed resume and retry preserve the existing draft without a replacement write horae-browser-checks> PASS: invalid hourly rates and hour/fee budgets retain input and focus their error at three widths horae-browser-checks> PASS: a stale email configuration rejection can be corrected without sending mail horae-browser-checks> PASS: task/person rate, cost and budget errors identify their row and preserve other inputs at three widths horae-browser-checks> PASS: single/monthly fees, empty schedules and individual milestone errors recover without changing another row horae-browser-checks> PASS: responsive form, conditional panels and Cancel preserve the draft horae-browser-checks> PASS: edits made while a save is pending are saved after its acknowledgement horae-browser-checks> PASS: lost acknowledgement retries the same request and preserves newer edits horae-browser-checks> PASS: real finalized budget reaches the authorized Projects endpoint and display horae-browser-checks> PASS: a new tagged project reaches reports and both exports; pending/error filters never show stale rows horae-browser-checks> PASS: project invoice defaults prefill real estimates, stale reviews cannot generate, and editable draft values persist independently horae-browser-checks> PASS: lost creation response is idempotent and clears the completed draft horae-browser-checks> PASS: stale tabs cannot overwrite saved input; explicit discard removes only the draft horae-browser-checks> PASS: invoice selection, partial balances, exact excess, dirty/pending navigation, reload recovery, account-scoped replay, storage failure safety and authorized per-occurrence project balances horae-browser-checks> PASS: New Project task rates and editor capabilities preserve configured/legacy modes, source currencies, unknown/zero recovery, scoped budgets and keyboard recovery across three widths horae-browser-checks> PASS: organization admin real-session UI, draft ownership, progress/export scope and financial redaction horae-browser-checks> PASS: organization manager real-session UI, draft ownership, progress/export scope and financial redaction horae-browser-checks> PASS: project lead real-session UI, draft ownership, progress/export scope and financial redaction horae-browser-checks> PASS: project admin real-session UI, draft ownership, progress/export scope and financial redaction horae-browser-checks> PASS: visible assigned member real-session UI, draft ownership, progress/export scope and financial redaction horae-browser-checks> PASS: private assigned member real-session UI, draft ownership, progress/export scope and financial redaction horae-browser-checks> PASS: revoked assignment and outsider identities cannot grant project-wide access horae-browser-checks> PASS: inactive/anonymous requests are denied and a manager creates a real project without private overrides horae-browser-checks> PASS: stale client/task/person references and archived task-name conflicts preserve drafts and support field-level recovery at three widths horae-browser-checks> PASS: saved invalid task names/access identify their row, preserve input and support keyboard recovery at three widths before real finalization horae-browser-checks> PASS: 390/1 hourly Person/No budget horae-browser-checks> PASS: 390/1 hourly Task/Hours per task horae-browser-checks> PASS: 390/1 hourly Project/Total project hours horae-browser-checks> PASS: 390/1 hourly Person/Hours per person horae-browser-checks> PASS: 390/1 hourly Task/Fees per task horae-browser-checks> PASS: 390/1 hourly Project/Total project fees horae-browser-checks> PASS: 390/1 fixed/no budget horae-browser-checks> PASS: 390/1 fixed/Single fee horae-browser-checks> PASS: 390/1 fixed/Milestones horae-browser-checks> PASS: 390/1 fixed/Monthly horae-browser-checks> PASS: 390/1 non-billable/No budget horae-browser-checks> PASS: 390/1 non-billable/Total project hours horae-browser-checks> PASS: 390/1 non-billable/Hours per task horae-browser-checks> PASS: 390/1 non-billable/Hours per person horae-browser-checks> PASS: native Tab order, accessible names, reverse Tab and unclipped focus across all billing/budget branches at 390px and 100% text horae-browser-checks> PASS: 768/1 hourly Person/No budget horae-browser-checks> PASS: 768/1 hourly Task/Hours per task horae-browser-checks> PASS: 768/1 hourly Project/Total project hours horae-browser-checks> PASS: 768/1 hourly Person/Hours per person horae-browser-checks> PASS: 768/1 hourly Task/Fees per task horae-browser-checks> PASS: 768/1 hourly Project/Total project fees horae-browser-checks> PASS: 768/1 fixed/no budget horae-browser-checks> PASS: 768/1 fixed/Single fee horae-browser-checks> PASS: 768/1 fixed/Milestones horae-browser-checks> PASS: 768/1 fixed/Monthly horae-browser-checks> PASS: 768/1 non-billable/No budget horae-browser-checks> PASS: 768/1 non-billable/Total project hours horae-browser-checks> PASS: 768/1 non-billable/Hours per task horae-browser-checks> PASS: 768/1 non-billable/Hours per person horae-browser-checks> PASS: native Tab order, accessible names, reverse Tab and unclipped focus across all billing/budget branches at 768px and 100% text horae-browser-checks> PASS: 1440/1 hourly Person/No budget horae-browser-checks> PASS: 1440/1 hourly Task/Hours per task horae-browser-checks> PASS: 1440/1 hourly Project/Total project hours horae-browser-checks> PASS: 1440/1 hourly Person/Hours per person horae-browser-checks> PASS: 1440/1 hourly Task/Fees per task horae-browser-checks> PASS: 1440/1 hourly Project/Total project fees horae-browser-checks> PASS: 1440/1 fixed/no budget horae-browser-checks> PASS: 1440/1 fixed/Single fee horae-browser-checks> PASS: 1440/1 fixed/Milestones horae-browser-checks> PASS: 1440/1 fixed/Monthly horae-browser-checks> PASS: 1440/1 non-billable/No budget horae-browser-checks> PASS: 1440/1 non-billable/Total project hours horae-browser-checks> PASS: 1440/1 non-billable/Hours per task horae-browser-checks> PASS: 1440/1 non-billable/Hours per person horae-browser-checks> PASS: native Tab order, accessible names, reverse Tab and unclipped focus across all billing/budget branches at 1440px and 100% text horae-browser-checks> PASS: 1440/2 hourly Person/No budget horae-browser-checks> PASS: 1440/2 hourly Task/Hours per task horae-browser-checks> PASS: 1440/2 hourly Project/Total project hours horae-browser-checks> PASS: 1440/2 hourly Person/Hours per person horae-browser-checks> PASS: 1440/2 hourly Task/Fees per task horae-browser-checks> PASS: 1440/2 hourly Project/Total project fees horae-browser-checks> PASS: 1440/2 fixed/no budget horae-browser-checks> PASS: 1440/2 fixed/Single fee horae-browser-checks> PASS: 1440/2 fixed/Milestones horae-browser-checks> PASS: 1440/2 fixed/Monthly horae-browser-checks> PASS: 1440/2 non-billable/No budget horae-browser-checks> PASS: 1440/2 non-billable/Total project hours horae-browser-checks> PASS: 1440/2 non-billable/Hours per task horae-browser-checks> PASS: 1440/2 non-billable/Hours per person horae-browser-checks> PASS: native Tab order, accessible names, reverse Tab and unclipped focus across all billing/budget branches at 1440px and 200% text horae-browser-checks> PASS: New client horae-browser-checks> PASS: Who can track to this task? horae-browser-checks> PASS: restricted task members horae-browser-checks> PASS: Discard this draft? horae-browser-checks> PASS: configured email threshold at 390 horae-browser-checks> PASS: configured email threshold at 768 horae-browser-checks> PASS: configured email threshold at 1440 horae-browser-checks> PASS: budget amount and checkbox choices survive draft reload and finalize correctly at 390px horae-browser-checks> PASS: keyboard-only Time & Materials creation at 390px took 15254ms and survives reopening horae-browser-checks> PASS: keyboard-only Fixed Fee creation at 390px took 11048ms and survives reopening horae-browser-checks> PASS: keyboard-only Non-Billable creation at 390px took 2678ms and survives reopening horae-browser-checks> PASS: budget amount and checkbox choices survive draft reload and finalize correctly at 768px horae-browser-checks> PASS: keyboard-only Time & Materials creation at 768px took 14613ms and survives reopening horae-browser-checks> PASS: keyboard-only Fixed Fee creation at 768px took 33482ms and survives reopening horae-browser-checks> PASS: keyboard-only Non-Billable creation at 768px took 10203ms and survives reopening horae-browser-checks> PASS: budget amount and checkbox choices survive draft reload and finalize correctly at 1440px horae-browser-checks> PASS: keyboard-only Time & Materials creation at 1440px took 12545ms and survives reopening horae-browser-checks> PASS: keyboard-only Fixed Fee creation at 1440px took 5605ms and survives reopening horae-browser-checks> PASS: keyboard-only Non-Billable creation at 1440px took 3447ms and survives reopening horae-browser-checks> PASS: modal traversal/Escape restores focus and configured email threshold is keyboard reachable without sending mail horae-browser-checks> PASS: interrupted response bodies remain retryable without losing newer edits horae-browser-checks> PASS: shared editor prefills, cancels, saves the same project and survives reload at 390px horae-browser-checks> PASS: shared editor prefills, cancels, saves the same project and survives reload at 768px horae-browser-checks> PASS: shared editor prefills, cancels, saves the same project and survives reload at 1440px horae-browser-checks> PASS: configured editor prefills exact zero, budgets, private notes and invoice defaults; persists changes and preserves identity on no-op horae-browser-checks> PASS: sidebar, back, forward, reload and replacement navigation preserve dirty edits until explicitly discarded horae-browser-checks> PASS: lost save acknowledgement blocks navigation and retries the identical committed request without another update horae-browser-checks> PASS: concurrent edits reject a stale save, retain local input and require confirmation before reloading horae-browser-checks> PASS: pending creation saves protect sidebar, Back, replacement, reload and full-document exits without losing newer edits horae-browser-checks> PASS: a lost acknowledgement blocks Forward and exits until the identical retry and newer edits are acknowledged horae-browser-checks> PASS: explicit Cancel preserves the draft, confirmed discard clears it, and successful creation releases the guard horae-browser-checks> PASS: clients create/reload/edit/cancel and explicit currency/rate intent horae-browser-checks> PASS: pending guard and explicit uncertain-create recovery retain input horae-browser-checks> PASS: lost creation acknowledgement can be inspected without duplicating or undoing the client horae-browser-checks> PASS: existing activation/deactivation does not cascade into projects or historical invoices horae-browser-checks> PASS: the existing administrator import entry point remains reachable horae-browser-checks> ExpectError: expect(locator).toContainText(expected) failed horae-browser-checks> horae-browser-checks> Locator: getByRole('alert') horae-browser-checks> Expected pattern: /Invalid client|unavailable/ horae-browser-checks> Timeout: 5000ms horae-browser-checks> Error: element(s) not found horae-browser-checks> horae-browser-checks> Call log: horae-browser-checks> - Expect "to.have.text" with timeout 5000ms horae-browser-checks> - waiting for getByRole('alert') horae-browser-checks> horae-browser-checks> at captureRawStack (/nix/store/i6xnc927g8yrwq0fws8wbmjvj4y36fq5-playwright-test-1.60.0/lib/node_modules/playwright-core/lib/coreBundle.js:3130:17) horae-browser-checks> at callMatcherAsStep (/nix/store/i6xnc927g8yrwq0fws8wbmjvj4y36fq5-playwright-test-1.60.0/lib/node_modules/playwright/lib/matchers/expect.js:12873:57) horae-browser-checks> at Object.toContainText (/nix/store/i6xnc927g8yrwq0fws8wbmjvj4y36fq5-playwright-test-1.60.0/lib/node_modules/playwright/lib/matchers/expect.js:12863:23) horae-browser-checks> at /nix/store/69j97diy8ybgln8phsmhlmbf07nb9rx1-horae/tests/browser/client-context.cjs:93:45 { horae-browser-checks> matcherResult: { horae-browser-checks> name: 'toContainText', horae-browser-checks> expected: /Invalid client|unavailable/, horae-browser-checks> message: '\x1B[2mexpect(\x1B[22m\x1B[31mlocator\x1B[39m\x1B[2m).\x1B[22mtoContainText\x1B[2m(\x1B[22m\x1B[32mexpected\x1B[39m\x1B[2m)\x1B[22m failed\n' + horae-browser-checks> '\n' + horae-browser-checks> "Locator: getByRole('alert')\n" + horae-browser-checks> 'Expected pattern: \x1B[32m/Invalid client|unavailable/\x1B[39m\n' + horae-browser-checks> 'Timeout: 5000ms\n' + horae-browser-checks> 'Error: element(s) not found\n' + horae-browser-checks> '\n' + horae-browser-checks> 'Call log:\n' + horae-browser-checks> '\x1B[2m - Expect "to.have.text" with timeout 5000ms\x1B[22m\n' + horae-browser-checks> "\x1B[2m - waiting for getByRole('alert')\x1B[22m\n", horae-browser-checks> pass: false, horae-browser-checks> actual: undefined, horae-browser-checks> log: [ horae-browser-checks> ' - Expect "to.have.text" with timeout 5000ms', horae-browser-checks> " - waiting for getByRole('alert')" horae-browser-checks> ], horae-browser-checks> timeout: 5000, horae-browser-checks> ariaSnapshot: '- complementary "Navigation":\n' + horae-browser-checks> ' - text: Horae\n' + horae-browser-checks> ' - button "Collapse sidebar": «\n' + horae-browser-checks> ' - button "Start timer"\n' + horae-browser-checks> ' - text: Track\n' + horae-browser-checks> ' - link "Timesheet":\n' + horae-browser-checks> ' - /url: /timesheet/week/2026-10-12?span=week&user=\n' + horae-browser-checks> ' - img\n' + horae-browser-checks> ' - text: Timesheet\n' + horae-browser-checks> ' - text: Organize\n' + horae-browser-checks> ' - link "Projects":\n' + horae-browser-checks> ' - /url: /projects\n' + horae-browser-checks> ' - img\n' + horae-browser-checks> ' - text: Projects\n' + horae-browser-checks> ' - link "Invoices":\n' + horae-browser-checks> ' - /url: /invoices\n' + horae-browser-checks> ' - img\n' + horae-browser-checks> ' - text: Invoices\n' + horae-browser-checks> ' - text: Review\n' + horae-browser-checks> ' - link "Approvals":\n' + horae-browser-checks> ' - /url: /approvals\n' + horae-browser-checks> ' - img\n' + horae-browser-checks> ' - text: Approvals\n' + horae-browser-checks> ' - link "Reports":\n' + horae-browser-checks> ' - /url: /reports\n' + horae-browser-checks> ' - img\n' + horae-browser-checks> ' - text: Reports\n' + horae-browser-checks> ' - button "· Not signed in ⌄"\n' + horae-browser-checks> '- main:\n' + horae-browser-checks> ' - status:\n' + horae-browser-checks> ' - paragraph: Checking invoice recovery…\n' + horae-browser-checks> ' - heading "Invoices" [level=1]\n' + horae-browser-checks> ' - text: Loading…' horae-browser-checks> } horae-browser-checks> } horae-browser-checks> 2026-10-12T20:51:36.045548Z WARN horae: DEV_LOGIN=1: /auth/dev-login signs anyone in as an admin without a password. Use it for local development only. horae-browser-checks> 2026-10-12T21:17:13.010105Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="WITH config AS ( …" db.statement="\n\nWITH config AS (\n SELECT p.id, p.budget_kind, p.budget_minutes, p.budget_amount_cents,\n p.project_type, p.currency, p.rate_cents, p.client_id,\n ps.budget_scope, ps.monthly_reset, ps.include_nonbillable, ps.rate_mode,\n ($4::uuid IS NULL OR $5 OR $6 OR ($7 AND management.id IS NOT NULL)) AS can_read_details,\n ($4::uuid IS NULL OR $5 OR $8 OR ($9 AND management.id IS NOT NULL)) AS can_view_money\n FROM projects p JOIN project_settings ps ON ps.project_id = p.id AND ps.org_id = p.org_id\n JOIN clients parent ON parent.id=p.client_id AND parent.org_id=p.org_id\n LEFT JOIN project_management_assignments management ON management.org_id=p.org_id\n AND management.project_id=p.id AND management.manager_id=$4\n LEFT JOIN assignments member ON member.project_id=p.id AND member.user_id=$4\n WHERE p.org_id = $1 AND ($2::uuid IS NULL OR p.id = $2)\n AND ($4::uuid IS NULL OR CASE WHEN $5 THEN EXISTS (\n SELECT 1 FROM project_read_access access\n WHERE access.org_id = p.org_id AND access.project_id = p.id\n AND access.user_id = $4 AND access.can_view_progress)\n ELSE $6 OR ($7 AND management.id IS NOT NULL)\n OR (member.id IS NOT NULL AND ps.report_visibility='project_members') END)\n ), scopes AS (\n SELECT c.id AS project_id, NULL::uuid AS task_id, NULL::uuid AS user_id,\n NULL::text AS label,\n CASE WHEN c.budget_kind = 'hours' THEN c.budget_minutes ELSE c.budget_amount_cents END AS budget\n FROM config c WHERE c.budget_scope = 'project'\n UNION ALL\n SELECT c.id, pt.task_id, NULL::uuid, t.name,\n CASE WHEN c.budget_kind = 'hours' THEN s.budget_minutes ELSE s.budget_cents END\n FROM config c JOIN project_tasks pt ON pt.project_id = c.id\n JOIN tasks t ON t.id = pt.task_id AND t.org_id = $1\n LEFT JOIN project_task_settings s ON s.project_id = c.id AND s.org_id = $1 AND s.task_id = pt.task_id\n WHERE c.budget_scope = 'task'\n UNION ALL\n SELECT c.id, NULL::uuid, a.user_id, u.name, s.budget_minutes\n FROM config c JOIN assignments a ON a.project_id = c.id\n JOIN users u ON u.id = a.user_id AND u.org_id = $1\n LEFT JOIN project_member_budgets s ON s.project_id = c.id AND s.org_id = $1 AND s.user_id = a.user_id\n WHERE c.budget_scope = 'person' AND c.budget_kind = 'hours'\n ), entries AS (\n SELECT c.id AS project_id, te.task_id, te.user_id,\n CASE WHEN c.budget_kind = 'hours'\n THEN effective_minutes(te.minutes, te.rounded_minutes, o.round_minutes, o.round_dir)::bigint\n WHEN c.can_view_money THEN COALESCE(line.amount_cents, line_amount_cents(\n COALESCE(resolve_project_rate(c.rate_mode, pt.rate_cents, a.rate_cents, c.rate_cents,\n CASE WHEN c.currency = o.default_currency THEN u.billable_rate_cents END,\n CASE WHEN c.currency = cl.currency THEN cl.default_rate_cents END), 0),\n effective_minutes(te.minutes, te.rounded_minutes, o.round_minutes, o.round_dir)))\n ELSE 0\n END AS consumed\n FROM config c JOIN time_entries te ON te.project_id = c.id AND te.org_id = $1\n JOIN organizations o ON o.id = te.org_id\n JOIN users u ON u.id = te.user_id AND u.org_id = te.org_id\n JOIN clients cl ON cl.id = c.client_id AND cl.org_id = te.org_id\n JOIN tasks t ON t.id = te.task_id AND t.org_id = te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id = c.id AND pt.task_id = te.task_id\n LEFT JOIN assignments a ON a.project_id = c.id AND a.user_id = te.user_id\n LEFT JOIN invoices invoice ON invoice.id=te.invoice_id AND invoice.org_id=te.org_id\n LEFT JOIN invoice_line_items line ON line.invoice_id = invoice.id AND line.time_entry_id = te.id\n WHERE c.budget_kind <> 'none' AND (NOT c.monthly_reset OR (\n te.spent_date >= date_trunc('month', $3::date)::date\n AND te.spent_date < (date_trunc('month', $3::date) + interval '1 month')::date))\n AND (te.invoice_id IS NULL OR invoice.id IS NOT NULL)\n AND (c.include_nonbillable OR c.project_type = 'non_billable'\n OR (te.billable AND (te.invoice_id IS NOT NULL OR COALESCE(pt.billable, t.billable_default))))\n )\n SELECT c.id AS \"project_id!\", s.task_id AS \"task_id?\", s.user_id AS \"user_id?\",\n s.label AS \"label?\", c.budget_scope AS \"scope!\", c.currency AS \"currency!\",\n c.budget_kind AS \"kind!: BudgetKind\",\n CASE WHEN c.budget_kind <> 'amount' OR c.can_view_money THEN s.budget END AS \"budget?\",\n c.can_view_money AS \"can_view_money!\", c.can_read_details AS \"can_read_details!\",\n CASE WHEN c.monthly_reset THEN to_char($3::date, 'YYYY-MM') ELSE 'lifetime' END AS \"period_key!\",\n COALESCE(SUM(e.consumed), 0)::bigint AS \"consumed!\"\n FROM config c LEFT JOIN scopes s ON s.project_id = c.id\n LEFT JOIN entries e ON e.project_id = c.id\n AND (s.task_id IS NULL OR e.task_id = s.task_id)\n AND (s.user_id IS NULL OR e.user_id = s.user_id)\n GROUP BY c.id, c.budget_kind, c.budget_scope, c.currency, c.monthly_reset,\n s.task_id, s.user_id, s.label, s.budget, c.can_view_money, c.can_read_details\n ORDER BY c.id, s.label, s.task_id, s.user_id\n" rows_affected=30 rows_returned=30 elapsed=1.06481557s elapsed_secs=1.06481557 slow_threshold=1s horae-browser-checks> 2026-10-12T21:17:13.071600Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="WITH visible AS ( …" db.statement="\n\nWITH visible AS (\n SELECT p.*,\n CASE WHEN $3 THEN COALESCE(legacy.can_view_progress, false)\n ELSE $6 OR ($7 AND management.id IS NOT NULL) END AS can_view_money\n FROM projects p\n JOIN clients parent ON parent.id=p.client_id AND parent.org_id=p.org_id\n LEFT JOIN project_read_access legacy ON legacy.org_id=p.org_id\n AND legacy.project_id=p.id AND legacy.user_id=$2\n LEFT JOIN project_management_assignments management ON management.org_id=p.org_id\n AND management.project_id=p.id AND management.manager_id=$2\n LEFT JOIN assignments member ON member.project_id=p.id AND member.user_id=$2\n LEFT JOIN project_settings settings ON settings.org_id=p.org_id AND settings.project_id=p.id\n WHERE p.org_id=$1 AND CASE WHEN $3 THEN COALESCE(legacy.can_view_progress, false)\n ELSE $4 OR ($5 AND management.id IS NOT NULL)\n OR (member.id IS NOT NULL AND COALESCE(settings.report_visibility, 'project_members')='project_members') END\n ), entries AS (\n SELECT p.id AS project_id, te.minutes,\n CASE WHEN p.can_view_money AND te.billable\n AND (te.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable, t.billable_default)))\n THEN COALESCE(line.amount_cents, line_amount_cents(\n COALESCE(CASE WHEN ps.project_id IS NULL OR p.project_type = 'time_and_materials'\n THEN resolve_project_rate(ps.rate_mode, pt.rate_cents, a.rate_cents, p.rate_cents,\n CASE WHEN ps.project_id IS NULL OR p.currency = o.default_currency THEN u.billable_rate_cents END,\n CASE WHEN p.currency = c.currency THEN c.default_rate_cents END\n ) END, 0),\n effective_minutes(te.minutes, te.rounded_minutes, o.round_minutes, o.round_dir)\n )) END AS amount_cents\n FROM visible p\n JOIN time_entries te ON te.project_id=p.id AND te.org_id=p.org_id\n JOIN clients c ON c.id = p.client_id AND c.org_id=te.org_id\n LEFT JOIN project_settings ps ON ps.project_id = p.id AND ps.org_id=te.org_id\n JOIN tasks t ON t.id = te.task_id AND t.org_id=te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id = te.project_id AND pt.task_id = te.task_id\n LEFT JOIN assignments a ON a.project_id = te.project_id AND a.user_id = te.user_id\n LEFT JOIN invoices invoice ON invoice.id=te.invoice_id AND invoice.org_id=te.org_id\n LEFT JOIN invoice_line_items line ON line.invoice_id = invoice.id AND line.time_entry_id = te.id\n JOIN users u ON u.id = te.user_id AND u.org_id=te.org_id\n JOIN organizations o ON o.id = te.org_id\n WHERE te.invoice_id IS NULL OR invoice.id IS NOT NULL\n )\n SELECT p.id AS \"project_id!\",\n COALESCE(SUM(e.minutes),0)::bigint AS \"spent_minutes!\",\n CASE WHEN p.can_view_money THEN COALESCE(SUM(e.amount_cents),0)::bigint END AS \"spent_cents?\"\n FROM visible p LEFT JOIN entries e ON e.project_id=p.id\n GROUP BY p.id,p.can_view_money\n ORDER BY p.id\n" rows_affected=31 rows_returned=31 elapsed=1.611940002s elapsed_secs=1.6119400019999999 slow_threshold=1s horae-browser-checks> 2026-10-12T21:19:36.508265Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="WITH visible AS ( …" db.statement="\n\nWITH visible AS (\n SELECT p.*,\n CASE WHEN $3 THEN COALESCE(legacy.can_view_progress, false)\n ELSE $6 OR ($7 AND management.id IS NOT NULL) END AS can_view_money\n FROM projects p\n JOIN clients parent ON parent.id=p.client_id AND parent.org_id=p.org_id\n LEFT JOIN project_read_access legacy ON legacy.org_id=p.org_id\n AND legacy.project_id=p.id AND legacy.user_id=$2\n LEFT JOIN project_management_assignments management ON management.org_id=p.org_id\n AND management.project_id=p.id AND management.manager_id=$2\n LEFT JOIN assignments member ON member.project_id=p.id AND member.user_id=$2\n LEFT JOIN project_settings settings ON settings.org_id=p.org_id AND settings.project_id=p.id\n WHERE p.org_id=$1 AND CASE WHEN $3 THEN COALESCE(legacy.can_view_progress, false)\n ELSE $4 OR ($5 AND management.id IS NOT NULL)\n OR (member.id IS NOT NULL AND COALESCE(settings.report_visibility, 'project_members')='project_members') END\n ), entries AS (\n SELECT p.id AS project_id, te.minutes,\n CASE WHEN p.can_view_money AND te.billable\n AND (te.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable, t.billable_default)))\n THEN COALESCE(line.amount_cents, line_amount_cents(\n COALESCE(CASE WHEN ps.project_id IS NULL OR p.project_type = 'time_and_materials'\n THEN resolve_project_rate(ps.rate_mode, pt.rate_cents, a.rate_cents, p.rate_cents,\n CASE WHEN ps.project_id IS NULL OR p.currency = o.default_currency THEN u.billable_rate_cents END,\n CASE WHEN p.currency = c.currency THEN c.default_rate_cents END\n ) END, 0),\n effective_minutes(te.minutes, te.rounded_minutes, o.round_minutes, o.round_dir)\n )) END AS amount_cents\n FROM visible p\n JOIN time_entries te ON te.project_id=p.id AND te.org_id=p.org_id\n JOIN clients c ON c.id = p.client_id AND c.org_id=te.org_id\n LEFT JOIN project_settings ps ON ps.project_id = p.id AND ps.org_id=te.org_id\n JOIN tasks t ON t.id = te.task_id AND t.org_id=te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id = te.project_id AND pt.task_id = te.task_id\n LEFT JOIN assignments a ON a.project_id = te.project_id AND a.user_id = te.user_id\n LEFT JOIN invoices invoice ON invoice.id=te.invoice_id AND invoice.org_id=te.org_id\n LEFT JOIN invoice_line_items line ON line.invoice_id = invoice.id AND line.time_entry_id = te.id\n JOIN users u ON u.id = te.user_id AND u.org_id=te.org_id\n JOIN organizations o ON o.id = te.org_id\n WHERE te.invoice_id IS NULL OR invoice.id IS NOT NULL\n )\n SELECT p.id AS \"project_id!\",\n COALESCE(SUM(e.minutes),0)::bigint AS \"spent_minutes!\",\n CASE WHEN p.can_view_money THEN COALESCE(SUM(e.amount_cents),0)::bigint END AS \"spent_cents?\"\n FROM visible p LEFT JOIN entries e ON e.project_id=p.id\n GROUP BY p.id,p.can_view_money\n ORDER BY p.id\n" rows_affected=34 rows_returned=34 elapsed=1.057257187s elapsed_secs=1.057257187 slow_threshold=1s horae-browser-checks> 2026-10-12T21:19:38.589729Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="WITH config AS ( …" db.statement="\n\nWITH config AS (\n SELECT p.id, p.budget_kind, p.budget_minutes, p.budget_amount_cents,\n p.project_type, p.currency, p.rate_cents, p.client_id,\n ps.budget_scope, ps.monthly_reset, ps.include_nonbillable, ps.rate_mode,\n ($4::uuid IS NULL OR $5 OR $6 OR ($7 AND management.id IS NOT NULL)) AS can_read_details,\n ($4::uuid IS NULL OR $5 OR $8 OR ($9 AND management.id IS NOT NULL)) AS can_view_money\n FROM projects p JOIN project_settings ps ON ps.project_id = p.id AND ps.org_id = p.org_id\n JOIN clients parent ON parent.id=p.client_id AND parent.org_id=p.org_id\n LEFT JOIN project_management_assignments management ON management.org_id=p.org_id\n AND management.project_id=p.id AND management.manager_id=$4\n LEFT JOIN assignments member ON member.project_id=p.id AND member.user_id=$4\n WHERE p.org_id = $1 AND ($2::uuid IS NULL OR p.id = $2)\n AND ($4::uuid IS NULL OR CASE WHEN $5 THEN EXISTS (\n SELECT 1 FROM project_read_access access\n WHERE access.org_id = p.org_id AND access.project_id = p.id\n AND access.user_id = $4 AND access.can_view_progress)\n ELSE $6 OR ($7 AND management.id IS NOT NULL)\n OR (member.id IS NOT NULL AND ps.report_visibility='project_members') END)\n ), scopes AS (\n SELECT c.id AS project_id, NULL::uuid AS task_id, NULL::uuid AS user_id,\n NULL::text AS label,\n CASE WHEN c.budget_kind = 'hours' THEN c.budget_minutes ELSE c.budget_amount_cents END AS budget\n FROM config c WHERE c.budget_scope = 'project'\n UNION ALL\n SELECT c.id, pt.task_id, NULL::uuid, t.name,\n CASE WHEN c.budget_kind = 'hours' THEN s.budget_minutes ELSE s.budget_cents END\n FROM config c JOIN project_tasks pt ON pt.project_id = c.id\n JOIN tasks t ON t.id = pt.task_id AND t.org_id = $1\n LEFT JOIN project_task_settings s ON s.project_id = c.id AND s.org_id = $1 AND s.task_id = pt.task_id\n WHERE c.budget_scope = 'task'\n UNION ALL\n SELECT c.id, NULL::uuid, a.user_id, u.name, s.budget_minutes\n FROM config c JOIN assignments a ON a.project_id = c.id\n JOIN users u ON u.id = a.user_id AND u.org_id = $1\n LEFT JOIN project_member_budgets s ON s.project_id = c.id AND s.org_id = $1 AND s.user_id = a.user_id\n WHERE c.budget_scope = 'person' AND c.budget_kind = 'hours'\n ), entries AS (\n SELECT c.id AS project_id, te.task_id, te.user_id,\n CASE WHEN c.budget_kind = 'hours'\n THEN effective_minutes(te.minutes, te.rounded_minutes, o.round_minutes, o.round_dir)::bigint\n WHEN c.can_view_money THEN COALESCE(line.amount_cents, line_amount_cents(\n COALESCE(resolve_project_rate(c.rate_mode, pt.rate_cents, a.rate_cents, c.rate_cents,\n CASE WHEN c.currency = o.default_currency THEN u.billable_rate_cents END,\n CASE WHEN c.currency = cl.currency THEN cl.default_rate_cents END), 0),\n effective_minutes(te.minutes, te.rounded_minutes, o.round_minutes, o.round_dir)))\n ELSE 0\n END AS consumed\n FROM config c JOIN time_entries te ON te.project_id = c.id AND te.org_id = $1\n JOIN organizations o ON o.id = te.org_id\n JOIN users u ON u.id = te.user_id AND u.org_id = te.org_id\n JOIN clients cl ON cl.id = c.client_id AND cl.org_id = te.org_id\n JOIN tasks t ON t.id = te.task_id AND t.org_id = te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id = c.id AND pt.task_id = te.task_id\n LEFT JOIN assignments a ON a.project_id = c.id AND a.user_id = te.user_id\n LEFT JOIN invoices invoice ON invoice.id=te.invoice_id AND invoice.org_id=te.org_id\n LEFT JOIN invoice_line_items line ON line.invoice_id = invoice.id AND line.time_entry_id = te.id\n WHERE c.budget_kind <> 'none' AND (NOT c.monthly_reset OR (\n te.spent_date >= date_trunc('month', $3::date)::date\n AND te.spent_date < (date_trunc('month', $3::date) + interval '1 month')::date))\n AND (te.invoice_id IS NULL OR invoice.id IS NOT NULL)\n AND (c.include_nonbillable OR c.project_type = 'non_billable'\n OR (te.billable AND (te.invoice_id IS NOT NULL OR COALESCE(pt.billable, t.billable_default))))\n )\n SELECT c.id AS \"project_id!\", s.task_id AS \"task_id?\", s.user_id AS \"user_id?\",\n s.label AS \"label?\", c.budget_scope AS \"scope!\", c.currency AS \"currency!\",\n c.budget_kind AS \"kind!: BudgetKind\",\n CASE WHEN c.budget_kind <> 'amount' OR c.can_view_money THEN s.budget END AS \"budget?\",\n c.can_view_money AS \"can_view_money!\", c.can_read_details AS \"can_read_details!\",\n CASE WHEN c.monthly_reset THEN to_char($3::date, 'YYYY-MM') ELSE 'lifetime' END AS \"period_key!\",\n COALESCE(SUM(e.consumed), 0)::bigint AS \"consumed!\"\n FROM config c LEFT JOIN scopes s ON s.project_id = c.id\n LEFT JOIN entries e ON e.project_id = c.id\n AND (s.task_id IS NULL OR e.task_id = s.task_id)\n AND (s.user_id IS NULL OR e.user_id = s.user_id)\n GROUP BY c.id, c.budget_kind, c.budget_scope, c.currency, c.monthly_reset,\n s.task_id, s.user_id, s.label, s.budget, c.can_view_money, c.can_read_details\n ORDER BY c.id, s.label, s.task_id, s.user_id\n" rows_affected=31 rows_returned=31 elapsed=1.049552237s elapsed_secs=1.0495522369999999 slow_threshold=1s horae-browser-checks> 2026-10-12 20:51:35.653 UTC [18] LOG: starting PostgreSQL 17.10 on x86_64-pc-linux-gnu, compiled by clang version 21.1.8, 64-bit horae-browser-checks> 2026-10-12 20:51:35.653 UTC [18] LOG: listening on Unix socket "/tmp/horae-browser.WTNu6u/.s.PGSQL.5432" horae-browser-checks> 2026-10-12 20:51:35.654 UTC [21] LOG: database system was shut down at 2026-10-12 20:51:35 UTC horae-browser-checks> 2026-10-12 20:51:35.656 UTC [18] LOG: database system is ready to accept connections horae-browser-checks> 2026-10-12 20:51:36.006 UTC [127] LOG: could not receive data from client: Connection reset by peer horae-browser-checks> 2026-10-12 20:51:59.408 UTC [942] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.408 UTC [942] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.418 UTC [946] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.418 UTC [946] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.422 UTC [949] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.422 UTC [949] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.433 UTC [950] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.433 UTC [950] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.439 UTC [951] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.439 UTC [951] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.450 UTC [952] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.450 UTC [952] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.454 UTC [953] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.454 UTC [953] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.465 UTC [954] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.465 UTC [954] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.472 UTC [955] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.472 UTC [955] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.481 UTC [957] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.481 UTC [957] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.490 UTC [958] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.490 UTC [958] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.497 UTC [959] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.497 UTC [959] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.504 UTC [960] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.504 UTC [960] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.510 UTC [961] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.510 UTC [961] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.517 UTC [962] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.517 UTC [962] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.523 UTC [963] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.523 UTC [963] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.530 UTC [964] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.530 UTC [964] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.537 UTC [965] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.537 UTC [965] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.543 UTC [966] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.543 UTC [966] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.550 UTC [967] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.551 UTC [967] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.557 UTC [968] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.557 UTC [968] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.563 UTC [969] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.563 UTC [969] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.570 UTC [970] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.570 UTC [970] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.578 UTC [971] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.578 UTC [971] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.585 UTC [972] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.585 UTC [972] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.592 UTC [973] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.592 UTC [973] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.601 UTC [974] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.601 UTC [974] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.607 UTC [975] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.607 UTC [975] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.615 UTC [976] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.615 UTC [976] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.622 UTC [977] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.622 UTC [977] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.628 UTC [978] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.629 UTC [978] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.635 UTC [979] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.635 UTC [979] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.641 UTC [980] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.641 UTC [980] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.648 UTC [981] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.648 UTC [981] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.654 UTC [982] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.654 UTC [982] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:51:59.661 UTC [983] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 20:51:59.661 UTC [983] FATAL: connection to client lost horae-browser-checks> 2026-10-12 20:56:35.755 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 20:58:51.827 UTC [19] LOG: checkpoint complete: wrote 1335 buffers (8.1%); 1 WAL file(s) added, 0 removed, 0 recycled; write=136.061 s, sync=0.001 s, total=136.073 s; sync files=0, longest=0.000 s, average=0.000 s; distance=7859 kB, estimate=7859 kB; lsn=0/1CF8B98, redo lsn=0/1C998D0 horae-browser-checks> 2026-10-12 21:01:35.931 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:01:46.390 UTC [19] LOG: checkpoint complete: wrote 107 buffers (0.7%); 0 WAL file(s) added, 0 removed, 0 recycled; write=10.452 s, sync=0.001 s, total=10.459 s; sync files=0, longest=0.000 s, average=0.000 s; distance=578 kB, estimate=7131 kB; lsn=0/1D2DB28, redo lsn=0/1D2A480 horae-browser-checks> 2026-10-12 21:06:35.492 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:06:35.836 UTC [19] LOG: checkpoint complete: wrote 4 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.314 s, sync=0.001 s, total=0.344 s; sync files=0, longest=0.000 s, average=0.000 s; distance=51 kB, estimate=6423 kB; lsn=0/1D37338, redo lsn=0/1D372E0 horae-browser-checks> 2026-10-12 21:11:35.936 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:11:36.850 UTC [19] LOG: checkpoint complete: wrote 9 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.847 s, sync=0.001 s, total=0.914 s; sync files=0, longest=0.000 s, average=0.000 s; distance=80 kB, estimate=5789 kB; lsn=0/1D4B3E8, redo lsn=0/1D4B390 horae-browser-checks> 2026-10-12 21:16:35.952 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:16:42.197 UTC [19] LOG: checkpoint complete: wrote 65 buffers (0.4%); 0 WAL file(s) added, 0 removed, 0 recycled; write=6.232 s, sync=0.001 s, total=6.245 s; sync files=0, longest=0.000 s, average=0.000 s; distance=295 kB, estimate=5240 kB; lsn=0/1DA9820, redo lsn=0/1D95290 horae-browser-checks> 2026-10-12 21:20:11.172 UTC [18] LOG: received fast shutdown request horae-browser-checks> 2026-10-12 21:20:11.228 UTC [18] LOG: aborting any active transactions horae-browser-checks> 2026-10-12 21:20:11.298 UTC [18] LOG: background worker "logical replication launcher" (PID 24) exited with exit code 1 horae-browser-checks> 2026-10-12 21:20:11.298 UTC [19] LOG: shutting down horae-browser-checks> 2026-10-12 21:20:11.312 UTC [19] LOG: checkpoint starting: shutdown immediate horae-browser-checks> 2026-10-12 21:20:11.569 UTC [19] LOG: checkpoint complete: wrote 50 buffers (0.3%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.217 s, sync=0.001 s, total=0.264 s; sync files=0, longest=0.000 s, average=0.000 s; distance=238 kB, estimate=4739 kB; lsn=0/1DD0D70, redo lsn=0/1DD0D70 horae-browser-checks> 2026-10-12 21:20:11.642 UTC [18] LOG: database system is shut down error: Cannot build '/nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv'. Reason: builder failed with exit code 1. Output paths: /nix/store/k1gx2amzn7d90a8mzji6la3k52ys0jx5-horae-browser-checks Last 25 log lines: > 2026-10-12 20:51:59.641 UTC [980] LOG: could not send data to client: Broken pipe > 2026-10-12 20:51:59.641 UTC [980] FATAL: connection to client lost > 2026-10-12 20:51:59.648 UTC [981] LOG: could not send data to client: Broken pipe > 2026-10-12 20:51:59.648 UTC [981] FATAL: connection to client lost > 2026-10-12 20:51:59.654 UTC [982] LOG: could not send data to client: Broken pipe > 2026-10-12 20:51:59.654 UTC [982] FATAL: connection to client lost > 2026-10-12 20:51:59.661 UTC [983] LOG: could not send data to client: Broken pipe > 2026-10-12 20:51:59.661 UTC [983] FATAL: connection to client lost > 2026-10-12 20:56:35.755 UTC [19] LOG: checkpoint starting: time > 2026-10-12 20:58:51.827 UTC [19] LOG: checkpoint complete: wrote 1335 buffers (8.1%); 1 WAL file(s) added, 0 removed, 0 recycled; write=136.061 s, sync=0.001 s, total=136.073 s; sync files=0, longest=0.000 s, average=0.000 s; distance=7859 kB, estimate=7859 kB; lsn=0/1CF8B98, redo lsn=0/1C998D0 > 2026-10-12 21:01:35.931 UTC [19] LOG: checkpoint starting: time > 2026-10-12 21:01:46.390 UTC [19] LOG: checkpoint complete: wrote 107 buffers (0.7%); 0 WAL file(s) added, 0 removed, 0 recycled; write=10.452 s, sync=0.001 s, total=10.459 s; sync files=0, longest=0.000 s, average=0.000 s; distance=578 kB, estimate=7131 kB; lsn=0/1D2DB28, redo lsn=0/1D2A480 > 2026-10-12 21:06:35.492 UTC [19] LOG: checkpoint starting: time > 2026-10-12 21:06:35.836 UTC [19] LOG: checkpoint complete: wrote 4 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.314 s, sync=0.001 s, total=0.344 s; sync files=0, longest=0.000 s, average=0.000 s; distance=51 kB, estimate=6423 kB; lsn=0/1D37338, redo lsn=0/1D372E0 > 2026-10-12 21:11:35.936 UTC [19] LOG: checkpoint starting: time > 2026-10-12 21:11:36.850 UTC [19] LOG: checkpoint complete: wrote 9 buffers (0.1%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.847 s, sync=0.001 s, total=0.914 s; sync files=0, longest=0.000 s, average=0.000 s; distance=80 kB, estimate=5789 kB; lsn=0/1D4B3E8, redo lsn=0/1D4B390 > 2026-10-12 21:16:35.952 UTC [19] LOG: checkpoint starting: time > 2026-10-12 21:16:42.197 UTC [19] LOG: checkpoint complete: wrote 65 buffers (0.4%); 0 WAL file(s) added, 0 removed, 0 recycled; write=6.232 s, sync=0.001 s, total=6.245 s; sync files=0, longest=0.000 s, average=0.000 s; distance=295 kB, estimate=5240 kB; lsn=0/1DA9820, redo lsn=0/1D95290 > 2026-10-12 21:20:11.172 UTC [18] LOG: received fast shutdown request > 2026-10-12 21:20:11.228 UTC [18] LOG: aborting any active transactions > 2026-10-12 21:20:11.298 UTC [18] LOG: background worker "logical replication launcher" (PID 24) exited with exit code 1 > 2026-10-12 21:20:11.298 UTC [19] LOG: shutting down > 2026-10-12 21:20:11.312 UTC [19] LOG: checkpoint starting: shutdown immediate > 2026-10-12 21:20:11.569 UTC [19] LOG: checkpoint complete: wrote 50 buffers (0.3%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.217 s, sync=0.001 s, total=0.264 s; sync files=0, longest=0.000 s, average=0.000 s; distance=238 kB, estimate=4739 kB; lsn=0/1DD0D70, redo lsn=0/1DD0D70 > 2026-10-12 21:20:11.642 UTC [18] LOG: database system is shut down For full logs, run: nix log /nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv nixbot: transient error detected, retrying once this derivation will be built: /nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv building '/nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv' horae-browser-checks> initdb: warning: enabling "trust" authentication for local connections horae-browser-checks> initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb. horae-browser-checks> waiting for server to start.... done horae-browser-checks> server started horae-browser-checks> 2026-10-12T21:20:49.467591Z INFO horae: Running migrations... horae-browser-checks> 2026-10-12T21:20:53.587359Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="-- New creation settings …" db.statement="\n\n-- New creation settings are opt-in. Existing and imported projects retain the\n-- legacy billing cascade when no project_settings row exists.\nALTER TABLE users ADD CONSTRAINT users_id_org_unique UNIQUE (id, org_id);\nALTER TABLE projects ADD CONSTRAINT projects_id_org_unique UNIQUE (id, org_id);\nALTER TABLE tasks ADD CONSTRAINT tasks_id_org_unique UNIQUE (id, org_id);\n\nALTER TABLE clients ADD COLUMN default_rate_cents bigint\n CHECK (default_rate_cents IS NULL OR default_rate_cents >= 0);\n\nCREATE TABLE project_drafts (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n creator_id uuid NOT NULL,\n revision bigint NOT NULL DEFAULT 1 CHECK (revision > 0),\n payload_version smallint NOT NULL DEFAULT 1 CHECK (payload_version = 1),\n payload jsonb NOT NULL CHECK (\n jsonb_typeof(payload) = 'object'\n AND octet_length(payload::text) <= 262144),\n completed_project_id uuid,\n discarded_at timestamptz,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n FOREIGN KEY (creator_id, org_id) REFERENCES users(id, org_id),\n FOREIGN KEY (completed_project_id, org_id) REFERENCES projects(id, org_id),\n CHECK (completed_project_id IS NULL OR discarded_at IS NULL)\n);\n\nCREATE UNIQUE INDEX project_drafts_current_creator_idx\n ON project_drafts (org_id, creator_id)\n WHERE completed_project_id IS NULL AND discarded_at IS NULL;\n\nCREATE TABLE project_settings (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL UNIQUE,\n creator_id uuid NOT NULL,\n rate_mode text NOT NULL CHECK (rate_mode IN ('person', 'task', 'project')),\n budget_scope text NOT NULL DEFAULT 'project'\n CHECK (budget_scope IN ('project', 'task', 'person')),\n monthly_reset boolean NOT NULL DEFAULT false,\n include_nonbillable boolean NOT NULL DEFAULT false,\n alert_enabled boolean NOT NULL DEFAULT false,\n alert_threshold smallint NOT NULL DEFAULT 80 CHECK (alert_threshold BETWEEN 0 AND 100),\n report_visibility text NOT NULL DEFAULT 'managers'\n CHECK (report_visibility IN ('managers', 'project_members')),\n fee_mode text CHECK (fee_mode IN ('single', 'milestones', 'monthly')),\n fee_amount_cents bigint CHECK (fee_amount_cents >= 0),\n monthly_day text CHECK (monthly_day IN ('first', 'fifteenth', 'last')),\n terms_days smallint NOT NULL DEFAULT 30 CHECK (terms_days BETWEEN 0 AND 365),\n po_number text NOT NULL DEFAULT '' CHECK (char_length(po_number) <= 200),\n discount_bps smallint NOT NULL DEFAULT 0 CHECK (discount_bps BETWEEN 0 AND 10000),\n tax1_bps smallint NOT NULL DEFAULT 0 CHECK (tax1_bps BETWEEN 0 AND 10000),\n tax2_name text CHECK (char_length(btrim(tax2_name)) BETWEEN 1 AND 100),\n tax2_bps smallint CHECK (tax2_bps BETWEEN 0 AND 10000),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE,\n FOREIGN KEY (creator_id, org_id) REFERENCES users(id, org_id),\n CHECK ((tax2_name IS NULL) = (tax2_bps IS NULL)),\n CHECK (CASE fee_mode\n WHEN 'single' THEN fee_amount_cents IS NOT NULL AND monthly_day IS NULL\n WHEN 'milestones' THEN fee_amount_cents IS NULL AND monthly_day IS NULL\n WHEN 'monthly' THEN fee_amount_cents IS NOT NULL AND monthly_day IS NOT NULL\n ELSE fee_amount_cents IS NULL AND monthly_day IS NULL\n END)\n);\n\n-- Private fields must not inherit table-level SELECT grants on projects or\n-- assignments held by the plugin database role.\nCREATE TABLE project_private_settings (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL UNIQUE,\n admin_notes text NOT NULL DEFAULT '' CHECK (char_length(admin_notes) <= 10000),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE\n);\n\nCREATE TABLE project_member_costs (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL,\n user_id uuid NOT NULL,\n cost_rate_cents bigint NOT NULL CHECK (cost_rate_cents >= 0),\n UNIQUE (project_id, user_id),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE,\n FOREIGN KEY (user_id, org_id) REFERENCES users(id, org_id),\n FOREIGN KEY (project_id, user_id) REFERENCES assignments(project_id, user_id) ON DELETE CASCADE\n);\n\nCREATE TABLE project_tags (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n name text NOT NULL CHECK (char_length(btrim(name)) BETWEEN 1 AND 50),\n UNIQUE (id, org_id)\n);\n\nCREATE UNIQUE INDEX project_tags_name_idx ON project_tags (org_id, lower(btrim(name)));\n\nCREATE TABLE project_tag_links (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL,\n tag_id uuid NOT NULL,\n UNIQUE (project_id, tag_id),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE,\n FOREIGN KEY (tag_id, org_id) REFERENCES project_tags(id, org_id)\n);\n\nCREATE TABLE project_task_settings (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL,\n task_id uuid NOT NULL,\n restricted boolean NOT NULL DEFAULT false,\n budget_minutes bigint CHECK (budget_minutes >= 0),\n budget_cents bigint CHECK (budget_cents >= 0),\n UNIQUE (project_id, task_id),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE,\n FOREIGN KEY (task_id, org_id) REFERENCES tasks(id, org_id),\n FOREIGN KEY (project_id, task_id) REFERENCES project_tasks(project_id, task_id) ON DELETE CASCADE,\n CHECK (budget_minutes IS NULL OR budget_cents IS NULL)\n);\n\nCREATE TABLE project_task_members (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL,\n task_id uuid NOT NULL,\n user_id uuid NOT NULL,\n UNIQUE (project_id, task_id, user_id),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE,\n FOREIGN KEY (task_id, org_id) REFERENCES tasks(id, org_id),\n FOREIGN KEY (user_id, org_id) REFERENCES users(id, org_id),\n FOREIGN KEY (project_id, task_id) REFERENCES project_task_settings(project_id, task_id) ON DELETE CASCADE,\n FOREIGN KEY (project_id, user_id) REFERENCES assignments(project_id, user_id) ON DELETE CASCADE\n);\n\nCREATE TABLE project_member_budgets (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL,\n user_id uuid NOT NULL,\n budget_minutes bigint NOT NULL CHECK (budget_minutes >= 0),\n UNIQUE (project_id, user_id),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE,\n FOREIGN KEY (user_id, org_id) REFERENCES users(id, org_id),\n FOREIGN KEY (project_id, user_id) REFERENCES assignments(project_id, user_id) ON DELETE CASCADE\n);\n\nCREATE TABLE project_fee_milestones (\n id uuid PRIMARY KEY,\n org_id uuid NOT NULL REFERENCES organizations(id),\n project_id uuid NOT NULL,\n name text NOT NULL CHECK (char_length(btrim(name)) BETWEEN 1 AND 200),\n due_on date NOT NULL,\n amount_cents bigint NOT NULL CHECK (amount_cents >= 0),\n position smallint NOT NULL CHECK (position BETWEEN 0 AND 99),\n UNIQUE (project_id, position),\n UNIQUE (id, org_id),\n FOREIGN KEY (project_id, org_id) REFERENCES projects(id, org_id) ON DELETE CASCADE\n);\n\nREVOKE ALL ON project_drafts, project_settings, project_private_settings,\n project_member_costs, project_tags, project_tag_links, project_task_settings,\n project_task_members, project_member_budgets, project_fee_milestones FROM PUBLIC;\n\n" rows_affected=0 rows_returned=0 elapsed=3.140160969s elapsed_secs=3.140160969 slow_threshold=1s horae-browser-checks> 2026-10-12T21:20:55.983693Z INFO horae: Migrations complete. horae-browser-checks> 2026-10-12T21:20:56.079223Z INFO horae::seed: Seeding demo data… horae-browser-checks> 2026-10-12T21:20:56.516539Z INFO horae::seed: Seed complete. horae-browser-checks> 2026-10-12T21:20:56.543477Z INFO horae::seed: time_entries: 10 rows horae-browser-checks> 2026-10-12T21:20:56.582975Z INFO horae::seed: clients: 2 rows horae-browser-checks> PASS: archived own timer labels survive without granting catalog or global-rate access horae-browser-checks> PASS: catalog/rate grants never enable unlinked or archived tasks for a new timer; valid start/stop persists horae-browser-checks> PASS: rail popovers accept clicks and release the resize handle after closing horae-browser-checks> PASS: scoped project list/detail expose workflow labels without directory access, private notes or rates horae-browser-checks> PASS: edit and managed-project revocation remove current UI authority without legacy Administrator fallback horae-browser-checks> PASS: inactive-account and changed-policy responses clear retained detail; retry recovers only the original binding horae-browser-checks> PASS: keyboard manager removal preserves archived membership and withheld money/notes at desktop and narrow widths horae-browser-checks> PASS: staged project task archive/restore, undo, cancellation and running-timer rejection preserve hidden configuration and restrictions horae-browser-checks> PASS: financial read grants display disabled values and ordinary saves preserve stored fields horae-browser-checks> PASS: explicit zero, cost reset and lost-acknowledgement replay preserve exact original intent horae-browser-checks> PASS: current-authority revocation discards old editor state; explicit reload restores a fresh authorized form horae-browser-checks> PASS: an explicit hours-only budget edit preserves inactive hidden money and recorded history horae-browser-checks> PASS: scoped report paging, totals, four individual reports, four nested breakdowns, filtered exports, stale/invalid states and policy binding; Chromium 148.0.7778.96 horae-browser-checks> ✔ permissions: pending navigation preserves history until the request is resolved (178.032192ms) horae-browser-checks> ✔ permissions: dirty navigation requires an explicit discard (214.582031ms) horae-browser-checks> ✔ client: pending navigation preserves history until the request is resolved (322.695268ms) horae-browser-checks> ✔ client: dirty navigation requires an explicit discard (1.650297ms) horae-browser-checks> ✔ invoice: pending navigation preserves history until the request is resolved (190.253963ms) horae-browser-checks> ✔ invoice: dirty navigation requires an explicit discard (153.932744ms) horae-browser-checks> ✔ project: pending navigation preserves history until the request is resolved (1.698083ms) horae-browser-checks> ✔ project: dirty navigation requires an explicit discard (162.746268ms) horae-browser-checks> ✔ timesheet: pending navigation preserves history until the request is resolved (1.223676ms) horae-browser-checks> ✔ timesheet: dirty navigation requires an explicit discard (103.109895ms) horae-browser-checks> ✔ permissions: scroll-only replacements preserve Dioxus coordinates without prompting (78.9375ms) horae-browser-checks> ✔ timesheet: scroll-only replacements preserve Dioxus coordinates without prompting (1.318223ms) horae-browser-checks> ✔ the legacy project opt-in and explicit release keep working (184.983973ms) horae-browser-checks> ℹ tests 13 horae-browser-checks> ℹ suites 0 horae-browser-checks> ℹ pass 13 horae-browser-checks> ℹ fail 0 horae-browser-checks> ℹ cancelled 0 horae-browser-checks> ℹ skipped 0 horae-browser-checks> ℹ todo 0 horae-browser-checks> ℹ duration_ms 2248.118476 horae-browser-checks> ✔ store acknowledgement precedes a load from a new execution (69.420539ms) horae-browser-checks> ✔ identical store is idempotent; another request cannot replace it (24.500553ms) horae-browser-checks> ✔ clear requires the exact stored record and is idempotent (58.599963ms) horae-browser-checks> ✔ storage errors never acknowledge a mutation or erase a request (20.597848ms) horae-browser-checks> ✔ size limit counts UTF-8 bytes on both reads and writes (45.803486ms) horae-browser-checks> ✔ other requesters and unrelated browser records are untouched (16.338298ms) horae-browser-checks> ℹ tests 6 horae-browser-checks> ℹ suites 0 horae-browser-checks> ℹ pass 6 horae-browser-checks> ℹ fail 0 horae-browser-checks> ℹ cancelled 0 horae-browser-checks> ℹ skipped 0 horae-browser-checks> ℹ todo 0 horae-browser-checks> ℹ duration_ms 284.395222 horae-browser-checks> Permission recovery browser: Chromium 148.0.7778.96 horae-browser-checks> PASS: canonical People separates read scope, Administrator editing and legacy roles without legacy reads horae-browser-checks> PASS: editor reload rejects a changed session and recovers only for the original requester horae-browser-checks> PASS: real person save survives lost response/reload and replays exactly one receipt horae-browser-checks> PASS: account changes isolate tab recovery; same-user reauthentication and restored authority recover the template horae-browser-checks> PASS: a deleted template is recovered from its exact receipt without recreating it horae-browser-checks> PASS: real permission history supports empty state, keyboard details, stable paging, deleted profiles, refresh/revocation and canonical access horae-browser-checks> PASS: storage refusal prevents sends; acknowledged self-demotion cleanup issues no second mutation horae-browser-checks> PASS: Export: semantics, keyboard, focus return, backdrop and short viewport horae-browser-checks> PASS: Add entry: semantics, keyboard, focus return, backdrop and short viewport horae-browser-checks> PASS: + Add row: semantics, keyboard, focus return, backdrop and short viewport horae-browser-checks> PASS: pending save blocks dismissal; failure preserves input and allows retry horae-browser-checks> PASS: row deletion is atomic after a stale-client lock and supports retry horae-browser-checks> PASS: move failure is visible and reconciles with saved data horae-browser-checks> PASS: resize failure is visible and reconciles with saved data horae-browser-checks> PASS: reorder failure is visible and reconciles with saved data horae-browser-checks> PASS: lost response failure is visible and reconciles with saved data horae-browser-checks> PASS: historical move works without current tracking choices horae-browser-checks> PASS: historical resize works without current tracking choices horae-browser-checks> PASS: historical reorder works without current tracking choices horae-browser-checks> PASS: day-view timer failure is visible horae-browser-checks> PASS: project scope includes zero-entry active teammates without exposing unrelated hours horae-browser-checks> PASS: changing person and browser history reload the correct sheet, including an empty teammate horae-browser-checks> PASS: Day and Week edits carry the selected owner and preserve hidden work horae-browser-checks> PASS: delegated creation uses the selected person and eligible project/task horae-browser-checks> PASS: delegated Calendar drawing, day movement and resizing persist exact minutes horae-browser-checks> PASS: delegated untimed moves and order inversions persist the complete ordered entry set horae-browser-checks> PASS: delegated modal and Week row deletion preserve unrelated hours and requester timer horae-browser-checks> PASS: revocation between click and commit rejects the write and preserves the draft/data horae-browser-checks> PASS: delegated timer leaves the requester timer alone and requires restored tracking eligibility horae-browser-checks> PASS: only the owner can use terminal recovery after losing project assignment horae-browser-checks> Timesheet read failed: 403 http://127.0.0.1:8093/api/load_timesheet_page16386063561583833955 horae-browser-checks> PASS: relationship revocation removes the selected sheet without falling back to own data horae-browser-checks> PASS: header actions, supported metrics and labelled native budget progress horae-browser-checks> PASS: design heading, compact row typography and inline project type horae-browser-checks> PASS: filtered empty state resets search, scope and client horae-browser-checks> PASS: narrow/short layouts, keyboard row actions and export formats horae-browser-checks> PASS: loading spend is unavailable until the read completes horae-browser-checks> PASS: failed spend is unavailable; retry restores real amounts horae-browser-checks> PASS: configured monthly consumption replaces lifetime spend only after loading horae-browser-checks> PASS: keyboard-accessible scope breakdown exposes overruns without layout overflow horae-browser-checks> PASS: failed configured budget never falls back to lifetime figures horae-browser-checks> PASS: empty-state guidance and action visibility for admin horae-browser-checks> PASS: empty-state guidance and action visibility for manager horae-browser-checks> PASS: empty-state guidance and action visibility for member horae-browser-checks> PASS: shared Menu, Combobox, empty-state and navigation-icon defaults are unchanged horae-browser-checks> PASS: /clients header at 320px horae-browser-checks> PASS: /clients header at 390px horae-browser-checks> PASS: /clients header at 768px horae-browser-checks> PASS: /clients header at 1280px horae-browser-checks> PASS: /clients header at 1440px horae-browser-checks> PASS: /projects header at 320px horae-browser-checks> PASS: /projects header at 390px horae-browser-checks> PASS: /projects header at 768px horae-browser-checks> PASS: /projects header at 1280px horae-browser-checks> PASS: /projects header at 1440px horae-browser-checks> PASS: /invoices header at 320px horae-browser-checks> PASS: /invoices header at 390px horae-browser-checks> PASS: /invoices header at 768px horae-browser-checks> PASS: /invoices header at 1280px horae-browser-checks> PASS: /invoices header at 1440px horae-browser-checks> PASS: /reports header at 320px horae-browser-checks> PASS: /reports header at 390px horae-browser-checks> PASS: /reports header at 768px horae-browser-checks> PASS: /reports header at 1280px horae-browser-checks> PASS: /reports header at 1440px horae-browser-checks> PASS: /admin/users header at 320px horae-browser-checks> PASS: /admin/users header at 390px horae-browser-checks> PASS: /admin/users header at 768px horae-browser-checks> PASS: /admin/users header at 1280px horae-browser-checks> PASS: /admin/users header at 1440px horae-browser-checks> PASS: /approvals header at 320px horae-browser-checks> PASS: /approvals header at 390px horae-browser-checks> PASS: /approvals header at 768px horae-browser-checks> PASS: /approvals header at 1280px horae-browser-checks> PASS: /approvals header at 1440px horae-browser-checks> PASS: /settings header at 320px horae-browser-checks> PASS: /settings header at 390px horae-browser-checks> PASS: /settings header at 768px horae-browser-checks> PASS: /settings header at 1280px horae-browser-checks> PASS: /settings header at 1440px horae-browser-checks> PASS: /admin/importers header at 320px horae-browser-checks> PASS: /admin/importers header at 390px horae-browser-checks> PASS: /admin/importers header at 768px horae-browser-checks> PASS: /admin/importers header at 1280px horae-browser-checks> PASS: /admin/importers header at 1440px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 320px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 390px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 768px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 1280px horae-browser-checks> PASS: /timesheet/week/2026-10-12 header at 1440px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 320px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 390px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 768px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 1280px horae-browser-checks> PASS: /timesheet/day/2026-10-12 header at 1440px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 320px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 390px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 768px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 1280px horae-browser-checks> PASS: /timesheet/calendar/2026-10-12 header at 1440px horae-browser-checks> PASS: project names and badges stay within aligned columns; scrolling to last-row actions opens editing horae-browser-checks> PASS: small-screen timesheet pager, date picker and view controls remain usable horae-browser-checks> PASS: admin subnavigation and its content remain reachable on mobile horae-browser-checks> PASS: day strip scrolls to Sunday and long entry labels do not cover actions horae-browser-checks> CHECK: late popover initialization restores missing focus without overriding deliberate focus horae-browser-checks> PASS: late popover initialization restores missing focus without overriding deliberate focus horae-browser-checks> CHECK: content reflow preserves an open menu while deliberate scrolling still dismisses it horae-browser-checks> PASS: content reflow preserves an open menu while deliberate scrolling still dismisses it horae-browser-checks> CHECK: first and last project-row actions are initially visible and clickable horae-browser-checks> PASS: first and last project-row actions are initially visible and clickable horae-browser-checks> CHECK: menu keyboard, disabled items, outside click and repeated opening horae-browser-checks> PASS: menu keyboard, disabled items, outside click and repeated opening horae-browser-checks> CHECK: scroll and resize dismiss without leaving stale menus or focus horae-browser-checks> PASS: scroll and resize dismiss without leaving stale menus or focus horae-browser-checks> CHECK: short-screen menu scrolls internally and supports reverse Tab and Space horae-browser-checks> PASS: short-screen menu scrolls internally and supports reverse Tab and Space horae-browser-checks> CHECK: filter and calendar menus keep their callbacks and survive route changes horae-browser-checks> PASS: filter and calendar menus keep their callbacks and survive route changes horae-browser-checks> CHECK: Timesheet keeps the shared calendar and week selection behavior horae-browser-checks> PASS: Timesheet keeps the shared calendar and week selection behavior horae-browser-checks> PASS: mobile content width, keyboard toggle, Escape/focus restoration and navigation close horae-browser-checks> PASS: short mobile viewport reaches account navigation and preserves desktop collapse state horae-browser-checks> PASS: desktop drag width survives mobile and breakpoint transitions horae-browser-checks> PASS: keyboard selection, mixed/select-all states and Actions count horae-browser-checks> PASS: search, status and client changes clear selection horae-browser-checks> PASS: keyboard selection/confirmation and no document overflow in both themes at three widths horae-browser-checks> PASS: cancel/focus, failure retry, pending guard and archive/reactivate confirmation horae-browser-checks> PASS: oversized selection cannot submit and members have no bulk controls horae-browser-checks> PASS: real atomic archive/reactivate, anonymous/member/inactive denial, manager/admin and safe retries horae-browser-checks> ExpectError: expect(locator).toHaveCount(expected) failed horae-browser-checks> horae-browser-checks> Locator: locator('.proj-row') horae-browser-checks> Expected: 2 horae-browser-checks> Received: 0 horae-browser-checks> Timeout: 5000ms horae-browser-checks> horae-browser-checks> Call log: horae-browser-checks> - Expect "to.have.count" with timeout 5000ms horae-browser-checks> - waiting for locator('.proj-row') horae-browser-checks> 3 × locator resolved to 0 elements horae-browser-checks> - unexpected value "0" horae-browser-checks> horae-browser-checks> at captureRawStack (/nix/store/i6xnc927g8yrwq0fws8wbmjvj4y36fq5-playwright-test-1.60.0/lib/node_modules/playwright-core/lib/coreBundle.js:3130:17) horae-browser-checks> at callMatcherAsStep (/nix/store/i6xnc927g8yrwq0fws8wbmjvj4y36fq5-playwright-test-1.60.0/lib/node_modules/playwright/lib/matchers/expect.js:12873:57) horae-browser-checks> at Object.toHaveCount (/nix/store/i6xnc927g8yrwq0fws8wbmjvj4y36fq5-playwright-test-1.60.0/lib/node_modules/playwright/lib/matchers/expect.js:12863:23) horae-browser-checks> at /nix/store/69j97diy8ybgln8phsmhlmbf07nb9rx1-horae/tests/browser/project-bulk-recovery.cjs:50:49 { horae-browser-checks> matcherResult: { horae-browser-checks> actual: 0, horae-browser-checks> expected: 2, horae-browser-checks> message: '\x1B[2mexpect(\x1B[22m\x1B[31mlocator\x1B[39m\x1B[2m).\x1B[22mtoHaveCount\x1B[2m(\x1B[22m\x1B[32mexpected\x1B[39m\x1B[2m)\x1B[22m failed\n' + horae-browser-checks> '\n' + horae-browser-checks> "Locator: locator('.proj-row')\n" + horae-browser-checks> 'Expected: \x1B[32m2\x1B[39m\n' + horae-browser-checks> 'Received: \x1B[31m0\x1B[39m\n' + horae-browser-checks> 'Timeout: 5000ms\n' + horae-browser-checks> '\n' + horae-browser-checks> 'Call log:\n' + horae-browser-checks> '\x1B[2m - Expect "to.have.count" with timeout 5000ms\x1B[22m\n' + horae-browser-checks> "\x1B[2m - waiting for locator('.proj-row')\x1B[22m\n" + horae-browser-checks> '\x1B[2m 3 × locator resolved to 0 elements\x1B[22m\n' + horae-browser-checks> '\x1B[2m - unexpected value "0"\x1B[22m\n', horae-browser-checks> name: 'toHaveCount', horae-browser-checks> pass: false, horae-browser-checks> log: [ horae-browser-checks> ' - Expect "to.have.count" with timeout 5000ms', horae-browser-checks> " - waiting for locator('.proj-row')", horae-browser-checks> ' 3 × locator resolved to 0 elements', horae-browser-checks> ' - unexpected value "0"' horae-browser-checks> ], horae-browser-checks> timeout: 5000, horae-browser-checks> ariaSnapshot: undefined horae-browser-checks> } horae-browser-checks> } horae-browser-checks> 2026-10-12T21:20:58.001705Z WARN horae: DEV_LOGIN=1: /auth/dev-login signs anyone in as an admin without a password. Use it for local development only. horae-browser-checks> 2026-10-12T21:23:13.179053Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="SELECT p.id, p.name, p.code, …" db.statement="\n\nSELECT p.id, p.name, p.code, c.name AS client_name, p.currency,\n CASE WHEN (CASE WHEN $4 THEN u.org_role IN ('admin', 'manager')\n ELSE ($8 OR ($9 AND management.id IS NOT NULL))\n AND ($10 OR ($11 AND management.id IS NOT NULL)) END)\n AND p.project_type <> 'non_billable'\n AND (settings.project_id IS NULL\n OR (p.project_type = 'time_and_materials' AND settings.rate_mode = 'task'))\n THEN p.currency END AS task_rate_currency,\n p.starts_on as \"starts_on: chrono::NaiveDate\",\n p.ends_on as \"ends_on: chrono::NaiveDate\",\n ARRAY(SELECT t.name FROM project_tag_links l\n JOIN project_tags t ON t.id = l.tag_id AND t.org_id = l.org_id\n WHERE l.project_id = p.id AND l.org_id = p.org_id\n ORDER BY lower(t.name), t.id) as \"tags!\",\n CASE WHEN (CASE WHEN $4 THEN u.org_role = 'admin' ELSE $7 END)\n THEN private.admin_notes END AS admin_notes\n FROM projects p\n JOIN clients c ON c.id = p.client_id AND c.org_id = p.org_id\n JOIN users u ON u.id = $2 AND u.org_id = p.org_id AND u.active\n LEFT JOIN project_read_access a ON a.project_id = p.id AND a.org_id = p.org_id AND a.user_id = u.id\n LEFT JOIN project_management_assignments management ON management.org_id = p.org_id\n AND management.project_id = p.id AND management.manager_id = u.id\n LEFT JOIN assignments member ON member.project_id = p.id AND member.user_id = u.id\n LEFT JOIN project_private_settings private ON private.project_id = p.id AND private.org_id = p.org_id\n LEFT JOIN project_settings settings ON settings.project_id = p.id AND settings.org_id = p.org_id\n WHERE p.org_id = $1 AND p.id = $3\n AND CASE WHEN $4 THEN COALESCE(a.can_view_progress, false)\n ELSE $5 OR ($6 AND management.id IS NOT NULL)\n OR (member.id IS NOT NULL AND COALESCE(settings.report_visibility, 'project_members') = 'project_members') END\n" rows_affected=1 rows_returned=1 elapsed=1.353492014s elapsed_secs=1.353492014 slow_threshold=1s horae-browser-checks> 2026-10-12T21:24:13.488397Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="WITH scoped AS NOT …" db.statement="\n\nWITH scoped AS NOT MATERIALIZED (\n SELECT e.id, e.spent_date, p.name AS project_name,\n t.name AS task_name, u.name AS user_name, e.minutes,\n effective_minutes(e.minutes,e.rounded_minutes,o.round_minutes,o.round_dir) AS rounded_minutes,\n (e.billable AND (e.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable,t.billable_default)))) AS billable, e.notes\n FROM time_entries e\n JOIN organizations o ON o.id=e.org_id\n JOIN users u ON u.id=e.user_id AND u.org_id=e.org_id\n JOIN projects p ON p.id=e.project_id AND p.org_id=e.org_id\n JOIN tasks t ON t.id=e.task_id AND t.org_id=e.org_id\n JOIN clients c ON c.id=p.client_id AND c.org_id=e.org_id\n LEFT JOIN project_tasks pt ON pt.project_id=p.id AND pt.task_id=t.id\n WHERE e.org_id=$1 AND (\n $5::bool OR ($3::bool AND e.user_id=$2) OR ($4::bool AND (\n EXISTS (SELECT 1 FROM person_management_assignments m\n WHERE m.org_id=e.org_id AND m.manager_id=$2 AND m.managed_user_id=e.user_id)\n OR EXISTS (SELECT 1 FROM project_management_assignments m\n WHERE m.org_id=e.org_id AND m.manager_id=$2 AND m.project_id=e.project_id))))\n AND e.spent_date BETWEEN $6 AND $7\n AND (NOT $17::bool OR p.active)\n AND ($18::bool IS NULL OR $18 = (e.billable AND (e.invoice_id IS NOT NULL\n OR (p.project_type <> 'non_billable' AND COALESCE(pt.billable,t.billable_default)))))\n AND (cardinality($8::uuid[])=0 OR p.client_id=ANY($8))\n AND (cardinality($9::uuid[])=0 OR e.project_id=ANY($9))\n AND (cardinality($10::uuid[])=0 OR e.user_id=ANY($10))\n AND (cardinality($11::uuid[])=0 OR e.task_id=ANY($11))\n AND (cardinality($12::uuid[])=0 OR EXISTS (\n SELECT 1 FROM project_tag_links l JOIN project_tags tag ON tag.id=l.tag_id AND tag.org_id=l.org_id\n WHERE l.org_id=e.org_id AND l.project_id=e.project_id AND tag.id=ANY($12)))\n ), stats AS (\n SELECT COUNT(*) AS entry_count,\n COALESCE(SUM(minutes),0)::bigint AS total_minutes,\n COALESCE(SUM(rounded_minutes),0)::bigint AS rounded_minutes,\n COALESCE(SUM(rounded_minutes) FILTER (WHERE billable),0)::bigint AS billable_minutes\n FROM scoped\n ), page AS (\n SELECT * FROM scoped\n WHERE ($13::date IS NULL OR (spent_date,project_name COLLATE \"C\",task_name COLLATE \"C\",id)\n > ($13,$14::text COLLATE \"C\",$15::text COLLATE \"C\",$16::uuid))\n ORDER BY spent_date,project_name COLLATE \"C\",task_name COLLATE \"C\",id LIMIT 501\n )\n SELECT s.entry_count AS \"entry_count!\", s.total_minutes AS \"total_minutes!\",\n s.rounded_minutes AS \"total_rounded_minutes!\", s.billable_minutes AS \"billable_minutes!\",\n p.id AS \"id?\", p.spent_date AS \"spent_date?: chrono::NaiveDate\",\n p.project_name AS \"project_name?\", p.task_name AS \"task_name?\", p.user_name AS \"user_name?\",\n p.minutes AS \"minutes?\", p.rounded_minutes AS \"rounded_minutes?\", p.billable AS \"billable?\", p.notes\n FROM stats s LEFT JOIN page p ON true\n ORDER BY p.spent_date,p.project_name COLLATE \"C\",p.task_name COLLATE \"C\",p.id\n" rows_affected=501 rows_returned=501 elapsed=1.443271653s elapsed_secs=1.443271653 slow_threshold=1s horae-browser-checks> 2026-10-12T21:24:50.408791Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="DECLARE horae_csv NO SCROLL …" db.statement="\n\nDECLARE horae_csv NO SCROLL CURSOR FOR\n WITH authority AS MATERIALIZED (\n SELECT o.permission_policy_version policy,u.active,\n s.catalog_version,s.grants,s.is_administrator,s.source permission_source,\n s.built_in_profile,s.template_id,s.applied_template_revision,s.revision,\n COALESCE(octet_length(s.source),0)::bigint + COALESCE(octet_length(s.built_in_profile),0)::bigint\n + COALESCE((SELECT SUM(octet_length(g)::bigint) FROM unnest(s.grants) g),0)::bigint authority_bytes\n FROM (VALUES ($1::uuid,$2::uuid)) identity(org_id,user_id)\n LEFT JOIN organizations o ON o.id=identity.org_id\n LEFT JOIN users u ON u.id=identity.user_id AND u.org_id=identity.org_id\n LEFT JOIN person_permission_states s ON s.org_id=o.id AND s.user_id=u.id\n ), scoped AS (\n SELECT CASE $10::text WHEN 'client' THEN c.id WHEN 'project' THEN p.id\n WHEN 'task' THEN t.id WHEN 'person' THEN u.id END group_id,\n CASE $10::text WHEN 'client' THEN c.name WHEN 'project' THEN p.name\n WHEN 'task' THEN t.name WHEN 'person' THEN u.name END name,\n te.user_id,te.project_id,\n effective_minutes(te.minutes,te.rounded_minutes,o.round_minutes,o.round_dir) rounded_minutes,\n (te.billable AND (te.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable,t.billable_default)))) billable\n FROM authority a CROSS JOIN time_entries te JOIN organizations o ON o.id=te.org_id\n JOIN projects p ON p.id=te.project_id AND p.org_id=te.org_id\n JOIN tasks t ON t.id=te.task_id AND t.org_id=te.org_id\n JOIN users u ON u.id=te.user_id AND u.org_id=te.org_id\n JOIN clients c ON c.id=p.client_id AND c.org_id=te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id=p.id AND pt.task_id=t.id\n WHERE te.org_id=$1 AND a.active AND a.policy=1 AND (\n 'time_read_all'=ANY(a.grants) OR ('time_read_own'=ANY(a.grants) AND te.user_id=$2)\n OR ('time_read_managed'=ANY(a.grants) AND (\n EXISTS (SELECT 1 FROM person_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.managed_user_id=te.user_id)\n OR EXISTS (SELECT 1 FROM project_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.project_id=te.project_id))))\n AND te.spent_date BETWEEN $3 AND $4\n AND (NOT $11::bool OR p.active)\n AND ($12::bool IS NULL OR $12 = (te.billable AND (te.invoice_id IS NOT NULL\n OR (p.project_type <> 'non_billable' AND COALESCE(pt.billable,t.billable_default)))))\n AND (cardinality($5::uuid[])=0 OR p.client_id=ANY($5))\n AND (cardinality($6::uuid[])=0 OR te.project_id=ANY($6))\n AND (cardinality($7::uuid[])=0 OR te.user_id=ANY($7))\n AND (cardinality($8::uuid[])=0 OR te.task_id=ANY($8))\n AND (cardinality($9::uuid[])=0 OR EXISTS (\n SELECT 1 FROM project_tag_links l JOIN project_tags tag ON tag.id=l.tag_id AND tag.org_id=l.org_id\n WHERE l.org_id=te.org_id AND l.project_id=te.project_id AND tag.id=ANY($9)))\n ), contexts AS (\n SELECT group_id,name,user_id,project_id,SUM(rounded_minutes)::bigint rounded_minutes,\n COALESCE(SUM(rounded_minutes) FILTER (WHERE billable),0)::bigint billable_minutes\n FROM scoped GROUP BY group_id,name,user_id,project_id\n ), fragments AS (\n SELECT group_id,name,user_id,project_id,\n SUM(rounded_minutes) OVER (PARTITION BY group_id)::bigint rounded_minutes,\n SUM(billable_minutes) OVER (PARTITION BY group_id)::bigint billable_minutes,\n ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY user_id DESC,project_id DESC)=1 last_context\n FROM contexts\n )\n SELECT a.policy,a.active,a.catalog_version,a.grants,a.is_administrator,\n a.permission_source,a.built_in_profile,a.template_id,a.applied_template_revision,a.revision,\n f.group_id,f.name,f.user_id,f.project_id,f.rounded_minutes,f.billable_minutes,f.last_context,\n 256::bigint + a.authority_bytes + COALESCE(octet_length(f.name),0)::bigint export_bytes\n FROM authority a LEFT JOIN fragments f ON true\n ORDER BY f.name COLLATE \"C\",f.group_id,f.user_id,f.project_id\n" rows_affected=0 rows_returned=0 elapsed=1.608012977s elapsed_secs=1.608012977 slow_threshold=1s horae-browser-checks> 2026-10-12T21:24:51.485632Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="SELECT policy,active,catalog_version,grants,is_administrator, permission_source,built_in_profile,template_id,applied_template_revision,revision, group_id,name,user_id,project_id,rounded_minutes,billable_minutes,last_context …" db.statement="\n\nSELECT policy,active,catalog_version,grants,is_administrator,\n permission_source,built_in_profile,template_id,applied_template_revision,revision,\n group_id,name,user_id,project_id,rounded_minutes,billable_minutes,last_context\n FROM fetch_csv_export_rows($1) AS source(policy integer,active boolean,\n catalog_version integer,grants text[],is_administrator boolean,permission_source text,\n built_in_profile text,template_id uuid,applied_template_revision bigint,revision bigint,\n group_id uuid,name text,user_id uuid,project_id uuid,rounded_minutes bigint,\n billable_minutes bigint,last_context boolean,export_bytes bigint)\n" rows_affected=1 rows_returned=1 elapsed=1.076536972s elapsed_secs=1.076536972 slow_threshold=1s horae-browser-checks> 2026-10-12T21:24:59.270381Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="DECLARE horae_csv NO SCROLL …" db.statement="\n\nDECLARE horae_csv NO SCROLL CURSOR FOR\n WITH authority AS MATERIALIZED (\n SELECT o.permission_policy_version policy,u.active,\n s.catalog_version,s.grants,s.is_administrator,s.source permission_source,\n s.built_in_profile,s.template_id,s.applied_template_revision,s.revision,\n COALESCE(octet_length(s.source),0)::bigint + COALESCE(octet_length(s.built_in_profile),0)::bigint\n + COALESCE((SELECT SUM(octet_length(g)::bigint) FROM unnest(s.grants) g),0)::bigint authority_bytes\n FROM (VALUES ($1::uuid,$2::uuid)) identity(org_id,user_id)\n LEFT JOIN organizations o ON o.id=identity.org_id\n LEFT JOIN users u ON u.id=identity.user_id AND u.org_id=identity.org_id\n LEFT JOIN person_permission_states s ON s.org_id=o.id AND s.user_id=u.id\n ), scoped AS (\n SELECT CASE $10::text WHEN 'client' THEN c.id WHEN 'project' THEN p.id\n WHEN 'task' THEN t.id WHEN 'person' THEN u.id END group_id,\n CASE $10::text WHEN 'client' THEN c.name WHEN 'project' THEN p.name\n WHEN 'task' THEN t.name WHEN 'person' THEN u.name END name,\n te.user_id,te.project_id,\n effective_minutes(te.minutes,te.rounded_minutes,o.round_minutes,o.round_dir) rounded_minutes,\n (te.billable AND (te.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable,t.billable_default)))) billable\n FROM authority a CROSS JOIN time_entries te JOIN organizations o ON o.id=te.org_id\n JOIN projects p ON p.id=te.project_id AND p.org_id=te.org_id\n JOIN tasks t ON t.id=te.task_id AND t.org_id=te.org_id\n JOIN users u ON u.id=te.user_id AND u.org_id=te.org_id\n JOIN clients c ON c.id=p.client_id AND c.org_id=te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id=p.id AND pt.task_id=t.id\n WHERE te.org_id=$1 AND a.active AND a.policy=1 AND (\n 'time_read_all'=ANY(a.grants) OR ('time_read_own'=ANY(a.grants) AND te.user_id=$2)\n OR ('time_read_managed'=ANY(a.grants) AND (\n EXISTS (SELECT 1 FROM person_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.managed_user_id=te.user_id)\n OR EXISTS (SELECT 1 FROM project_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.project_id=te.project_id))))\n AND te.spent_date BETWEEN $3 AND $4\n AND (NOT $11::bool OR p.active)\n AND ($12::bool IS NULL OR $12 = (te.billable AND (te.invoice_id IS NOT NULL\n OR (p.project_type <> 'non_billable' AND COALESCE(pt.billable,t.billable_default)))))\n AND (cardinality($5::uuid[])=0 OR p.client_id=ANY($5))\n AND (cardinality($6::uuid[])=0 OR te.project_id=ANY($6))\n AND (cardinality($7::uuid[])=0 OR te.user_id=ANY($7))\n AND (cardinality($8::uuid[])=0 OR te.task_id=ANY($8))\n AND (cardinality($9::uuid[])=0 OR EXISTS (\n SELECT 1 FROM project_tag_links l JOIN project_tags tag ON tag.id=l.tag_id AND tag.org_id=l.org_id\n WHERE l.org_id=te.org_id AND l.project_id=te.project_id AND tag.id=ANY($9)))\n ), contexts AS (\n SELECT group_id,name,user_id,project_id,SUM(rounded_minutes)::bigint rounded_minutes,\n COALESCE(SUM(rounded_minutes) FILTER (WHERE billable),0)::bigint billable_minutes\n FROM scoped GROUP BY group_id,name,user_id,project_id\n ), fragments AS (\n SELECT group_id,name,user_id,project_id,\n SUM(rounded_minutes) OVER (PARTITION BY group_id)::bigint rounded_minutes,\n SUM(billable_minutes) OVER (PARTITION BY group_id)::bigint billable_minutes,\n ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY user_id DESC,project_id DESC)=1 last_context\n FROM contexts\n )\n SELECT a.policy,a.active,a.catalog_version,a.grants,a.is_administrator,\n a.permission_source,a.built_in_profile,a.template_id,a.applied_template_revision,a.revision,\n f.group_id,f.name,f.user_id,f.project_id,f.rounded_minutes,f.billable_minutes,f.last_context,\n 256::bigint + a.authority_bytes + COALESCE(octet_length(f.name),0)::bigint export_bytes\n FROM authority a LEFT JOIN fragments f ON true\n ORDER BY f.name COLLATE \"C\",f.group_id,f.user_id,f.project_id\n" rows_affected=0 rows_returned=0 elapsed=1.709460094s elapsed_secs=1.709460094 slow_threshold=1s horae-browser-checks> 2026-10-12T21:25:01.957646Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="DECLARE horae_csv NO SCROLL …" db.statement="\n\nDECLARE horae_csv NO SCROLL CURSOR FOR\n WITH authority AS MATERIALIZED (\n SELECT o.permission_policy_version policy,u.active,\n s.catalog_version,s.grants,s.is_administrator,s.source permission_source,\n s.built_in_profile,s.template_id,s.applied_template_revision,s.revision,\n COALESCE(octet_length(s.source),0)::bigint + COALESCE(octet_length(s.built_in_profile),0)::bigint\n + COALESCE((SELECT SUM(octet_length(g)::bigint) FROM unnest(s.grants) g),0)::bigint authority_bytes\n FROM (VALUES ($1::uuid,$2::uuid)) identity(org_id,user_id)\n LEFT JOIN organizations o ON o.id=identity.org_id\n LEFT JOIN users u ON u.id=identity.user_id AND u.org_id=identity.org_id\n LEFT JOIN person_permission_states s ON s.org_id=o.id AND s.user_id=u.id\n ), scoped AS (\n SELECT CASE $10::text WHEN 'client' THEN c.id WHEN 'project' THEN p.id\n WHEN 'task' THEN t.id WHEN 'person' THEN u.id END group_id,\n CASE $10::text WHEN 'client' THEN c.name WHEN 'project' THEN p.name\n WHEN 'task' THEN t.name WHEN 'person' THEN u.name END name,\n te.user_id,te.project_id,\n effective_minutes(te.minutes,te.rounded_minutes,o.round_minutes,o.round_dir) rounded_minutes,\n (te.billable AND (te.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable,t.billable_default)))) billable\n FROM authority a CROSS JOIN time_entries te JOIN organizations o ON o.id=te.org_id\n JOIN projects p ON p.id=te.project_id AND p.org_id=te.org_id\n JOIN tasks t ON t.id=te.task_id AND t.org_id=te.org_id\n JOIN users u ON u.id=te.user_id AND u.org_id=te.org_id\n JOIN clients c ON c.id=p.client_id AND c.org_id=te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id=p.id AND pt.task_id=t.id\n WHERE te.org_id=$1 AND a.active AND a.policy=1 AND (\n 'time_read_all'=ANY(a.grants) OR ('time_read_own'=ANY(a.grants) AND te.user_id=$2)\n OR ('time_read_managed'=ANY(a.grants) AND (\n EXISTS (SELECT 1 FROM person_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.managed_user_id=te.user_id)\n OR EXISTS (SELECT 1 FROM project_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.project_id=te.project_id))))\n AND te.spent_date BETWEEN $3 AND $4\n AND (NOT $11::bool OR p.active)\n AND ($12::bool IS NULL OR $12 = (te.billable AND (te.invoice_id IS NOT NULL\n OR (p.project_type <> 'non_billable' AND COALESCE(pt.billable,t.billable_default)))))\n AND (cardinality($5::uuid[])=0 OR p.client_id=ANY($5))\n AND (cardinality($6::uuid[])=0 OR te.project_id=ANY($6))\n AND (cardinality($7::uuid[])=0 OR te.user_id=ANY($7))\n AND (cardinality($8::uuid[])=0 OR te.task_id=ANY($8))\n AND (cardinality($9::uuid[])=0 OR EXISTS (\n SELECT 1 FROM project_tag_links l JOIN project_tags tag ON tag.id=l.tag_id AND tag.org_id=l.org_id\n WHERE l.org_id=te.org_id AND l.project_id=te.project_id AND tag.id=ANY($9)))\n ), contexts AS (\n SELECT group_id,name,user_id,project_id,SUM(rounded_minutes)::bigint rounded_minutes,\n COALESCE(SUM(rounded_minutes) FILTER (WHERE billable),0)::bigint billable_minutes\n FROM scoped GROUP BY group_id,name,user_id,project_id\n ), fragments AS (\n SELECT group_id,name,user_id,project_id,\n SUM(rounded_minutes) OVER (PARTITION BY group_id)::bigint rounded_minutes,\n SUM(billable_minutes) OVER (PARTITION BY group_id)::bigint billable_minutes,\n ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY user_id DESC,project_id DESC)=1 last_context\n FROM contexts\n )\n SELECT a.policy,a.active,a.catalog_version,a.grants,a.is_administrator,\n a.permission_source,a.built_in_profile,a.template_id,a.applied_template_revision,a.revision,\n f.group_id,f.name,f.user_id,f.project_id,f.rounded_minutes,f.billable_minutes,f.last_context,\n 256::bigint + a.authority_bytes + COALESCE(octet_length(f.name),0)::bigint export_bytes\n FROM authority a LEFT JOIN fragments f ON true\n ORDER BY f.name COLLATE \"C\",f.group_id,f.user_id,f.project_id\n" rows_affected=0 rows_returned=0 elapsed=1.672647051s elapsed_secs=1.672647051 slow_threshold=1s horae-browser-checks> 2026-10-12T21:25:04.627644Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="DECLARE horae_csv NO SCROLL …" db.statement="\n\nDECLARE horae_csv NO SCROLL CURSOR FOR\n WITH authority AS MATERIALIZED (\n SELECT o.permission_policy_version policy,u.active,\n s.catalog_version,s.grants,s.is_administrator,s.source permission_source,\n s.built_in_profile,s.template_id,s.applied_template_revision,s.revision,\n COALESCE(octet_length(s.source),0)::bigint + COALESCE(octet_length(s.built_in_profile),0)::bigint\n + COALESCE((SELECT SUM(octet_length(g)::bigint) FROM unnest(s.grants) g),0)::bigint authority_bytes\n FROM (VALUES ($1::uuid,$2::uuid)) identity(org_id,user_id)\n LEFT JOIN organizations o ON o.id=identity.org_id\n LEFT JOIN users u ON u.id=identity.user_id AND u.org_id=identity.org_id\n LEFT JOIN person_permission_states s ON s.org_id=o.id AND s.user_id=u.id\n ), scoped AS (\n SELECT CASE $10::text WHEN 'client' THEN c.id WHEN 'project' THEN p.id\n WHEN 'task' THEN t.id WHEN 'person' THEN u.id END group_id,\n CASE $10::text WHEN 'client' THEN c.name WHEN 'project' THEN p.name\n WHEN 'task' THEN t.name WHEN 'person' THEN u.name END name,\n te.user_id,te.project_id,\n effective_minutes(te.minutes,te.rounded_minutes,o.round_minutes,o.round_dir) rounded_minutes,\n (te.billable AND (te.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable,t.billable_default)))) billable\n FROM authority a CROSS JOIN time_entries te JOIN organizations o ON o.id=te.org_id\n JOIN projects p ON p.id=te.project_id AND p.org_id=te.org_id\n JOIN tasks t ON t.id=te.task_id AND t.org_id=te.org_id\n JOIN users u ON u.id=te.user_id AND u.org_id=te.org_id\n JOIN clients c ON c.id=p.client_id AND c.org_id=te.org_id\n LEFT JOIN project_tasks pt ON pt.project_id=p.id AND pt.task_id=t.id\n WHERE te.org_id=$1 AND a.active AND a.policy=1 AND (\n 'time_read_all'=ANY(a.grants) OR ('time_read_own'=ANY(a.grants) AND te.user_id=$2)\n OR ('time_read_managed'=ANY(a.grants) AND (\n EXISTS (SELECT 1 FROM person_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.managed_user_id=te.user_id)\n OR EXISTS (SELECT 1 FROM project_management_assignments m\n WHERE m.org_id=te.org_id AND m.manager_id=$2 AND m.project_id=te.project_id))))\n AND te.spent_date BETWEEN $3 AND $4\n AND (NOT $11::bool OR p.active)\n AND ($12::bool IS NULL OR $12 = (te.billable AND (te.invoice_id IS NOT NULL\n OR (p.project_type <> 'non_billable' AND COALESCE(pt.billable,t.billable_default)))))\n AND (cardinality($5::uuid[])=0 OR p.client_id=ANY($5))\n AND (cardinality($6::uuid[])=0 OR te.project_id=ANY($6))\n AND (cardinality($7::uuid[])=0 OR te.user_id=ANY($7))\n AND (cardinality($8::uuid[])=0 OR te.task_id=ANY($8))\n AND (cardinality($9::uuid[])=0 OR EXISTS (\n SELECT 1 FROM project_tag_links l JOIN project_tags tag ON tag.id=l.tag_id AND tag.org_id=l.org_id\n WHERE l.org_id=te.org_id AND l.project_id=te.project_id AND tag.id=ANY($9)))\n ), contexts AS (\n SELECT group_id,name,user_id,project_id,SUM(rounded_minutes)::bigint rounded_minutes,\n COALESCE(SUM(rounded_minutes) FILTER (WHERE billable),0)::bigint billable_minutes\n FROM scoped GROUP BY group_id,name,user_id,project_id\n ), fragments AS (\n SELECT group_id,name,user_id,project_id,\n SUM(rounded_minutes) OVER (PARTITION BY group_id)::bigint rounded_minutes,\n SUM(billable_minutes) OVER (PARTITION BY group_id)::bigint billable_minutes,\n ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY user_id DESC,project_id DESC)=1 last_context\n FROM contexts\n )\n SELECT a.policy,a.active,a.catalog_version,a.grants,a.is_administrator,\n a.permission_source,a.built_in_profile,a.template_id,a.applied_template_revision,a.revision,\n f.group_id,f.name,f.user_id,f.project_id,f.rounded_minutes,f.billable_minutes,f.last_context,\n 256::bigint + a.authority_bytes + COALESCE(octet_length(f.name),0)::bigint export_bytes\n FROM authority a LEFT JOIN fragments f ON true\n ORDER BY f.name COLLATE \"C\",f.group_id,f.user_id,f.project_id\n" rows_affected=0 rows_returned=0 elapsed=1.05798917s elapsed_secs=1.05798917 slow_threshold=1s horae-browser-checks> 2026-10-12T21:26:27.182384Z WARN sqlx::query: slow statement: execution time exceeded alert threshold summary="WITH scoped AS NOT …" db.statement="\n\nWITH scoped AS NOT MATERIALIZED (\n SELECT e.id, e.spent_date, p.name AS project_name,\n t.name AS task_name, u.name AS user_name, e.minutes,\n effective_minutes(e.minutes,e.rounded_minutes,o.round_minutes,o.round_dir) AS rounded_minutes,\n (e.billable AND (e.invoice_id IS NOT NULL OR (p.project_type <> 'non_billable'\n AND COALESCE(pt.billable,t.billable_default)))) AS billable, e.notes\n FROM time_entries e\n JOIN organizations o ON o.id=e.org_id\n JOIN users u ON u.id=e.user_id AND u.org_id=e.org_id\n JOIN projects p ON p.id=e.project_id AND p.org_id=e.org_id\n JOIN tasks t ON t.id=e.task_id AND t.org_id=e.org_id\n JOIN clients c ON c.id=p.client_id AND c.org_id=e.org_id\n LEFT JOIN project_tasks pt ON pt.project_id=p.id AND pt.task_id=t.id\n WHERE e.org_id=$1 AND (\n $5::bool OR ($3::bool AND e.user_id=$2) OR ($4::bool AND (\n EXISTS (SELECT 1 FROM person_management_assignments m\n WHERE m.org_id=e.org_id AND m.manager_id=$2 AND m.managed_user_id=e.user_id)\n OR EXISTS (SELECT 1 FROM project_management_assignments m\n WHERE m.org_id=e.org_id AND m.manager_id=$2 AND m.project_id=e.project_id))))\n AND e.spent_date BETWEEN $6 AND $7\n AND (NOT $17::bool OR p.active)\n AND ($18::bool IS NULL OR $18 = (e.billable AND (e.invoice_id IS NOT NULL\n OR (p.project_type <> 'non_billable' AND COALESCE(pt.billable,t.billable_default)))))\n AND (cardinality($8::uuid[])=0 OR p.client_id=ANY($8))\n AND (cardinality($9::uuid[])=0 OR e.project_id=ANY($9))\n AND (cardinality($10::uuid[])=0 OR e.user_id=ANY($10))\n AND (cardinality($11::uuid[])=0 OR e.task_id=ANY($11))\n AND (cardinality($12::uuid[])=0 OR EXISTS (\n SELECT 1 FROM project_tag_links l JOIN project_tags tag ON tag.id=l.tag_id AND tag.org_id=l.org_id\n WHERE l.org_id=e.org_id AND l.project_id=e.project_id AND tag.id=ANY($12)))\n ), stats AS (\n SELECT COUNT(*) AS entry_count,\n COALESCE(SUM(minutes),0)::bigint AS total_minutes,\n COALESCE(SUM(rounded_minutes),0)::bigint AS rounded_minutes,\n COALESCE(SUM(rounded_minutes) FILTER (WHERE billable),0)::bigint AS billable_minutes\n FROM scoped\n ), page AS (\n SELECT * FROM scoped\n WHERE ($13::date IS NULL OR (spent_date,project_name COLLATE \"C\",task_name COLLATE \"C\",id)\n > ($13,$14::text COLLATE \"C\",$15::text COLLATE \"C\",$16::uuid))\n ORDER BY spent_date,project_name COLLATE \"C\",task_name COLLATE \"C\",id LIMIT 501\n )\n SELECT s.entry_count AS \"entry_count!\", s.total_minutes AS \"total_minutes!\",\n s.rounded_minutes AS \"total_rounded_minutes!\", s.billable_minutes AS \"billable_minutes!\",\n p.id AS \"id?\", p.spent_date AS \"spent_date?: chrono::NaiveDate\",\n p.project_name AS \"project_name?\", p.task_name AS \"task_name?\", p.user_name AS \"user_name?\",\n p.minutes AS \"minutes?\", p.rounded_minutes AS \"rounded_minutes?\", p.billable AS \"billable?\", p.notes\n FROM stats s LEFT JOIN page p ON true\n ORDER BY p.spent_date,p.project_name COLLATE \"C\",p.task_name COLLATE \"C\",p.id\n" rows_affected=501 rows_returned=501 elapsed=1.0162269s elapsed_secs=1.0162269 slow_threshold=1s horae-browser-checks> 2026-10-12 21:20:44.491 UTC [18] LOG: starting PostgreSQL 17.10 on x86_64-pc-linux-gnu, compiled by clang version 21.1.8, 64-bit horae-browser-checks> 2026-10-12 21:20:44.495 UTC [18] LOG: listening on Unix socket "/tmp/horae-browser.JaZlCI/.s.PGSQL.5432" horae-browser-checks> 2026-10-12 21:20:44.556 UTC [21] LOG: database system was shut down at 2026-10-12 21:20:42 UTC horae-browser-checks> 2026-10-12 21:20:44.608 UTC [18] LOG: database system is ready to accept connections horae-browser-checks> 2026-10-12 21:20:55.988 UTC [77] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:20:55.994 UTC [77] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:25:44.671 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:27:26.136 UTC [926] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:26.137 UTC [926] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:26.368 UTC [924] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:26.368 UTC [924] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:26.435 UTC [923] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:26.436 UTC [923] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:26.931 UTC [929] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:26.931 UTC [929] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:26.944 UTC [879] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:26.944 UTC [879] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:26.980 UTC [930] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:26.980 UTC [930] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.018 UTC [931] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.019 UTC [931] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.163 UTC [934] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.163 UTC [934] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.176 UTC [932] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.176 UTC [932] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.227 UTC [935] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.227 UTC [935] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.332 UTC [937] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.332 UTC [937] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.399 UTC [936] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.399 UTC [936] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.446 UTC [933] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.446 UTC [933] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.633 UTC [939] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.633 UTC [939] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.729 UTC [941] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.729 UTC [941] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.772 UTC [942] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.772 UTC [942] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.782 UTC [938] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.783 UTC [938] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:27.806 UTC [940] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:27.806 UTC [940] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.133 UTC [945] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.133 UTC [945] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.153 UTC [944] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.153 UTC [944] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.303 UTC [943] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.303 UTC [943] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.332 UTC [947] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.332 UTC [947] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.351 UTC [948] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.351 UTC [948] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.378 UTC [946] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.378 UTC [946] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.408 UTC [950] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.408 UTC [950] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.842 UTC [951] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.842 UTC [951] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:28.988 UTC [953] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:28.992 UTC [953] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.069 UTC [952] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.069 UTC [952] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.251 UTC [955] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.251 UTC [955] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.293 UTC [949] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.293 UTC [949] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.384 UTC [957] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.384 UTC [957] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.442 UTC [956] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.442 UTC [956] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.554 UTC [958] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.554 UTC [958] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.571 UTC [960] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.575 UTC [960] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.589 UTC [954] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.589 UTC [954] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:29.632 UTC [959] LOG: could not send data to client: Broken pipe horae-browser-checks> 2026-10-12 21:27:29.632 UTC [959] FATAL: connection to client lost horae-browser-checks> 2026-10-12 21:27:56.410 UTC [19] LOG: checkpoint complete: wrote 1246 buffers (7.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=131.664 s, sync=0.001 s, total=131.740 s; sync files=0, longest=0.000 s, average=0.000 s; distance=6800 kB, estimate=6800 kB; lsn=0/1BD9FC0, redo lsn=0/1B90B58 horae-browser-checks> 2026-10-12 21:30:44.551 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:30:50.822 UTC [19] LOG: checkpoint complete: wrote 65 buffers (0.4%); 1 WAL file(s) added, 0 removed, 0 recycled; write=6.249 s, sync=0.001 s, total=6.271 s; sync files=0, longest=0.000 s, average=0.000 s; distance=438 kB, estimate=6164 kB; lsn=0/1C02508, redo lsn=0/1BFE720 horae-browser-checks> 2026-10-12 21:35:44.923 UTC [19] LOG: checkpoint starting: time horae-browser-checks> 2026-10-12 21:35:52.735 UTC [19] LOG: checkpoint complete: wrote 76 buffers (0.5%); 0 WAL file(s) added, 0 removed, 0 recycled; write=7.787 s, sync=0.001 s, total=7.812 s; sync files=0, longest=0.000 s, average=0.000 s; distance=307 kB, estimate=5578 kB; lsn=0/1C5A580, redo lsn=0/1C4B320 horae-browser-checks> 2026-10-12 21:40:42.782 UTC [18] LOG: received fast shutdown request horae-browser-checks> 2026-10-12 21:40:42.793 UTC [18] LOG: aborting any active transactions horae-browser-checks> 2026-10-12 21:40:42.849 UTC [18] LOG: background worker "logical replication launcher" (PID 24) exited with exit code 1 horae-browser-checks> 2026-10-12 21:40:42.851 UTC [19] LOG: shutting down horae-browser-checks> 2026-10-12 21:40:42.860 UTC [19] LOG: checkpoint starting: shutdown immediate horae-browser-checks> 2026-10-12 21:40:42.959 UTC [19] LOG: checkpoint complete: wrote 29 buffers (0.2%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.079 s, sync=0.001 s, total=0.108 s; sync files=0, longest=0.000 s, average=0.000 s; distance=153 kB, estimate=5036 kB; lsn=0/1C71870, redo lsn=0/1C71870 horae-browser-checks> 2026-10-12 21:40:43.270 UTC [18] LOG: database system is shut down error: Cannot build '/nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv'. Reason: builder failed with exit code 1. Output paths: /nix/store/k1gx2amzn7d90a8mzji6la3k52ys0jx5-horae-browser-checks Last 25 log lines: > 2026-10-12 21:27:29.293 UTC [949] FATAL: connection to client lost > 2026-10-12 21:27:29.384 UTC [957] LOG: could not send data to client: Broken pipe > 2026-10-12 21:27:29.384 UTC [957] FATAL: connection to client lost > 2026-10-12 21:27:29.442 UTC [956] LOG: could not send data to client: Broken pipe > 2026-10-12 21:27:29.442 UTC [956] FATAL: connection to client lost > 2026-10-12 21:27:29.554 UTC [958] LOG: could not send data to client: Broken pipe > 2026-10-12 21:27:29.554 UTC [958] FATAL: connection to client lost > 2026-10-12 21:27:29.571 UTC [960] LOG: could not send data to client: Broken pipe > 2026-10-12 21:27:29.575 UTC [960] FATAL: connection to client lost > 2026-10-12 21:27:29.589 UTC [954] LOG: could not send data to client: Broken pipe > 2026-10-12 21:27:29.589 UTC [954] FATAL: connection to client lost > 2026-10-12 21:27:29.632 UTC [959] LOG: could not send data to client: Broken pipe > 2026-10-12 21:27:29.632 UTC [959] FATAL: connection to client lost > 2026-10-12 21:27:56.410 UTC [19] LOG: checkpoint complete: wrote 1246 buffers (7.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=131.664 s, sync=0.001 s, total=131.740 s; sync files=0, longest=0.000 s, average=0.000 s; distance=6800 kB, estimate=6800 kB; lsn=0/1BD9FC0, redo lsn=0/1B90B58 > 2026-10-12 21:30:44.551 UTC [19] LOG: checkpoint starting: time > 2026-10-12 21:30:50.822 UTC [19] LOG: checkpoint complete: wrote 65 buffers (0.4%); 1 WAL file(s) added, 0 removed, 0 recycled; write=6.249 s, sync=0.001 s, total=6.271 s; sync files=0, longest=0.000 s, average=0.000 s; distance=438 kB, estimate=6164 kB; lsn=0/1C02508, redo lsn=0/1BFE720 > 2026-10-12 21:35:44.923 UTC [19] LOG: checkpoint starting: time > 2026-10-12 21:35:52.735 UTC [19] LOG: checkpoint complete: wrote 76 buffers (0.5%); 0 WAL file(s) added, 0 removed, 0 recycled; write=7.787 s, sync=0.001 s, total=7.812 s; sync files=0, longest=0.000 s, average=0.000 s; distance=307 kB, estimate=5578 kB; lsn=0/1C5A580, redo lsn=0/1C4B320 > 2026-10-12 21:40:42.782 UTC [18] LOG: received fast shutdown request > 2026-10-12 21:40:42.793 UTC [18] LOG: aborting any active transactions > 2026-10-12 21:40:42.849 UTC [18] LOG: background worker "logical replication launcher" (PID 24) exited with exit code 1 > 2026-10-12 21:40:42.851 UTC [19] LOG: shutting down > 2026-10-12 21:40:42.860 UTC [19] LOG: checkpoint starting: shutdown immediate > 2026-10-12 21:40:42.959 UTC [19] LOG: checkpoint complete: wrote 29 buffers (0.2%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.079 s, sync=0.001 s, total=0.108 s; sync files=0, longest=0.000 s, average=0.000 s; distance=153 kB, estimate=5036 kB; lsn=0/1C71870, redo lsn=0/1C71870 > 2026-10-12 21:40:43.270 UTC [18] LOG: database system is shut down For full logs, run: nix log /nix/store/kkhd47qgr3i21n0sqdkm0rmmiyf4qv3g-horae-browser-checks.drv