Shop It Docs
Developer ResourcesSupport

Support Module Backend Documentation

Backend architecture for support inquiries, support requests, feedback, realtime, and maintenance.

Support Module - Backend Documentation

1. Backend Scope and Boundaries

The support backend owns:

  • public/customer support inquiry lifecycle
  • guest inquiry token lifecycle
  • support inquiry message persistence
  • inquiry email capture and verification handoff
  • admin inquiry handling and conversion to support requests
  • authenticated mobile support request lifecycle
  • support request message persistence
  • admin support request handling
  • authenticated mobile feedback submission
  • admin feedback review
  • support websocket room authorization
  • support realtime event publishing and replay
  • scheduled inactive inquiry close

The module does not own:

  • customer account registration
  • customer password/login flows
  • email template rendering internals
  • global websocket connection management
  • generic role/permission storage
  • generic activity log persistence

Those responsibilities are delegated to existing auth, notifications, realtime, permissions, and activity services.

2. Module Composition (Aggregate + Leaf)

SupportModule composes:

  • SupportSharedModule
  • SupportAdminAggregateModule
  • SupportInquiriesCustomerModule

SupportAdminAggregateModule composes:

  • SupportRequestsAdminModule
  • SupportInquiriesAdminModule
  • FeedbackAdminModule

Mobile support surfaces are composed centrally by MobileModule:

  • SupportRequestsMobileModule
  • FeedbackMobileModule

Shared providers:

ProviderResponsibility
SupportRequestDomainServiceshared support request reads, mapping, status update helpers, message author mapping
SupportInquiryDomainServiceinquiry create/read/write/identify/verify/link/close behavior
SupportNotificationServicesupport request notification handoff
SupportRealtimePublisherServicesupport websocket envelope creation and room publishing
SupportRealtimeAccessServicewebsocket room authorization and replay sync access
SupportInquiriesMaintenanceSchedulercron registration for inactive inquiry closing

Admin shared providers:

ProviderResponsibility
SupportAdminSharedServiceadmin lookup, audit context extraction, activity recorder access

3. Data Model (Drizzle / PostgreSQL)

Primary support tables:

  • support_inquiries
  • support_inquiry_messages
  • support_inquiry_tokens
  • support_requests
  • support_request_messages
  • feedback_submissions

Schema source of truth:

  • packages/db/src/schema/support/support-inquiries.ts
  • packages/db/src/schema/support/support-inquiry-messages.ts
  • packages/db/src/schema/support/support-inquiry-tokens.ts
  • packages/db/src/schema/support/support-requests.ts
  • packages/db/src/schema/support/support-request-messages.ts
  • packages/db/src/schema/support/feedback-submissions.ts

Migration source of truth for the new inquiry tables:

  • packages/db/src/migrations/0002_add_support_inquiries.sql

4. Table Details

4.1 support_inquiries

Purpose:

  • stores public/customer inquiry metadata and lifecycle
  • stores public tracking code
  • links optional customer/admin/support request references
  • stores guest contact fields

Important columns:

ColumnTypeNotes
idserial PKinternal database identity
tracking_codevarchar(32), uniquecustomer-safe inquiry reference
customer_iduuid nullable FKlinked customer after auth/verification
guest_namevarchar(255) nullableoptional visitor contact field
guest_emailvarchar(320) nullablenormalized lowercase email
guest_phonevarchar(32) nullableoptional visitor contact field
email_verified_attimestamp nullableset only when guest email verified
categoryvarchar(32)account, payment, technical, product, order, other
subjectvarchar(255)non-blank inquiry subject
statusvarchar(32)open, active, waiting, linked, resolved, closed, spam
assigned_admin_iduuid nullable FKassigned admin user
support_request_idinteger nullable FKlinked support request
last_visitor_message_attimestamp nullablelatest guest/customer message
last_admin_message_attimestamp nullablelatest admin reply
closed_attimestamp nullablerequired for closed and spam
created_attimestampcreation time
updated_attimestampupdated on mutation

