Skip to main content

Comments & Messaging

Overview

AMS has a unified comment system used at multiple scopes and with configurable visibility. Understanding internal vs external is critical — it is a core business rule with security implications.

Visibility: Internal vs External

Business rule

INTERNAL comments are visible only to org staff (OWNER, ADMIN, MANAGER, MEMBER). EXTERNAL comments are visible to both staff and clients.

Clients never see INTERNAL comments. This is enforced at the GraphQL query level.

TypeWho sees it
INTERNALStaff only (OWNER, ADMIN, MANAGER, MEMBER)
EXTERNALStaff + clients

When adding a comment, staff must explicitly choose the visibility. The default varies by context.

Comment scope

Comments can be scoped to two levels:

ScopeapplicationDocumentDefinitionIdUse case
Application-levelnullGeneral discussion about the application
Document-levelSet to a slot IDDiscussion about a specific document slot

Comment categories

CategoryUsed for
APPLICATIONGeneral application-level comments
DOCUMENTSDocument slot comments
DECISIONComments in the decision section
APPLICANTSComments about applicants section

The category is set automatically based on scope: document-level comments default to DOCUMENTS, others to APPLICATION.

Action log auto-comments

When staff review a document (approve, reject, re-request, mark not-applicable), the system automatically creates a comment with an actionType set. These are not user-written comments — they are system-generated audit entries.

ActionactionTypeVisibility
ApproveAPPROVEDEXTERNAL
RejectREJECTEDEXTERNAL
Re-requestRE_REQUESTEDEXTERNAL
Not applicableNOT_APPLICABLEEXTERNAL
File uploadedUPLOADEDEXTERNAL

Action log comments have parentId linking them to the relevant reply thread.

Threading & unread tracking

  • Comments have a parentId for reply threading
  • ApplicationCommentRead tracks per-user read state per comment
  • needsReply flag — whether a comment requires a staff response
  • workspaceUnreadCommentCount — total unread count across all apps in workspace
  • markCategoryCommentsAsRead — marks an entire category as read (triggered after 1.5s viewing)

Workspace messages inbox

The workspace-level Messages page shows a cross-application view of all comment threads:

Left panel: Tree of threads filtered by:

  • All / Internal / External
  • Unread
  • Needs Reply
  • Category
  • Search

Right panel: Thread detail with full comment history

Application-level messages tab shows:

  • Application-level comments (paginated, 20 per page)
  • Document-level comment summaries per slot

Notification format

When a comment triggers a notification, the message uses this format:

"Domain · Application Title · Visibility"

Examples:

  • "Application · My Tax App · Internal" — app-level internal comment
  • "Document · My Tax App · External" — doc-slot external comment

The parseContext() function in notification-panel.tsx splits on · to extract { label, title, visibility }.

GraphQL hooks (frontend)

Use useCreateApplicationComment(applicationId, applicationTitle?) from use-application-comments.ts:

// Build message for notification
const contextLabel = input.applicationDocumentDefinitionId ? 'Document' : 'Application'
const visibility = input.type === 'INTERNAL' ? 'Internal' : 'External'
const message = applicationTitle
? `${contextLabel} · ${applicationTitle} · ${visibility}`
: `${contextLabel} · ${visibility}`

applicationTitle must be passed by the caller — it is NOT fetched inside the hook.


See also