Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
62 KiB
62 KiB
Scratchpad — Board-Specific Ticket Statuses
- Plan slug:
board-specific-ticket-statuses - Created:
2026-03-14
What This Is
Keep a lightweight, continuously-updated log of discoveries and decisions made while implementing this plan.
Prefer short bullets. Append new entries as you learn things, and also update earlier notes when a decision changes or an open question is resolved.
Decisions
- (2026-03-14) Scope is ticket statuses only. Project, interaction, and project-task statuses stay unchanged in this phase.
- (2026-03-14) Ticket statuses will use separate board-owned records, not board-level overrides on top of tenant-global statuses.
- (2026-03-14) Keep the existing
statusestable and add board ownership for ticket statuses instead of introducing a second ticket-status table. - (2026-03-14) Migration must clone current tenant-wide ticket statuses onto every board and generate new board-owned
status_idvalues. - (2026-03-14) Saved ticket-status references should be automatically remapped where board context exists.
- (2026-03-14) Changing a ticket board must require explicit user status reselection. No runtime auto-remap.
- (2026-03-14) New board creation must let admins either copy statuses from an existing board or create statuses inline.
- (2026-03-14) Ticket board changes are now blocked in both backend update paths and the
TicketInfoUI until the user explicitly selects a destination-board status, which prevents the old board's status from being silently retained. - (2026-03-14) New board creation now has an explicit copy-source board picker; save passes
copy_ticket_statuses_from_board_idintocreateBoard, and the action clones board-owned ticket statuses with fresh ids onto the new board. - (2026-03-14) Board create now supports a
status_seed_modeswitch. Increate_inlinemode the dialog carries an unsavedinline_ticket_statusesarray and sends it tocreateBoardas explicit board-owned status rows. - (2026-03-14)
F001/F002: addstatuses.board_idas nullable first, then enforce ticket ownership after clone/remap. Rationale: current tenant-global ticket rows must survive until the data migration rewrites them. - (2026-03-14)
F003/F004/F005: keep the legacy tenant-global ticket status rows in place for now and clone from them during migration, because later remap steps still need the old ids to rewrite inbound, billing, and workflow references before the global rows can be retired. - (2026-03-14)
F006/F007/F008: remap saved status references by joining legacy global ticket statuses to their board-owned clones viatenant + board_id + status name. Rationale: the old global status ids remain available during migration, so we can rewrite board-context tables without persisting a separate remap table. - (2026-03-14)
T003/T004/T005/T006: cover the clone/remap migration with a DB-backed integration fixture that seeds one tenant, two boards, two legacy ticket statuses, and board-specific tickets before invoking the migration directly. - (2026-03-14)
F006/F007/F008: remap inbound defaults, tenant billing renewal defaults, and contract renewal overrides by joining cloned ticket statuses back to the legacy status name within the saved board context. - (2026-03-14)
T007/T008/T009: cover board-context remaps with a DB-backed integration fixture that runs the clone migration first, then asserts each persisted configuration surface moves from the legacy global status id to the correct board-owned replacement. - (2026-03-14)
F025was too broad once Quick Add landed: narrowed it to the already-shipped Quick Add board-scoped status work, then split follow-up work intoF043(bulk update surfaces) andF044(auxiliary ticket creation helpers). Rationale: there is no standalone bulk ticket status edit UI in this branch today, so the remaining work needs separate traceable items instead of one mixed feature. - (2026-03-14)
F028/F029/F030: workflow ticket status handling now uses saved board context end-to-end. Authoring pickers depend on fixedboard_idorticket_id, create/update runtime paths reject cross-board statuses before calling shared ticket writes, andtickets.closeresolves the closed status from the ticket's own board. Rationale: workflow actions were one of the last places still capable of surfacing or persisting tenant-global ticket status assumptions. - (2026-03-14)
F032/F033: public ticket status APIs now expose board-owned ticket statuses only./api/v1/tickets/statuseshonors optionalboard_idand always excludes legacy board-less ticket rows, while generic/api/v1/statusesrequiresboard_idfortype=ticket, hides legacy ticket rows by id, and the old shared reference-data status CRUD rejects ticket status mutation in favor of board-local status actions. - (2026-03-14)
F034: join-heavy ticket reads were mostly already safe because they join onstatus_id, but two board-owned regressions remained:TicketService.search(...)did not project ticket status metadata at all, so search callers could not reliably see the board-owned status state.TicketService.getTicketStats(...)grouped counts bystatus_name, which collapses distinct board-owned statuses that reuse the same label.
- (2026-03-14)
F027: treat billing renewal ticket status persistence the same way as other board-scoped ticket status saves. Rationale: tenant defaults and contract overrides both already persistboard_id + status_id, so the safest implementation is to share the same board/status compatibility guard instead of trusting UI state alone. - (2026-03-14)
F037: onboarding and standard reference-data ticket-status imports should enforce board scope at the action boundary, not just in the onboarding UI. Rationale: the import helper is reused outside onboarding, so board ownership has to be written and validated in the shared importer as well. - (2026-03-14)
F038keepsstandard_statusesunchanged. Rationale: that table is template/reference data, not the livestatusesrows used by ticket runtime validation, so only real seed/fixture writers needed board scoping changes.
Discoveries / Constraints
- (2026-03-14) Current ticket status actions are tenant-global:
packages/reference-data/src/actions/status-actions/statusActions.tspackages/tickets/src/models/status.tsserver/src/app/api/v1/tickets/statuses/route.ts
- (2026-03-14) Board management and ticket status management are currently split across:
server/src/components/settings/general/BoardsSettings.tsxserver/src/components/settings/general/StatusSettings.tsx
- (2026-03-14) Ticket default status helpers currently resolve tenant-wide ticket defaults with no board input:
shared/models/ticketModel.tspackages/client-portal/src/actions/client-portal-actions/client-tickets.ts
- (2026-03-14) Workflow ticket operations and pickers persist raw ticket
status_idvalues and currently validate only against tenant + status id:shared/workflow/runtime/actions/businessOperations/tickets.tsshared/workflow/runtime/actions/registerEmailWorkflowActions.tsserver/src/components/workflow-designer/WorkflowActionInputFixedPicker.tsx
- (2026-03-14) Billing renewal defaults store both board and status ids already, which makes them a good candidate for automatic remap:
packages/billing/src/actions/billingSettingsActions.tspackages/billing/src/actions/renewalsQueueActions.tsserver/src/lib/jobs/handlers/processRenewalQueueHandler.ts
- (2026-03-14) There is no standalone bulk ticket status edit surface in the current ticket dashboard branch; the only ticket bulk action present right now is bulk delete. That means
T032needs either a future implementation surface or a scoped plan update, not a false claim of coverage. - (2026-03-14) There is no repo-backed UI yet that edits
default_billing_settings.renewal_ticket_board_id/renewal_ticket_status_idor the contract-level renewal ticket routing overrides.F027is therefore currently blocked on a missing settings surface, even though the underlying persistence columns and queue/runtime readers exist. - (2026-03-14) Onboarding ticketing had drifted from the current board schema:
configureTicketing(...)still inserted boards using legacyemail/is_activefields, while current board creation in this branch uses the newer board shape and may expose onlyis_inactive.- The onboarding fix now introspects
boardscolumns before insert so board creation works against the current schema while still attaching board-owned statuses immediately afterward.
- (2026-03-14) The earlier
F027blocker was stale on this branch:- tenant billing settings can now host a renewal automation card,
- contract assignment renewal overrides already have an edit surface in
ContractDetail.tsx, - the missing piece was board-scoped status loading and save-time validation.
- (2026-03-14) Dev seed fallout for board-owned ticket statuses was narrower than the initial grep suggested:
- active runtime seeds needed changes in
server/seeds/dev/07_statuses.cjs,server/seeds/dev/14_tickets.cjs,server/seeds/dev/66_asset_tickets.cjs, andserver/seeds/dev/80_default_inbound_ticket_defaults.cjs server/seeds/dev/58_populate_standard_statuses.cjsstayed unchanged because it seeds template/reference rows, not livestatuses
- active runtime seeds needed changes in
- (2026-03-14) Completed
F027by scoping billing renewal ticket statuses to the selected board:packages/billing/src/components/settings/billing/RenewalAutomationSettings.tsxadds a tenant renewal automation card with board-first ticket status selection and clears stale statuses when the board changes.packages/billing/src/actions/billingSettingsActions.tsnow rejects renewal ticket status saves when the status does not belong to the selected board.shared/billingClients/clientContracts.tsnow applies the same guard to contract assignment create/update paths, andpackages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsxexposes board-scoped renewal ticket board/status controls for per-assignment overrides.
- (2026-03-14) Completed
T035with focused billing coverage:packages/billing/tests/RenewalAutomationSettings.boardScopedStatuses.test.tsxverifies tenant billing renewal settings only load statuses for the selected board, disable status selection until a board is chosen, and clear stale status values on board change before save.packages/billing/tests/billingSettingsActions.boardScopedRenewalStatus.test.tsverifies save-time validation rejects a stale cross-board renewal status pair.shared/billingClients/__tests__/clientContracts.boardScopedRenewalStatus.test.tscovers the shared contract-assignment guard so per-contract renewal overrides cannot persist mismatched board/status ids.
- (2026-03-14) SLA, notifications, surveys, and client portal ticket flows all resolve ticket statuses directly by
status_id, so they are migration-sensitive:packages/sla/src/services/slaPauseService.tsserver/src/lib/eventBus/subscribers/internalNotificationSubscriber.tsserver/src/lib/eventBus/subscribers/surveySubscriber.tspackages/client-portal/src/actions/client-portal-actions/client-tickets.ts
- (2026-03-14)
packages/tickets/src/components/ticket/TicketInfo.tsxalready carries pending board/category state locally, soF014could be implemented by clearingpendingChanges.status_idon board change and disabling save until the new board gets a status. - (2026-03-14)
packages/tickets/src/actions/board-actions/boardActions.tscan own status seeding for board create because it already centralizes transactional board creation and ITIL setup. - (2026-03-14) The copy path and inline path can coexist cleanly if copy remains the default
status_seed_mode; that keepsF015green while addingF016without forcing a broader board-edit refactor. - (2026-03-14) Current schema still enforced tenant-global ticket status uniqueness before this batch:
server/migrations/202409101116_add_status_constraints.cjspackages/types/src/interfaces/status.interface.ts
- (2026-03-14) Ticket board-change UX still remains incomplete after the shared update-path validation fix:
shared/models/ticketModel.tspackages/tickets/src/actions/ticketActions.tspackages/tickets/src/actions/optimizedTicketActions.tsserver/src/lib/api/services/TicketService.ts
- (2026-03-14) Board settings and board actions do not yet seed or manage board-local ticket statuses:
packages/tickets/src/actions/board-actions/boardActions.tsserver/src/components/settings/general/BoardsSettings.tsx
- (2026-03-14) Saved config with explicit board context now has a direct migration path:
inbound_ticket_defaults.board_id + status_iddefault_billing_settings.renewal_ticket_board_id + renewal_ticket_status_idclient_contracts.renewal_ticket_board_id + renewal_ticket_status_id
- (2026-03-14) Postgres migration gotcha: in
UPDATE ... FROM, the target table alias cannot be referenced inside the joined tableONclause the way a regular join can. The board-column predicate for the board-context remap migration needs to live in the outerWHEREclause instead. - (2026-03-14)
F009/F010are the first non-tabular migration slice:- workflow ticket board/status references live inside
workflow_definitions.draft_definitionandworkflow_definition_versions.definition_json - ticket board/status values can appear as fixed literals or dynamic
inputMappingexpressions in action configs, so safe remap/surfacing needs JSON traversal and explicit unresolved detection rather than a single SQL join
- workflow ticket board/status references live inside
- (2026-03-14) Completed
F009with a workflow JSON remap migration:server/migrations/20260314130000_remap_workflow_ticket_status_references.cjstraverses workflow v2stepsrecursively and rewrites fixed literalstatus_idvalues only when a fixed literalboard_idis present in the same saved payload.- The remap runs against both
workflow_definitions.draft_definitionandworkflow_definition_versions.definition_json. - Because workflow tables do not carry
tenant, the migration derives the legacy-to-board-owned mapping fromstatusesrows usingtenant + nameand applies it via savedboard_id + status_idpairs.
- (2026-03-14) Completed
T010with DB-backed coverage inserver/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts:- verifies
tickets.create,create_ticket_from_email, and nestedticketDefaults.status_idinsidecreate_ticket_with_initial_commentall remap in both workflow drafts and published versions - reran with
cd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts; the suite now passes with 9 migration tests after the laterT011guard was added
- verifies
- (2026-03-14) Completed
F010with an explicit unresolved-reference guard:server/migrations/20260314133000_surface_unresolved_ticket_status_references.cjsscans workflow drafts and published versions for fixed legacy ticketstatus_idvalues that still lack literal board context.- The guard throws a migration error containing the workflow id, table, step path, action id, and input path so unresolved references are surfaced before release instead of guessed.
- (2026-03-14) Completed
T011inserver/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts:- seeds a workflow
tickets.update_fieldsstep with fixed legacypatch.status_idand no board context - verifies the guard migration rejects with a concrete unresolved-reference message and leaves the stored status id unchanged
- reran with
cd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tsand confirmed all 9 migration tests pass
- seeds a workflow
- (2026-03-14) Completed
F011by making ticket default resolution board-aware in shared ticket creation paths:shared/models/ticketModel.tsnow resolves a default ticket status only for the selectedboard_idand no longer falls back to tenant-global ticket statuses.packages/client-portal/src/actions/client-portal-actions/client-tickets.tsnow asksTicketModel.getDefaultStatusId(...)for the default status tied to the client portal's default board instead of querying tenant-global ticket defaults directly.
- (2026-03-14) Completed
F012by enforcing board/status compatibility on ticket creation:shared/models/ticketModel.tsnow validates that a provided ticketstatus_idbelongs to the selectedboard_idbefore insert.TicketModel.createTicket(...)now auto-fills the selected board's default status when callers omitstatus_id, and rejects create attempts when no board-local default exists.
- (2026-03-14) Completed
T012andT013with shared unit coverage inshared/models/__tests__/ticketModel.boardStatusValidation.test.ts:T012provesgetDefaultStatusIdreturns the selected board's default instead of a legacy tenant-global default.T013proves create-time business rule validation rejects a status from a different board.- verified with
cd shared && npx vitest run models/__tests__/ticketModel.boardStatusValidation.test.ts --config vitest.config.ts.
- (2026-03-14) Completed
T014with DB-backed create-path coverage inserver/src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts:- seeds two boards with distinct board-owned ticket statuses and proves
TicketModel.createTicket(...)inserts only for the matching board/status pair - verifies the cross-board create attempt throws and leaves only the valid ticket row persisted
- verified with
cd server && npx vitest run --coverage.enabled false src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts.
- seeds two boards with distinct board-owned ticket statuses and proves
- (2026-03-14) Completed
F013by enforcing board/status compatibility on ticket update paths:shared/models/ticketModel.tsnow validates update-timestatus_idchanges against the effective board for the ticket.packages/tickets/src/actions/ticketActions.ts,packages/tickets/src/actions/optimizedTicketActions.ts, andserver/src/lib/api/services/TicketService.tsnow all reject cross-board ticket status updates instead of validating ticket statuses at tenant scope only.
- (2026-03-14) Completed
T015inshared/models/__tests__/ticketModel.boardStatusValidation.test.ts:- proves
TicketModel.updateTicket(...)rejects a status-only update when the new status belongs to a different board - verified with
cd shared && npx vitest run models/__tests__/ticketModel.boardStatusValidation.test.ts --config vitest.config.ts.
- proves
- (2026-03-14) Completed
T016with DB-backed update coverage inserver/src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts:- proves
TicketModel.updateTicket(...)rejects a cross-board status id and leaves the persisted ticket's prior status untouched - verified with
cd server && npx vitest run --coverage.enabled false src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts.
- proves
- (2026-03-14) Completed
F017/F018/F021by moving board-local ticket lifecycle editing into board create/edit:server/src/components/settings/general/BoardsSettings.tsxnow manages ticket statuses in both create-inline and edit flows, including add/remove/reorder/open-closed/default operations.- Save is blocked until the managed board-local status set contains exactly one open default, which keeps board create and board edit aligned with the PRD's required lifecycle invariant.
- (2026-03-14) Completed
F019by retiring the old central ticket status settings surface:server/src/components/settings/general/StatusSettings.tsxnow renders an informational handoff to Boards instead of acting as a tenant-global ticket status editor.
- (2026-03-14) Completed
F020with board-scoped ticket status actions and model reads:packages/tickets/src/models/status.tsnow exposes board-scoped ticket status lookup helpers.packages/tickets/src/actions/board-actions/boardTicketStatusActions.tsnow owns board-local ticket status reads plus create/update/delete/save operations, and explicitly rejects implicit cross-board mutation.
- (2026-03-14) Completed
T020/T021/T022/T023/T024/T025/T026with focused UI and action coverage:server/src/components/settings/general/BoardsSettings.copyStatuses.test.tsxnow covers create-time lifecycle validation and board-edit status loading.server/src/components/settings/general/StatusSettings.ticketStatusesRetired.test.tsxverifies the central status surface is informational only.packages/tickets/src/actions/board-actions/boardTicketStatusActions.test.tsverifies board-local create/update/delete/default rules and duplicate-name scoping.
- (2026-03-14) Completed
F022/F023/F024by making ticket status options board-dependent in both create and edit ticket flows:packages/reference-data/src/actions/status-actions/statusActions.tsnow accepts an optionalboardIdfor ticket-status lookups.packages/tickets/src/components/QuickAddTicket.tsxnow leaves status options empty until a board is chosen, then fetches that board's statuses and selects only that board's default.packages/tickets/src/components/ticket/TicketInfo.tsxnow reloads status options from the currently selected board and disables the picker when no board is in scope.
- (2026-03-14) Completed
T027/T028/T029/T030with focused picker coverage:packages/tickets/src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsxnow verifies board-scoped option loading, empty/disabled state with no board, and board-change option reloading.packages/tickets/src/components/__tests__/QuickAddTicket.boardScopedStatuses.test.tsxverifies create flow status pickers stay empty until a board is selected and then choose that board's default.
- (2026-03-14) Completed
F026by making inbound ticket defaults board-scoped for statuses:packages/integrations/src/components/email/forms/InboundTicketDefaultsForm.tsxnow clearsstatus_idwhen the board changes, disables the status picker until a board is chosen, and reloads only that board's statuses viagetAvailableStatuses(boardId).packages/integrations/src/actions/email-actions/ticketFieldOptionsActions.tsnow exposesgetAvailableStatuses(boardId)as a board-filtered ticket-status lookup for inbound-email setup.packages/integrations/src/actions/email-actions/inboundTicketDefaultsActions.tsnow rejects saves wherestatus_iddoes not belong to the selectedboard_id.
- (2026-03-14) Completed
T034inserver/src/test/unit/components/InboundTicketDefaultsForm.test.tsx:- verifies inbound ticket defaults keep the status picker disabled until a board is selected
- verifies the form requests only the selected board's statuses and clears a stale status when the board changes
- reran with
cd server && npx vitest run --coverage.enabled false src/test/unit/components/InboundTicketDefaultsForm.test.tsx --config vitest.config.ts
- (2026-03-14) Completed
F031by scoping client portal ticket status flows to the ticket board:packages/client-portal/src/actions/client-portal-actions/client-tickets.tsnow rejects client-portal status updates when the requestedstatus_iddoes not belong to the ticket'sboard_id.server/src/app/client-portal/tickets/[ticketId]/page.tsxnow preloads only the selected ticket board's statuses for the standalone details page.packages/client-portal/src/components/tickets/TicketList.tsxnow fetches board-owned status menus per ticket board so the list's status-change dropdown stops offering cross-board choices.
- (2026-03-14) Completed
F036/T049/T050by tightening downstream subscriber coverage and remapping saved survey trigger status filters:server/migrations/20260314135000_remap_survey_trigger_ticket_status_references.cjsnow rewrites legacy ticketsurvey_triggers.trigger_conditions.status_idvalues to board-owned ticket status ids using the savedboard_idfilter when present, and deterministically expands across all cloned boards when the trigger was intentionally board-agnostic.server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tsnow covers survey trigger remap persistence for migrated board-specific ticket statuses.server/src/test/integration/internal-notifications/eventSubscribers.integration.test.tsnow proves ticket update notifications still resolve old/new board-owned status names, and its query stub now supports thewhereNotNullcalls used by the subscriber's assignee lookup.
- (2026-03-14) Completed
F037by moving onboarding and standard ticket-status imports to board-owned creation:packages/reference-data/src/actions/referenceDataActions.tsnow requiresboard_idwhen importing ticket statuses, writes it onto imported rows, and scopes duplicate/default/order conflict checks to the target board.packages/onboarding/src/actions/onboarding-actions/onboardingActions.tsnow requires a board before saving onboarding ticket statuses, writes new statuses withboard_id, validates the default status on the default board, returns only the active board's ticket statuses to onboarding state, and creates boards using the current schema columns instead of assuming legacyemail/is_activefields exist.packages/onboarding/src/components/steps/TicketingConfigStep.tsxnow loads standard ticket statuses only when a board is in scope, imports them withboard_id, and uses board-local ticket status actions for manual creation and default changes.
- (2026-03-14) Completed
T051/T052inserver/src/test/integration/onboardingBoardTicketStatuses.integration.test.ts:- proves
configureTicketing(...)creates only board-owned ticket statuses for the onboarding-created board and leaves a valid board-local default status behind - proves
importReferenceData('statuses', ..., { item_type: 'ticket', board_id })writes ticket statuses only to the target board and does not treat the same ticket status name on another board as a conflict - reran with
cd server && npx vitest run --coverage.enabled false src/test/integration/onboardingBoardTicketStatuses.integration.test.ts --config vitest.config.ts
- proves
- (2026-03-14) Completed
F038by moving shared seeds, fixtures, and workflow harness setup to board-owned ticket statuses:server/src/test/e2e/utils/e2eTestSetup.tsandserver/src/test/e2e/fixtures/test-setup.tsnow create a default board before ticket statuses, writeboard_idon seeded ticket statuses, and clean up statuses before boards.server/seeds/dev/07_statuses.cjsnow clones the seeded ticket lifecycle onto every seeded board instead of inserting one tenant-global ticket status list.server/seeds/dev/14_tickets.cjs,server/seeds/dev/66_asset_tickets.cjs, andserver/seeds/dev/80_default_inbound_ticket_defaults.cjsnow resolve ticket statuses from the relevant board.ee/test-data/workflow-harness/_lib/biz-fixture.cjsplus the inline ticket workflow fixtures now select ticket statuses bytenant + board_id.
- (2026-03-14) Completed
T053inserver/src/test/e2e/utils/utilities.test.ts:- verifies the shared e2e environment creates ticket statuses only on the default board and still preserves a valid default status
- reran with
cd server && npx vitest run --coverage.enabled false src/test/e2e/utils/utilities.test.ts -t "T053" --config vitest.config.ts
- (2026-03-14) Completed
T054inserver/src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.ts:- verifies the workflow smoke fixture resolves a ticket status from the seeded board-owned status set
- reran with
cd server && npx vitest run --coverage.enabled false src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.ts -t "T054" --config vitest.config.ts
- (2026-03-14) Completed
F039as a plan close-out because the existing migration DB integration suite already covers both required cases:server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tsalready contains the multi-board clone/remap happy path (T003) and the unresolved no-board-context guard (T011)T055/T056therefore map to existing coverage rather than requiring a new migration suite
- (2026-03-14) Completed
T055/T056by revalidating the existing migration integration suite:- reran the targeted happy-path and guard cases in
server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts - confirmed the suite already proves both clone/remap correctness and explicit unresolved-reference surfacing
- reran the targeted happy-path and guard cases in
- (2026-03-14) Completed
F040as a plan close-out because the existing UI/component coverage already exercises the required board-local status management and board-change reselection behavior:server/src/components/settings/general/BoardsSettings.copyStatuses.test.tsxcovers board create/edit lifecycle rules and board-local status editingpackages/tickets/src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsxcovers explicit status reselection after a board change
- (2026-03-14) Completed
F041as a plan close-out because the existing migration, billing, and workflow suites already prove remapped saved configuration still resolves under board-owned statuses:server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tscovers billing and workflow remap persistence (T008/T009/T010/T011)shared/workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.tsandpackages/billing/tests/*.boardScoped*cover runtime/use-site validation after remap
- (2026-03-14) Completed
F042as a plan close-out because the existing API and client portal suites already cover the board-scoped lookup and validation regressions:server/src/test/unit/api/ticketStatusesRoute.boardScope.test.tsandserver/src/test/unit/api/statusService.ticketBoardScope.test.tscover API board scopepackages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.tscovers client portal create/update validation
- (2026-03-14) Completed
F043as a no-op scope close-out because this branch does not currently contain a ticket bulk-update surface:packages/tickets/src/components/TicketingDashboard.tsxonly exposes bulk delete for ticketsserver/src/test/e2e/api/tickets.e2e.test.tsstill treats/api/v1/tickets/bulk-updateas optional and accepts404/405, which confirms there is no shipped bulk ticket status edit path to harden in this branch
- (2026-03-14) Completed
F044by scoping the remaining auxiliary ticket creation helper to board-owned ticket statuses:packages/assets/src/components/CreateTicketFromAssetButton.tsxnow loads ticket statuses only for the active board, clears stalestatus_idvalues as soon as the board changes, and disables the status picker when no board is in scope.- Project-linked ticket creation did not need new changes because
packages/projects/src/components/TaskTicketLinks.tsxalready routes through the board-scopedQuickAddTicketflow.
- (2026-03-14) Completed
T033inpackages/assets/src/components/CreateTicketFromAssetButton.boardScopedStatuses.test.tsx:- verifies the asset ticket dialog loads statuses with
getTicketStatuses(boardId)instead of a tenant-global lookup - verifies changing boards swaps the available status options and submit persists only the destination board's status id
- reran with
cd packages/assets && npx vitest run src/components/CreateTicketFromAssetButton.boardScopedStatuses.test.tsx --config vitest.config.ts
- verifies the asset ticket dialog loads statuses with
- (2026-03-14) Completed
T032as a no-op scope close-out because there is no ticket bulk-update flow in this branch:packages/tickets/src/components/TicketingDashboard.tsxexposes only bulk deleteserver/src/test/e2e/api/tickets.e2e.test.tsstill treats/api/v1/tickets/bulk-updateas optional and accepts404/405
- (2026-03-14) Completed
T057/T058via equivalent UI/component coverage already present in the branch:server/src/components/settings/general/BoardsSettings.copyStatuses.test.tsxverifies board create with copied statuses, inline statuses, and board-local status editingpackages/tickets/src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsxverifies explicit status reselection after a board change
- (2026-03-14) Completed
T059via the existing workflow remap and runtime regression suites:server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tsproves migrated saved workflow status references are remapped onto board-owned status idsshared/workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.tsandserver/src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.tscover execution against board-owned ticket statuses after remap
- (2026-03-14) Completed
T060via the existing billing remap and renewal routing regression suites:server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tsproves tenant and contract renewal defaults remap to board-owned ticket status idspackages/billing/tests/RenewalAutomationSettings.boardScopedStatuses.test.tsx,packages/billing/tests/billingSettingsActions.boardScopedRenewalStatus.test.ts,shared/billingClients/__tests__/clientContracts.boardScopedRenewalStatus.test.ts, andserver/src/lib/jobs/tests/renewalQueueScheduling.wiring.test.tstogether prove renewal ticket routing keeps using the intended board-owned board/status pair
- (2026-03-14) Completed
T061/T062via the existing API/service and client portal regression suites:server/src/test/integration/ticketCreateBoardStatusValidation.integration.test.tsproves valid board-owned create/update pairs succeed and cross-board pairs fail without persistingserver/src/test/unit/api/ticketStatusesRoute.boardScope.test.ts,server/src/test/unit/api/statusService.ticketBoardScope.test.ts, andpackages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.tscover the board-scoped lookup and client portal validation paths
- (2026-03-14) Completed
T041/T042inpackages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.ts:- verifies client portal ticket creation resolves the default status from the default board before creating the ticket
- verifies client portal status updates reject a status from another board and skip the write/event path
- reran with
cd server && npx vitest run --coverage.enabled false ../packages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.ts --config vitest.config.ts
- (2026-03-14) Completed
F035for SLA pause config and reporting compatibility with board-owned ticket statuses:server/migrations/20260314134000_remap_sla_pause_ticket_status_configs.cjsclones legacystatus_sla_pause_configrows onto each board-owned clone of the matching ticket status name, then deletes the legacy global ticket-status configs.packages/sla/src/actions/slaPauseConfigActions.tsnow filters pause configs to board-owned ticket statuses, rejects writes against legacy/global ticket status ids, and exposes board-qualified ticket status options for the SLA settings UI.packages/sla/src/components/SlaPauseSettings.tsxnow loads board-owned ticket statuses directly from SLA actions and renders duplicate status names with board context so pause rules stay unambiguous across boards.- SLA integration fixtures now seed board-owned ticket statuses in
server/src/test/integration/sla/slaPauseService.integration.test.tsandserver/src/test/integration/sla/slaReportingService.integration.test.ts, and the reporting suite now includes a same-name cross-board closed/open regression case.
- (2026-03-14) Completed
T047/T048with focused SLA coverage:server/src/test/unit/components/SlaPauseSettings.boardOwnedStatuses.test.tsxverifies the SLA pause settings UI shows duplicate ticket status names with board labels and saves only the changed board-ownedstatus_id.server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.tsnow verifies the SLA pause config migration remaps a legacy ticket status rule onto every board-owned clone.server/src/test/unit/migrations/boardSpecificTicketStatusesMigration.test.tsasserts the SLA pause config remap migration exists and keeps the legacy/global cleanup logic in place.server/src/test/integration/sla/slaPauseConfigActions.integration.test.tsadds regression assertions for rejecting legacy/global ticket status ids and hiding legacy configs from the returned board-owned config list, and the same suite also covers same-name cross-board pause evaluation via distinct board-ownedstatus_idvalues.- DB-backed SLA integration suites are still locally blocked in this shell because the server test database port (
127.0.0.1:5438/::1:5438) is not reachable and fails withEPERM, so only the unit/component coverage above was rerun here.
- (2026-03-14) Completed
F028by making workflow ticket status authoring board-aware:shared/workflow/runtime/actions/businessOperations/tickets.tsnow declaresticket-statuspicker dependencies onboard_idfortickets.createandticket_idfortickets.update_fields.ee/server/src/components/workflow-designer/WorkflowActionInputFixedPicker.tsxnow resolvesticket-statusoptions from the selected fixed board or from the fixed ticket's board instead of using tenant-global ticket statuses.ee/server/vitest.config.tsnow aliases@alga-psa/tickets/*so the EE workflow-designer tests can import ticket actions directly.
- (2026-03-14) Completed
T036with workflow authoring coverage:shared/workflow/runtime/actions/__tests__/registerTicketActionPickerMetadata.test.tsverifies the real action schemas now export board/ticket dependencies for ticket status pickers.ee/server/src/components/workflow-designer/__tests__/InputMappingEditorPickerFields.test.tsxverifies fixed ticket-status pickers load only the selected board's statuses and can derive board context from a fixedticket_id.- reran with
cd shared && npx vitest run workflow/runtime/actions/__tests__/registerTicketActionPickerMetadata.test.ts --config vitest.config.ts - reran with
cd ee/server && npx vitest run --coverage.enabled false src/components/workflow-designer/__tests__/InputMappingEditorPickerFields.test.tsx --config vitest.config.ts
- (2026-03-14) Completed
F029/F030in workflow runtime:shared/workflow/runtime/actions/businessOperations/tickets.tsnow treatstickets.create.status_idas optional so workflow runs can rely on board-local default status resolution.tickets.createandtickets.update_fieldsnow rejectstatus_idvalues that do not belong to the effective board before calling shared ticket writes.tickets.closenow picks the terminal closed status from the ticket's own board, and closure timestamps usectx.nowIso()for deterministic runtime behavior.
- (2026-03-14) Completed
T037/T038/T039/T040inshared/workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.ts:- proves workflow create rejects a status from another board
- proves workflow update rejects a cross-board status patch for the current ticket board
- proves workflow close resolves a closed status from the ticket's board even when another board has a lower-order closed status
- proves workflow create returns the selected board's default status when
status_idis omitted - reran with
cd shared && npx vitest run workflow/runtime/actions/__tests__/registerTicketActionPickerMetadata.test.ts workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.ts --config vitest.config.ts
- (2026-03-14) Completed
F032by making the ticket statuses API board-aware:server/src/app/api/v1/tickets/statuses/route.tsnow filters tostatus_type='ticket', excludes legacy board-less ticket statuses, and honors optionalboard_idscope.
- (2026-03-14) Completed
F033by removing tenant-global ticket behavior from generic status surfaces:server/src/lib/api/schemas/status.tsnow requiresboard_idwhen queryingtype=ticket.server/src/lib/api/services/StatusService.tsnow filters generic ticket status lists byboard_id, excludes board-less ticket rows, and hides legacy board-less ticket statuses ingetById.packages/reference-data/src/actions/status-actions/statusActions.tsnow filtersgetStatuses('ticket')to board-owned rows and rejects generic ticket status create/update/delete in favor of board settings.
- (2026-03-14) Completed
T043/T044with in-process API contract coverage:server/src/test/unit/api/ticketStatusesRoute.boardScope.test.tsverifies/api/v1/tickets/statuseshonorsboard_idand excludes legacy board-less ticket statuses.server/src/test/unit/api/statusService.ticketBoardScope.test.tsverifies generic ticket status queries require board scope, list only board-owned ticket statuses, and hide legacy global ticket statuses by id.- reran with
cd server && npx vitest run --coverage.enabled false src/test/unit/api/ticketStatusesRoute.boardScope.test.ts src/test/unit/api/statusService.ticketBoardScope.test.ts --config vitest.config.ts
- (2026-03-14) Completed
F034by aligning ticket list/search/reporting read surfaces with board-owned ticket statuses:server/src/lib/api/services/TicketService.tssearch results now projectstatus_nameandstatus_is_closedfrom the joined board-owned status row.TicketService.getTicketStats(...)now groups status counts bystatus_idinstead of only bystatus_name, preventing cross-board count collapse when boards reuse the same label.
- (2026-03-14) Completed
T045/T046inserver/src/test/integration/ticketStatusReadSurfaces.integration.test.ts:- proves ticket list and search joins return the correct status metadata for tickets on different boards that reuse the same status name
- proves grouped ticket stats keep counts separated by board-owned
status_idinstead of collapsing same-name statuses across boards - reran with
cd server && npx vitest run --coverage.enabled false src/test/integration/ticketStatusReadSurfaces.integration.test.ts --config vitest.config.ts
Commands / Runbooks
- (2026-03-14) Audit ticket status references:
rg -n "status_id|statusIds|ticket-status|renewal_ticket_status_id|inbound.*status_id" server shared ee packages -g '!**/node_modules/**'
- (2026-03-14) Inspect current board + ticket status settings surfaces:
sed -n '1,260p' server/src/components/settings/general/BoardsSettings.tsxsed -n '1,260p' server/src/components/settings/general/StatusSettings.tsx
- (2026-03-14) Inspect current status actions and APIs:
sed -n '1,260p' packages/reference-data/src/actions/status-actions/statusActions.tssed -n '1,220p' server/src/app/api/v1/tickets/statuses/route.tssed -n '1,240p' server/src/app/api/v1/statuses/route.ts
- (2026-03-14) Inspect ticket default resolution:
sed -n '1165,1260p' shared/models/ticketModel.ts
- (2026-03-14) Validate plan artifacts:
python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/validate_plan.py ee/docs/plans/2026-03-14-board-specific-ticket-statuses
- (2026-03-14) Validate board-change status reselection:
cd packages/tickets && npx vitest run src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsx --config vitest.config.tscd shared && npx vitest run models/__tests__/ticketModel.boardStatusValidation.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts --config vitest.config.ts
- (2026-03-14) Validate board status copy-on-create:
cd server && npx vitest run --coverage.enabled false src/components/settings/general/BoardsSettings.copyStatuses.test.tsx --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/boardCopyTicketStatuses.integration.test.ts --config vitest.config.ts
- (2026-03-14) Validate inline board status authoring:
cd server && npx vitest run --coverage.enabled false src/components/settings/general/BoardsSettings.copyStatuses.test.tsx --config vitest.config.ts
- (2026-03-14) Run the board-status migration schema tests directly from the server package:
cd server && npx vitest run src/test/unit/migrations/boardSpecificTicketStatusesMigration.test.ts
- (2026-03-14) Repo-level
npm run test:local -- ...is currently not usable in this shell because the installeddotenvCLI rejects-e ../.env.localtestas non-boolean. - (2026-03-14) Attempt the DB-backed clone/remap migration suite:
cd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts
- (2026-03-14) Attempt the board-context status-reference remap suite:
cd server && npx vitest run src/test/integration/boardContextTicketStatusReferenceRemap.integration.test.ts --coverage=false- Run it after the clone/remap suite or against a schema that already includes
20260314113000_clone_global_ticket_statuses_to_boards.cjs.
- (2026-03-14) Run the shared board-status helper tests:
cd shared && npx vitest run models/__tests__/ticketModel.boardStatusValidation.test.ts --config vitest.config.ts
- (2026-03-14) Run the DB-backed ticket create board/status validation test:
cd server && npx vitest run --coverage.enabled false src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts
- (2026-03-14) Validate board-local ticket status management and the retired central status surface:
cd packages/tickets && npx vitest run src/actions/board-actions/boardTicketStatusActions.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/components/settings/general/BoardsSettings.copyStatuses.test.tsx src/components/settings/general/StatusSettings.ticketStatusesRetired.test.tsx --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/boardCopyTicketStatuses.integration.test.ts --config vitest.config.ts
- (2026-03-14) Validate board-dependent ticket status pickers:
cd packages/tickets && npx vitest run src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsx src/components/__tests__/QuickAddTicket.boardScopedStatuses.test.tsx --config vitest.config.ts
- (2026-03-14) Validate inbound ticket defaults board-scoped statuses:
cd server && npx vitest run --coverage.enabled false src/test/unit/components/InboundTicketDefaultsForm.test.tsx --config vitest.config.ts
- (2026-03-14) Validate client portal board-scoped status flows:
cd server && npx vitest run --coverage.enabled false ../packages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.ts --config vitest.config.ts
- (2026-03-14) Validate onboarding board-owned ticket statuses:
cd server && npx vitest run --coverage.enabled false src/test/integration/onboardingBoardTicketStatuses.integration.test.ts --config vitest.config.ts
- (2026-03-14) Validate seed/fixture board-owned ticket status setup:
cd server && npx vitest run --coverage.enabled false src/test/e2e/utils/utilities.test.ts -t "T053" --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.ts -t "T054" --config vitest.config.ts
- (2026-03-14) Revalidate the existing migration integration coverage used to close
F039:cd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts -t "T003" --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts -t "T011" --config vitest.config.ts
- (2026-03-14) Revalidate the existing UI/API coverage used to close
F040/F042:cd server && npx vitest run --coverage.enabled false src/components/settings/general/BoardsSettings.copyStatuses.test.tsx --config vitest.config.tscd packages/tickets && npx vitest run src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsx --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/unit/api/ticketStatusesRoute.boardScope.test.ts src/test/unit/api/statusService.ticketBoardScope.test.ts ../packages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.ts --config vitest.config.ts
- (2026-03-14) Revalidate the existing workflow/billing coverage used to close
F041:cd shared && npx vitest run workflow/runtime/actions/__tests__/registerTicketActionPickerMetadata.test.ts workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false ../packages/billing/tests/billingSettingsActions.boardScopedRenewalStatus.test.ts ../packages/billing/tests/RenewalAutomationSettings.boardScopedStatuses.test.tsx ../packages/billing/tests/ContractDetail.assignmentRenewalSettings.wiring.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts --config vitest.config.ts
- (2026-03-14) Verify whether a ticket bulk-update surface exists before implementing
F043:rg -n "bulk[-_ ]update|bulk update|bulkUpdate|bulk_update|/bulk-update|Bulk" packages/tickets server shared ee -g '!**/node_modules/**'sed -n '1,260p' packages/tickets/src/components/TicketingDashboard.tsxsed -n '850,905p' server/src/test/e2e/api/tickets.e2e.test.ts
- (2026-03-14) Validate asset-linked ticket creation board-scoped statuses:
cd packages/assets && npx vitest run src/components/CreateTicketFromAssetButton.boardScopedStatuses.test.tsx --config vitest.config.tscd packages/assets && npx vitest run --config vitest.config.ts- The package-wide assets run still trips the pre-existing contract failure in
src/components/QuickAddAsset.quick-add-client.contract.test.ts(open={isQuickAddClientOpen}no longer matches the current quick-add client API shape); the new board-scoped asset ticket test itself passes.
- (2026-03-14) Revalidate the remaining test checklist close-outs:
cd server && npx vitest run --coverage.enabled false src/lib/jobs/tests/renewalQueueScheduling.wiring.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts --config vitest.config.ts
- (2026-03-14) Validate SLA board-owned pause config and migration coverage:
cd server && npx vitest run --coverage.enabled false src/test/unit/components/SlaPauseSettings.boardOwnedStatuses.test.tsx src/test/unit/migrations/boardSpecificTicketStatusesMigration.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/sla/slaPauseService.integration.test.ts src/test/integration/sla/slaReportingService.integration.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/sla/slaPauseConfigActions.integration.test.ts --config vitest.config.ts- In this shell, the broader SLA DB suites are not currently reliable:
slaPauseService.integration.test.ts/slaReportingService.integration.test.tstripped shared DB bootstrap issues (duplicate key value violates unique constraint "pg_database_datname_index"andROLLBACK - Connection terminated unexpectedly), andslaPauseConfigActions.integration.test.tsstill expects aserverdatabase plus olderpriorities.priority_orderfixture columns.
- (2026-03-14) Validate workflow ticket status authoring + runtime:
cd shared && npx vitest run workflow/runtime/actions/__tests__/registerTicketActionPickerMetadata.test.ts workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.ts --config vitest.config.tscd ee/server && npx vitest run --coverage.enabled false src/components/workflow-designer/__tests__/InputMappingEditorPickerFields.test.tsx --config vitest.config.ts
- (2026-03-14) Validate API ticket status board scope in-process:
cd server && npx vitest run --coverage.enabled false src/test/unit/api/ticketStatusesRoute.boardScope.test.ts src/test/unit/api/statusService.ticketBoardScope.test.ts --config vitest.config.ts
- (2026-03-14) Validate ticket read/reporting status joins:
cd server && npx vitest run --coverage.enabled false src/test/integration/ticketStatusReadSurfaces.integration.test.ts --config vitest.config.ts
- (2026-03-14) Validate subscriber and survey remap regressions:
cd server && npx vitest run --coverage.enabled false src/test/integration/internal-notifications/eventSubscribers.integration.test.ts -t "creates status change notifications for ticket updated events" --config vitest.config.tscd server && npx vitest run --coverage.enabled false src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts --config vitest.config.ts
- (2026-03-14) API e2e harness note:
cd server && npx vitest run --coverage.enabled false src/test/e2e/api/ticket-statuses.e2e.test.ts src/test/e2e/api/statuses.e2e.test.ts --config vitest.config.ts- In this shell the e2e setup can seed the DB, but the HTTP assertions fail with
fetch failedbecause no server is listening onTEST_API_BASE_URL/http://127.0.0.1:3000.
- (2026-03-14) Validate billing renewal defaults board-scoped statuses:
cd shared && npx vitest run billingClients/__tests__/clientContracts.boardScopedRenewalStatus.test.ts --config vitest.config.tscd server && npx vitest run --coverage.enabled false ../packages/billing/tests/billingSettingsActions.boardScopedRenewalStatus.test.ts ../packages/billing/tests/RenewalAutomationSettings.boardScopedStatuses.test.tsx ../packages/billing/tests/ContractDetail.assignmentRenewalSettings.wiring.test.ts --config vitest.config.ts
- (2026-03-14) Legacy Quick Add regression note:
cd packages/tickets && npx vitest run src/components/__tests__/ticket-inline-add-prefill.test.tsx --config vitest.config.ts- Current failures in that broader suite are mock-assumption mismatches around board-first status loading and unrelated quick-add helper behavior; they are not yet curated as plan items in this pass.
Links / References
- Design summary:
ee/docs/plans/2026-03-14-board-specific-ticket-statuses-design.md - Plan folder:
ee/docs/plans/2026-03-14-board-specific-ticket-statuses - Board settings UI:
server/src/components/settings/general/BoardsSettings.tsx - Central ticket status settings UI:
server/src/components/settings/general/StatusSettings.tsx - Ticket status actions:
packages/reference-data/src/actions/status-actions/statusActions.ts - Ticket status model:
packages/tickets/src/models/status.ts - Board actions:
packages/tickets/src/actions/board-actions/boardActions.ts - Board create copy-source test:
server/src/components/settings/general/BoardsSettings.copyStatuses.test.tsx - Board status copy integration:
server/src/test/integration/boardCopyTicketStatuses.integration.test.ts - Board create inline statuses wiring:
server/src/components/settings/general/BoardsSettings.tsx - Board-local ticket status action layer:
packages/tickets/src/actions/board-actions/boardTicketStatusActions.ts - Board-local ticket status action tests:
packages/tickets/src/actions/board-actions/boardTicketStatusActions.test.ts - Retired central ticket status surface:
server/src/components/settings/general/StatusSettings.tsx - Retired central ticket status test:
server/src/components/settings/general/StatusSettings.ticketStatusesRetired.test.tsx - Board-scoped status action lookup:
packages/reference-data/src/actions/status-actions/statusActions.ts - Quick Add board-scoped status test:
packages/tickets/src/components/__tests__/QuickAddTicket.boardScopedStatuses.test.tsx - Ticket edit board-scoped status test:
packages/tickets/src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsx - Ticket model default status helper:
shared/models/ticketModel.ts - Ticket create board/status validation integration:
server/src/test/integration/ticketCreateBoardStatusValidation.integration.test.ts - Ticket API service:
server/src/lib/api/services/TicketService.ts - Ticket edit UI:
packages/tickets/src/components/ticket/TicketInfo.tsx - Ticket edit reselection test:
packages/tickets/src/components/ticket/__tests__/TicketInfo.boardChangeStatusReselection.test.tsx - Ticket statuses API route:
server/src/app/api/v1/tickets/statuses/route.ts - Workflow ticket actions:
shared/workflow/runtime/actions/businessOperations/tickets.ts - Billing renewal defaults:
packages/billing/src/actions/billingSettingsActions.ts - Inbound ticket defaults form:
packages/integrations/src/components/email/forms/InboundTicketDefaultsForm.tsx - Inbound ticket defaults actions:
packages/integrations/src/actions/email-actions/inboundTicketDefaultsActions.ts - Inbound ticket field options actions:
packages/integrations/src/actions/email-actions/ticketFieldOptionsActions.ts - Inbound ticket defaults test:
server/src/test/unit/components/InboundTicketDefaultsForm.test.tsx - Client portal ticket actions:
packages/client-portal/src/actions/client-portal-actions/client-tickets.ts - Client portal board status validation test:
packages/client-portal/src/actions/client-portal-actions/client-tickets.boardStatusValidation.test.ts - Client portal ticket list UI:
packages/client-portal/src/components/tickets/TicketList.tsx - Client portal ticket details page:
server/src/app/client-portal/tickets/[ticketId]/page.tsx - Onboarding ticketing actions:
packages/onboarding/src/actions/onboarding-actions/onboardingActions.ts - Onboarding ticketing step UI:
packages/onboarding/src/components/steps/TicketingConfigStep.tsx - Seeded board-owned ticket statuses:
server/seeds/dev/07_statuses.cjs - Seeded ticket rows with board-owned statuses:
server/seeds/dev/14_tickets.cjs - Seeded asset-linked ticket rows:
server/seeds/dev/66_asset_tickets.cjs - Seeded inbound defaults with board-owned statuses:
server/seeds/dev/80_default_inbound_ticket_defaults.cjs - Shared e2e setup:
server/src/test/e2e/utils/e2eTestSetup.ts - Simplified e2e fixture setup:
server/src/test/e2e/fixtures/test-setup.ts - Workflow harness ticket fixture helper:
ee/test-data/workflow-harness/_lib/biz-fixture.cjs - Seed/fixture board-owned status test:
server/src/test/e2e/utils/utilities.test.ts - Workflow smoke board-owned status test:
server/src/test/integration/workflowWorkerV2.inboundEmailSmoke.integration.test.ts - Reference-data ticket import actions:
packages/reference-data/src/actions/referenceDataActions.ts - Onboarding board-owned status integration test:
server/src/test/integration/onboardingBoardTicketStatuses.integration.test.ts - Workflow ticket action definitions:
shared/workflow/runtime/actions/businessOperations/tickets.ts - Workflow ticket picker test:
shared/workflow/runtime/actions/__tests__/ticketWorkflowBoardStatusRuntime.test.ts - Workflow designer fixed picker:
ee/server/src/components/workflow-designer/WorkflowActionInputFixedPicker.tsx - Ticket statuses API route:
server/src/app/api/v1/tickets/statuses/route.ts - Generic status API service:
server/src/lib/api/services/StatusService.ts - Generic status query schema:
server/src/lib/api/schemas/status.ts - Ticket statuses route unit test:
server/src/test/unit/api/ticketStatusesRoute.boardScope.test.ts - Generic status API unit test:
server/src/test/unit/api/statusService.ticketBoardScope.test.ts - Ticket read/reporting regression test:
server/src/test/integration/ticketStatusReadSurfaces.integration.test.ts - Billing renewal automation settings UI:
packages/billing/src/components/settings/billing/RenewalAutomationSettings.tsx - Billing renewal settings action validation:
packages/billing/src/actions/billingSettingsActions.ts - Contract renewal assignment guard:
shared/billingClients/clientContracts.ts - Contract renewal assignment edit UI:
packages/billing/src/components/billing-dashboard/contracts/ContractDetail.tsx - Billing renewal UI test:
packages/billing/tests/RenewalAutomationSettings.boardScopedStatuses.test.tsx - Billing renewal action test:
packages/billing/tests/billingSettingsActions.boardScopedRenewalStatus.test.ts - Shared contract renewal validation test:
shared/billingClients/__tests__/clientContracts.boardScopedRenewalStatus.test.ts - Asset-linked ticket creation helper:
packages/assets/src/components/CreateTicketFromAssetButton.tsx - Asset-linked ticket board scope regression test:
packages/assets/src/components/CreateTicketFromAssetButton.boardScopedStatuses.test.tsx - New status schema migration:
server/migrations/20260314100000_add_board_ownership_to_ticket_statuses.cjs - Migration schema coverage:
server/src/test/unit/migrations/boardSpecificTicketStatusesMigration.test.ts - Clone/remap migration:
server/migrations/20260314113000_clone_global_ticket_statuses_to_boards.cjs - Clone/remap DB integration coverage:
server/src/test/integration/boardSpecificTicketStatusesMigration.integration.test.ts - Board-context status-reference remap migration:
server/migrations/20260314120000_remap_board_context_ticket_status_references.cjs - Board-context status-reference integration coverage:
server/src/test/integration/boardContextTicketStatusReferenceRemap.integration.test.ts - Workflow status-reference remap migration:
server/migrations/20260314130000_remap_workflow_ticket_status_references.cjs - Workflow unresolved-reference guard migration:
server/migrations/20260314133000_surface_unresolved_ticket_status_references.cjs - Survey trigger status-reference remap migration:
server/migrations/20260314135000_remap_survey_trigger_ticket_status_references.cjs
Open Questions
- (2026-03-14) Which persisted ticket-status references do not currently carry enough board context for a guaranteed automatic remap?