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
6.2 KiB
6.2 KiB
PRD — Ticket Watch Lists and CC-Style Notifications
- Slug:
ticket-watch-lists - Date:
2026-02-25 - Status: Draft
Summary
Add a ticket-level Watch List so teams can include additional recipients (including technicians) on customer-visible ticket notifications. Watchers are managed on the ticket, auto-populated from inbound email To/CC, and notified via separate individual emails (not CC headers).
Problem
Current ticket notification behavior primarily targets the ticket contact/client plus internal assignment/resource recipients. Customers and internal stakeholders often need extra ad-hoc visibility for a specific ticket thread. Without a Watch List:
- Teams manually forward updates.
- Inbound email context (
To/CC) is lost after ingestion. - Visibility is inconsistent across customer-visible ticket updates.
Goals
- Provide a per-ticket Watch List that can include any email address (techs included).
- Auto-add inbound email
To/CCrecipients to Watch List during ingestion. - Let users uncheck/remove Watch List recipients from the ticket UI.
- Send Watch List notifications only for customer-visible ticket updates.
- Send Watch List recipients as separate individual emails.
Non-goals
- Global watcher templates/distribution lists across all tickets.
- Changing existing notification preference architecture for non-watch-list recipients.
- Replacing core recipient logic (contact/client/assigned/resource); Watch List is additive.
- Introducing SMS/push channels.
Users and Primary Flows
- Dispatcher / coordinator:
- Adds or removes watcher emails on a ticket.
- Expects watchers to receive customer-visible updates going forward.
- Technician / internal stakeholder:
- Can be added as watcher by email.
- Receives same customer-visible updates as other watchers.
- Inbound email flow:
- Incoming message creates/replies on a ticket.
- Recipients in
To/CCare merged into ticket Watch List automatically.
UX / UI Notes
- Add a
Watch Listsection on ticket details (properties panel). - UI elements:
- Email input +
Addaction. - List of watcher entries with checkbox (
active) and remove action.
- Email input +
- Checkbox behavior:
- Checked: watcher receives notifications.
- Unchecked: watcher remains listed but inactive (no notifications).
- Clarified customer choice: notifications to watchers are separate individual sends, not a single email with CC recipients.
Requirements
Functional Requirements
- FR-01: Ticket attributes include a Watch List array of recipients with at least email + active state.
- FR-02: Manual add validates/normalizes email and prevents duplicate active entries by normalized email.
- FR-03: Manual remove deletes the watcher entry from the ticket.
- FR-04: Manual uncheck toggles watcher to inactive without deleting required history fields.
- FR-05: Inbound email ingestion collects
To+CCrecipients and merges them into Watch List. - FR-06: Inbound merge excludes sender and provider mailbox address to avoid self-watch loops.
- FR-07: Inbound merge reactivates an existing inactive watcher when that email appears again in
To/CC. - FR-08: Watchers receive notifications for customer-visible ticket events:
- ticket created
- ticket updated
- ticket assigned (customer-visible notification path)
- ticket comment added (public/customer-visible comments only)
- ticket closed
- FR-09: Watcher notifications are sent as individual emails (one watcher per send).
- FR-10: Watcher recipients are deduped against existing recipients per event.
- FR-11: Public comment watcher notifications must not notify the comment author.
- FR-12: Existing recipient behavior (contact/client/assigned/additional resources) remains unchanged except dedupe where applicable.
Non-functional Requirements
- NFR-01: No schema migration required for v1 (use
ticket.attributes.watch_list). - NFR-02: Behavior must be backward-compatible for tickets with null/legacy attributes.
- NFR-03: Errors in watch-list enrichment should not break inbound email ticket/comment creation.
Data / API / Integrations
- Storage target:
tickets.attributes.watch_list(JSON array).
- Suggested entry shape:
email: string(normalized lowercase)active: boolean- optional metadata:
name,source(manual|inbound_to|inbound_cc), timestamps.
- Inbound integration:
shared/services/email/processInboundEmailInApp.tsshared/workflow/actions/emailWorkflowActions.ts
- Outbound integration:
server/src/lib/eventBus/subscribers/ticketEmailSubscriber.ts
- UI integration:
packages/tickets/src/components/ticket/TicketProperties.tsxpackages/tickets/src/components/ticket/TicketDetails.tsx
Security / Permissions
- Watch List edits follow existing ticket update permissions.
- No privileged bypass: only authorized ticket editors can modify watchers.
- Email validation/sanitization required for manual entry and inbound ingestion.
Observability
- Use existing notification logs and email send instrumentation.
- Errors in watcher merge/send should include ticketId/tenantId/recipient context in existing logger paths.
Rollout / Migration
- v1 rollout can be immediate without migration because data is in ticket attributes.
- Existing tickets start with empty Watch List unless updated manually or by inbound email processing.
Open Questions
- Should inactive watchers remain visible indefinitely or be auto-pruned after a period?
- Should Watch List edits themselves generate an audit event/comment in the ticket timeline?
- Should watcher sends respect internal user notification preference toggles when watcher email matches an internal user?
Acceptance Criteria (Definition of Done)
- Users can add, uncheck, and remove watcher emails on a ticket.
- Inbound email processing auto-adds
To/CCrecipients to Watch List, excluding sender/provider mailbox. - Active watchers receive customer-visible ticket updates via separate individual emails.
- Public comment notifications do not email the comment author.
- Duplicate emails are not sent to the same address for a single event.
- Existing non-watcher recipients continue to receive expected notifications.
- Automated tests cover watch-list parsing/merge logic, inbound recipient enrichment, and outbound watcher fan-out per event path.