Indexes:

  • unique support_inquiries_tracking_code_unique
  • support_inquiries_customer_id_idx
  • support_inquiries_guest_email_idx
  • support_inquiries_status_idx
  • support_inquiries_category_idx
  • support_inquiries_assigned_admin_id_idx
  • support_inquiries_support_request_id_idx
  • support_inquiries_created_at_idx

Check constraints:

  • tracking code must be non-blank
  • subject must be non-blank
  • category must be one of the declared category values
  • status must be one of the declared status values
  • closed_at must match closed/spam state
  • email_verified_at requires guest_email

4.2 support_inquiry_messages

Purpose:

  • stores full inquiry message history
  • supports guest, customer, admin, and system authors

Important columns:

ColumnTypeNotes
idserial PKinternal message identity
support_inquiry_idinteger FK cascadeparent inquiry
author_typevarchar(32)guest, customer, admin, system
author_customer_iduuid nullable FKrequired only for customer author
author_admin_iduuid nullable FKrequired only for admin author
bodytextnon-blank message body
created_attimestampappend time

Indexes:

  • support_inquiry_messages_support_inquiry_id_idx
  • support_inquiry_messages_author_customer_id_idx
  • support_inquiry_messages_author_admin_id_idx
  • support_inquiry_messages_created_at_idx

Check constraints:

  • author type must be valid
  • body must be non-blank
  • author FK consistency is enforced by author type

4.3 support_inquiry_tokens

Purpose:

  • stores hashed guest access tokens for inquiry-specific REST and websocket access

Important columns:

ColumnTypeNotes
idserial PKinternal token identity
support_inquiry_idinteger FK cascadeparent inquiry
token_hashvarchar(64), uniqueSHA-256 hex digest of si_... token
expires_attimestamptoken expiry
revoked_attimestamp nullableexplicit revocation
created_attimestampcreation time

Indexes:

  • support_inquiry_tokens_support_inquiry_id_idx
  • unique support_inquiry_tokens_token_hash_unique
  • support_inquiry_tokens_expires_at_idx

Check constraints:

  • token hash length is exactly 64
  • expires_at must be after created_at

4.4 support_requests

Purpose:

  • stores authenticated customer support tickets
  • existing ticket model used by mobile and admin support request APIs

Important columns:

ColumnTypeNotes
idserial PKinternal ticket identity
customer_iduuid FK cascaderequired customer owner
categoryvarchar(32)account, payment, technical, other
subjectvarchar(255)non-blank ticket subject
statusvarchar(32)open, in_progress, resolved, closed
assigned_admin_iduuid nullable FKassigned admin
resolution_notetext nullableallowed only for resolved/closed
resolved_attimestamp nullablestatus-coupled
closed_attimestamp nullablestatus-coupled
last_customer_message_attimestamp nullablelatest customer message
last_admin_message_attimestamp nullablelatest admin reply
created_attimestampcreation time
updated_attimestampupdated on mutation

Indexes:

  • support_requests_customer_id_idx
  • support_requests_status_idx
  • support_requests_assigned_admin_id_idx
  • support_requests_created_at_idx
  • support_requests_category_idx

4.5 support_request_messages

Purpose:

  • stores full ticket message history
  • supports customer and admin authors

Important columns:

ColumnTypeNotes
idserial PKinternal message identity
support_request_idinteger FK cascadeparent request
author_typevarchar(32)customer or admin
author_customer_iduuid nullable FKrequired for customer author
author_admin_iduuid nullable FKrequired for admin author
bodytextnon-blank message body
created_attimestampappend time

4.6 feedback_submissions

Purpose:

  • stores authenticated mobile feedback for admin review

Important columns:

ColumnTypeNotes
idserial PKinternal feedback identity
customer_iduuid FK cascadesubmitting customer
categoryvarchar(32)bug_report, feature_request, general_feedback
subjectvarchar(255)non-blank subject
messagetextnon-blank feedback message
statusvarchar(32)new, reviewed
reviewed_by_admin_iduuid nullable FKadmin reviewer
reviewed_attimestamp nullablereview time
created_attimestampcreation time
updated_attimestampupdated on mutation

