Skip to content

Domain Model

Signal defines no schema of its own. Its only persisted entity is ActivityNotification, whose table, model, and repository all live in @nx/core. Connection and AES-key state are held in-memory per instance and are not modeled here.

1. Full ERD

ActivityNotification has no foreign-key relations in the schema — recipientId and organizerId are soft references to user / organizer IDs resolved at write time.

2. Entities

ActivityNotification

PropertyValue
TableActivityNotification
Sourcepackages/core/src/models/schemas/public/activity-notification/schema.ts
Modelpackages/core/src/models/schemas/public/activity-notification/model.ts
RepositoryActivityNotificationRepository (@nx/core)
Soft-deleteyes (SoftDeletableRepository, deletedAt)
Owner ID columnrecipientId (per-user)

Fields:

FieldTypeRequiredDefaultDescription
idtextSnowflakePrimary key
recipientIdtextTarget user; one row per recipient
typevarchar(80)TActivityNotificationTypes (see enum)
organizerIdtextnullOwning organizer, if scoped
contenttextRendered plain-text content
htmltextRendered HTML content
actionUrltextnullDeep-link target
datajsonb{}Actor + event payload snapshot
isReadbooleanfalseRead flag
readAttimestamptznullSet when marked read

Type enum (ActivityNotificationTypes):

ValueDescription
PAYMENT_SUCCESSOnly type implemented today; rendered from the actor + payment payload

The worker rejects any eventType not in ActivityNotificationTypes.SCHEME_SET (logs a warning and skips).

Indexes:

NameColumnsPurpose
IDX_ActivityNotification_recipientId_isDeleted_createdAtrecipient_id, deleted_at, created_atBell query — recipient's notifications, newest first
IDX_ActivityNotification_recipientId_isReadrecipient_id, is_readUnread count
IDX_ActivityNotification_organizerId_type_createdAtorganizer_id, type, created_atFilter by organizer + type

Relations: none declared in schema (recipientId / organizerId are soft references).

3. Cross-entity Invariants

InvariantEnforcement
One row per recipient per fan-outWorker loops over resolved recipients and createAlls a row each
readAt set ⇔ isRead = trueActivityNotificationService.markAsRead / markAllAsRead set both together
Recipient can only read/mutate their own rowsController scopes every query by recipientId = JWT subject

4. Soft-delete Behavior

BehaviorDetail
Read defaultdeletedAt IS NULL (model defaultFilter)
Hard-deletenot used by signal
Restorenot exposed

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.