Past Due must track the deadline (Due Date), not Schedule On. Keep dueDate and scheduledDate PATCH mutations independent so rescheduling alone does not clear Past Due.
Map board PendingUpliftCount through WorkOrderDetailService.MapInfo and ignore soft-deleted dispatches in the aggregate so SH-188 gating is authoritative for board/search/detail.
Close the remaining SH-221 bypass: board/legacy comments and completion-doc now enforce server-derived account scope, authorize before blob storage, and cover cross-account regressions.
Stamp WorkOrder.AccountId on all create paths and filter board/list/search/detail by server-derived account claims so scoped callers cannot cross accounts.
Co-authored-by: Cursor <cursoragent@cursor.com>
Derive staff vs technician scope from claims (Assigned for User), map
DbUpdateConcurrencyException to a stable 409, and add SQLite competing-write
tests for categorize-vs-categorize and categorize-vs-delete.
Require an authenticated ClaimsPrincipal at service entry and filter
tracked work orders with board base scope so deleted/template rows
surface as NotFound without disclosure.
Enforce MIME/extension/magic-byte validation, auth and workOrderVersion concurrency, audit on category changes, and validate-before-store with blob compensate.
Expose completedDate on PATCH /workorders/{id}/board so CompDoc can leave legacy EditWorkorder. Allow optional media category on upload, PATCH category afterward, and enforce JPG/PNG/MP4/MOV allowlist (SH-116).
* feat(work-orders): enrich board search overdue filters and 0-based paging
* fix(work-orders): align stacked services with CI build
* fix(tests): pass userDataService in comment service unit test
* fix(work-orders): use dedicated overdue query flag
Stop treating WorkOrderType.Other as an overdue sentinel. Board and advanced search now accept overdue=true while types=Other filters real Other rows; combining both uses OR.
* feat(work-orders): allow comment edit and resolve author audit display names
Add PATCH comment for author/Admin, return authorName, and resolve
AssignTo audit values to user display names.
* fix(work-orders): enforce author-only comment edits per SH-122
Remove the undocumented Admin override so only the original comment author can edit, matching the ticket acceptance criteria.
---------
Co-authored-by: Arthur Bassi <arthur.winiarski.ranger@outlook.com>
Co-authored-by: Alexandre Brandizzi <alex_brandizzi@hotmail.com>
* feat(work-orders): enrich board search overdue filters and 0-based paging
* fix(work-orders): align stacked services with CI build
* fix(tests): pass userDataService in comment service unit test
* fix(work-orders): use dedicated overdue query flag
Stop treating WorkOrderType.Other as an overdue sentinel. Board and advanced search now accept overdue=true while types=Other filters real Other rows; combining both uses OR.
* test(work-orders): cover overdue date/status boundary and Other type-filter
Lock the PR #23 overdue regression boundary through the public advanced
search service. Prove overdue filtering is driven by past-due date plus
non-terminal status, not by the WorkOrderType.Other sentinel:
- Other + future/not-completed excluded from overdue
- past-due + Scheduled included; past-due + Completed/Canceled excluded
- types=[PM, Other] keeps real Other rows and does not pull past-due rows
- assert 0-based paging (Page=0) is preserved alongside overdue/type filters
---------
Co-authored-by: Arthur Bassi <arthur.winiarski.ranger@outlook.com>
Co-authored-by: Alexandre Brandizzi <alex_brandizzi@hotmail.com>
* refactor(api): enforce service and data-service boundaries
* refactor(api): complete feature service boundaries
* refactor(identity): enforce service and data boundaries
* refactor(vendors): enforce service and data boundaries
* refactor(workorders): enforce service and data boundaries
* refactor(backend): enforce architecture and optimize dispatch
* style(backend): format changed architecture files
* fix(architecture): address backend review follow-ups
* fix(backend): sanitize exception disclosure in changed API endpoints
Replace raw exception-message disclosure (ex.Message) returned to API
callers with a stable sanitized public message plus correlated structured
internal logging, across the endpoints changed in this PR.
- Add SanitizedErrors helper: logs the original exception at Error with a
generated correlation id and returns a stable public message referencing
it so support can trace without exposing internals.
- Inject ILogger<T> into the 14 changed controllers and route every
ex.Message/dbex.Message disclosure through the helper, preserving status
codes, response shapes, and business data (e.g. OpenWorkOrders).
- Leave FluentValidation (vex.Errors) and existing fixed-message catches
untouched; out-of-scope controllers (Account/Contact/Employee/Asset/
PMSchedule) are unchanged.
- Add focused tests proving internal exception text is not returned and
that Error logging carrying the original exception is invoked.
* fix(architecture): abstract job run state access
* style: format board update service
* test: use collection assertion idiom