Check constraints enforce valid category/status, non-blank subject/message, and review state consistency.

5. Runtime Rules and Domain Invariants

5.1 Support inquiry creation

Create flow:

  1. Normalize category, subject, message, and guest contact fields.
  2. Generate unique trackingCode.
  3. If authenticated customer exists, set customerId.
  4. If guest, generate si_... token and store SHA-256 hash.
  5. Insert inquiry.
  6. Insert system greeting message.
  7. Insert optional initial guest/customer message when provided.
  8. Return detail response and inquiryAccessToken only for guest-created inquiries.

Transaction boundary:

  • inquiry row
  • token row
  • system greeting message
  • optional initial visitor message

5.2 Inquiry message writes

Visitor messages:

  • accepted from customer JWT or valid guest inquiry token
  • blocked for closed and spam
  • update lastVisitorMessageAt
  • can move status to active depending on current state
  • emit support.inquiry_message.created

Admin messages:

  • require SupportInquiries_UPDATE
  • blocked for closed/spam inquiries
  • update lastAdminMessageAt
  • emit support.inquiry_message.created
  • record admin activity

5.3 Inquiry identification

PATCH /api/support-inquiries/:id/identify updates:

  • guestName
  • guestEmail
  • guestPhone

Email behavior:

  • email is trimmed and lowercased
  • empty values are omitted by DTO transform/validation behavior
  • a stored email does not imply customer identity
  • customer linking requires verification or login

5.4 Inquiry email verification

Request behavior:

  • validates the visitor has access to the inquiry
  • requires guestEmail
  • creates an OTP using verification token infrastructure
  • enqueues email via notifications queue
  • returns a generic response

Confirm behavior:

  • validates OTP
  • sets emailVerifiedAt
  • silently links customerId only when the verified email matches a customer
  • never exposes "email exists" versus "email does not exist"

5.5 Inquiry to support request linking

Admin linking behavior:

  • If supportRequestId is supplied, backend validates target request exists and belongs to the same verified customer.
  • If supportRequestId is omitted, backend creates a new support_request.
  • A new support request can only be created when the inquiry has customerId.
  • Non-system inquiry messages are copied into support_request_messages.
  • Inquiry supportRequestId is set.
  • Inquiry status becomes linked.

Category mapping:

Inquiry categorySupport request category
accountaccount
paymentpayment
technicaltechnical
productother
orderother
otherother

5.6 Support request creation

Mobile support request create flow:

  1. Customer submits category, subject, and initial message.
  2. Backend creates support_request.
  3. Backend creates initial support_request_message.
  4. Response includes request detail and message history.

Support requests always require a customer. They are not guest records.

5.7 Support request replies

Customer replies:

  • require customer JWT and ownership
  • blocked when status is closed
  • reopen resolved requests to open
  • update lastCustomerMessageAt
  • emit support.request_message.created

Admin replies:

  • require SupportRequests_UPDATE
  • blocked when status is closed
  • update lastAdminMessageAt
  • emit support.request_message.created
  • notify customer via SupportNotificationService
  • record admin activity

5.8 Feedback review

Feedback create:

  • requires customer JWT
  • inserts new feedback_submissions row
  • status defaults to new

Feedback review:

  • requires Feedback_UPDATE
  • sets status = reviewed
  • sets reviewedByAdminId
  • sets reviewedAt
  • records admin activity

6. Authentication and Authorization

6.1 REST guards

SurfaceGuards
Public/customer inquiriesSupportInquiryOptionalAuthGuard, selected routes also IpThrottlerGuard
Admin inquiriesJwtAuthGuard, AdminActorGuard, RoleGuard
Mobile support requestsJwtAuthGuard
Admin support requestsJwtAuthGuard, AdminActorGuard, RoleGuard
Mobile feedbackJwtAuthGuard
Admin feedbackJwtAuthGuard, AdminActorGuard, RoleGuard

6.2 Permissions

Permission modules:

  • SupportInquiries
  • SupportRequests
  • Feedback

Permission codes:

  • SupportInquiries_READ
  • SupportInquiries_UPDATE
  • SupportRequests_READ
  • SupportRequests_UPDATE
  • Feedback_READ
  • Feedback_UPDATE

6.3 Websocket authorization

The realtime auth guard supports:

  • admin JWT
  • customer JWT
  • guest inquiry token (si_...)

Room access rules:

RoomAdminCustomerGuest
Support request messagesAny request with permissionOwn customer request onlyNot allowed
Support inquiry messagesAny inquiry with permissionOwn linked inquiry onlyInquiry matching valid token only

7. Realtime Architecture

Support realtime is built on the shared RealtimeGateway.

Support contracts live in:

  • apps/api/src/modules/support/realtime/contracts/support-realtime.contract.ts

Support services:

  • SupportRealtimePublisherService
  • SupportRealtimeAccessService

Room names:

  • support:request:{supportRequestId}:messages
  • support:inquiry:{supportInquiryId}:messages

Client events:

  • support:join_request_messages
  • support:leave_request_messages
  • support:sync_request_messages
  • support:join_inquiry_messages
  • support:leave_inquiry_messages
  • support:sync_inquiry_messages

Server event types:

  • support.request_message.created
  • support.inquiry_message.created

Event envelope:

interface SupportRealtimeEnvelope<TData> {
  eventId: string;
  eventType: "support.request_message.created" | "support.inquiry_message.created";
  occurredAt: string;
  data: TData;
}

Event IDs use UUIDv7, which preserves ordering properties for replay and follows the cross-system ID policy.

8. Maintenance Scheduler

Scheduler source:

  • apps/api/src/modules/support/shared/schedulers/support-inquiries-maintenance.scheduler.ts

Runtime config:

VariableDefaultDescription
SUPPORT_INQUIRIES_INACTIVE_CLOSE_CRON0 * * * *Cron expression for inactive inquiry sweep
SUPPORT_INQUIRIES_INACTIVE_CLOSE_DAYS7Number of inactive days before close

The scheduler:

  1. Resolves env-backed cron expression and inactivity window at startup.
  2. Registers a cron job with SchedulerRegistry.
  3. Calls SupportInquiryDomainService.closeInactive(before).
  4. Marks stale open, active, waiting, and resolved inquiries as closed.
  5. Sets closedAt and updatedAt.
  6. Logs success/failure using Nest Logger.

It does not delete rows. Message history remains available for admins.

9. Email and Notification Integration

Support inquiry email verification uses:

  • VerificationTokenService
  • BullService
  • QueueName.NOTIFICATIONS
  • NotificationJob.SEND_EMAIL

Verification request flow:

Support request admin replies use:

  • SupportNotificationService.notifyCustomerOfAdminReply(...)
  • realtime event publishing
  • activity recorder

10. Activity Logging

Admin support request operations record:

  • status updates
  • assignment changes
  • replies

Admin support inquiry operations record:

  • replies
  • assignment changes
  • status updates
  • link/create support request operations

Admin feedback operations record:

  • review action

Activity fields include:

  • admin user id/name/role
  • action
  • module
  • resource id/type
  • request context from SupportAdminSharedService.buildAuditContext(...)
  • changes when applicable

11. Error and Resilience Contracts

Inquiry-specific error codes:

HTTPerrorCodeScenario
404SUPPORT_INQUIRY_NOT_FOUNDInquiry does not exist
403SUPPORT_INQUIRY_ACCESS_DENIEDCustomer/guest lacks access
403SUPPORT_INQUIRY_TOKEN_INVALIDMissing, expired, revoked, or mismatched guest token
400SUPPORT_INQUIRY_CLOSEDMessage attempted against closed/spam inquiry
400SUPPORT_INQUIRY_LINK_INVALIDInvalid support request link target or identity mismatch
400SUPPORT_INQUIRY_EMAIL_VERIFICATION_INVALIDInvalid/missing verification state or OTP
400SUPPORT_INQUIRY_SUPPORT_REQUEST_REQUIREDSupport request creation requires verified customer

Existing support request and feedback services also use standard Nest exceptions and global exception formatting.

Resilience controls:

  • token hashes are stored, not raw guest tokens
  • email lookup is silent
  • multi-row create/link operations are transactional
  • websocket sync supports replay and gap detection
  • inactive close is idempotent
  • admin activity record failures are handled by the activity service without blocking primary operations

12. Query, Pagination, and Mapping Strategy

List endpoints use the project QueryDto and PaginationUtil patterns:

  • normalize pagination defaults
  • apply Drizzle limit and offset through utility output
  • count total rows only for paginated responses
  • map DB rows to response DTOs in services/domain services

Mapping boundaries:

  • controllers return ResponseDto<T>
  • services/domain services map raw database rows
  • guest token hashes are never mapped to response DTOs
  • admin response DTOs include internal references needed for operations
  • mobile/customer response DTOs omit admin-only details where the existing request DTOs already enforce that behavior

13. Backend Diagram

14. Conversion Data Flow

15. Release/QA Checklist

  • DB migration for support_inquiries, support_inquiry_messages, and support_inquiry_tokens has run before deploying API code.
  • Permission seed includes SupportInquiries.
  • Admin role has SupportInquiries_READ and SupportInquiries_UPDATE where needed.
  • Guest token storage hashes raw si_... tokens.
  • Guest token is returned only on create and only for guest-created inquiries.
  • Customer inquiry create does not return inquiryAccessToken.
  • Email verification request returns generic response for all email states.
  • OTP confirm links existing customer only after valid verification.
  • Inquiry-to-request conversion requires customerId.
  • Closed/spam inquiry messages are blocked.
  • Existing support request reply behavior still blocks closed tickets and reopens resolved tickets.
  • Feedback review sets reviewer metadata and activity record.
  • Websocket room joins enforce correct customer/admin/guest access.
  • Realtime sync fallback behavior is documented for frontend.
  • Inactive-close scheduler starts with env-backed config.

16. File Map

Support aggregate and shared:

  • apps/api/src/modules/support/support.module.ts
  • apps/api/src/modules/support/shared/support-shared.module.ts
  • apps/api/src/modules/support/shared/services/support-inquiry-domain.service.ts
  • apps/api/src/modules/support/shared/services/support-request-domain.service.ts
  • apps/api/src/modules/support/shared/services/support-notification.service.ts
  • apps/api/src/modules/support/shared/schedulers/support-inquiries-maintenance.scheduler.ts

Support inquiries:

  • apps/api/src/modules/support/customer/inquiries/*
  • apps/api/src/modules/support/admin/inquiries/*

Support requests:

  • apps/api/src/modules/support/mobile/support-requests/*
  • apps/api/src/modules/support/admin/support-requests/*

Feedback:

  • apps/api/src/modules/support/mobile/feedback/*
  • apps/api/src/modules/support/admin/feedback/*

Realtime:

  • apps/api/src/modules/support/realtime/*
  • apps/api/src/services/realtime/realtime.gateway.ts
  • apps/api/src/services/realtime/realtime-auth.guard.ts

Schema:

  • packages/db/src/schema/support/*

Migration:

  • packages/db/src/migrations/0002_add_support_inquiries.sql

17. Environment Variables

VariableDefaultDescription
SUPPORT_EMAILoptionalSupport contact email used by email templates/config where applicable
SUPPORT_INQUIRIES_INACTIVE_CLOSE_CRON0 * * * *Cron schedule for closing inactive inquiries
SUPPORT_INQUIRIES_INACTIVE_CLOSE_DAYS7Inactivity window before inquiry auto-close
OTP_EXPIRY_MINUTES15OTP expiry used by verification token service
OTP_MAX_ATTEMPTS5Maximum OTP attempts
WS_NAMESPACE/realtimeWebsocket namespace
EVENT_HISTORY_ENABLEDtrueEnables event replay history
EVENT_HISTORY_TTL3600Realtime replay TTL in seconds
ACK_TIMEOUT10000Socket acknowledgement timeout
ACK_RETRIES0Socket acknowledgement retries
WS_AUTH_DISABLEDfalseRealtime auth bypass for non-prod/test only

Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.


See Also