Documentation Index
Fetch the complete documentation index at: https://grantmaster.dev/llms.txt
Use this file to discover all available pages before exploring further.
Event Catalog
| Status | Updated | Covered Files |
|---|
| 🟢 Stable | 2026-02-21 | packages/shared/src/events/*, core/eventBus.ts |
Overview
GrantMaster uses a centralized event system (SystemEventType enum) for cross-feature coordination, notification triggering, and audit trail persistence. This catalog lists every event type, its payload schema, emitting service, persistence behavior, and typical subscribers.
Source file: packages/shared/src/events/index.ts
For the canonical cross-feature contract used by status projections (Grants/Projects/Compliance/Billing/Agents/Extensions), see docs/engineering/architecture/canonical-event-contract.md.
EventBus Topology
The EventBus follows a fan-out pattern: many domain services emit events into a single centralized bus, which dispatches them to a small set of cross-cutting consumers. Each consumer independently decides which event types it cares about.
Base Event Envelope
Every event shares the SystemEvent<T> envelope:
interface SystemEvent<T> {
type: SystemEventType;
organizationId: string;
userId: string;
severity: EventSeverity; // INFO | WARNING | ERROR | CRITICAL
timestamp: Date;
payload: T;
metadata?: {
source?: string;
version?: string;
correlationId?: string;
};
}
Severity Levels
| Level | Usage |
|---|
INFO | Normal operations (approvals, creations, completions) |
WARNING | Approaching limits, non-critical issues |
ERROR | Failures, rejections, errors |
CRITICAL | Budget depletion, compliance violations, credit exhaustion |
Persistence Rules
Events are persisted to Firestore when requiresPersistence(eventType) returns true. The following categories are always persisted:
- Audit events (
AUDIT_LOG_CREATED)
- Compliance events (all 3)
- Approval/rejection events (journals, expenses, time off)
- Budget events (threshold exceeded, depleted)
- User lifecycle events (onboarded, offboarded)
- Project lifecycle events (all 5)
- Template events (created, used)
- Quota events (exceeded, warning)
- Intelligence events (all 3)
- Portal events (all 4)
- Agent events (all 8)
- Credit events (all 3)
- Impact/M&E events (all 25)
- Module marketplace events (all 7 + 2 extension health)
Events NOT in these categories are ephemeral (notification-only, not saved to Firestore).
Type Guards
Helper functions for grouping events by domain:
| Function | Returns true for |
|---|
isJournalEvent() | JOURNAL_SUBMITTED, JOURNAL_APPROVED, JOURNAL_REJECTED |
isExpenseEvent() | EXPENSE_SUBMITTED, EXPENSE_APPROVED, EXPENSE_REJECTED |
isComplianceEvent() | COMPLIANCE_ALERT_RAISED, COMPLIANCE_ALERT_RESOLVED, COMPLIANCE_RULE_VIOLATED |
isBudgetEvent() | BUDGET_THRESHOLD_EXCEEDED, BUDGET_THRESHOLD_WARNING, BUDGET_DEPLETED |
isProjectLifecycleEvent() | PROJECT_CREATED, PROJECT_PHASE_ADVANCED, PROJECT_ARCHIVED, PROJECT_UNARCHIVED, PROJECT_CHECKLIST_COMPLETED |
isProjectTemplateEvent() | PROJECT_TEMPLATE_CREATED, PROJECT_TEMPLATE_USED |
isTimeOffRequestEvent() | TIME_OFF_REQUEST_SUBMITTED, TIME_OFF_REQUEST_APPROVED, TIME_OFF_REQUEST_REJECTED |
isQuotaEvent() | QUOTA_EXCEEDED, QUOTA_WARNING |
isIntelligenceEvent() | GRANT_APPLICATION_OUTCOME, INTELLIGENCE_CONSENT_CHANGED, INTELLIGENCE_SNAPSHOT_GENERATED |
isGrantEvent() | All 9 grant pipeline events |
isPortalEvent() | PORTAL_REPORT_ACKNOWLEDGED, PORTAL_REVISION_REQUESTED, PORTAL_COMMENT_POSTED, PORTAL_REPORT_SUBMITTED |
isAgentEvent() | All 8 agent lifecycle events |
isCreditEvent() | CREDITS_CONSUMED, CREDITS_EXHAUSTED, CREDITS_PURCHASED |
isMEEvent() | All 25 M&E events |
isModuleEvent() | All 7 module marketplace + 2 extension health events |
Event Reference by Domain
Journal Events
| Event | Severity | Persisted | Payload Interface |
|---|
JOURNAL_SUBMITTED | INFO | No | JournalSubmittedPayload |
JOURNAL_APPROVED | INFO | Yes | JournalApprovedPayload |
JOURNAL_REJECTED | WARNING | Yes | JournalRejectedPayload |
JournalSubmittedPayload: journalId, userId, userName, projectId, projectName, hours, date, managerId?
JournalApprovedPayload: journalId, userId, userName, projectId, projectName, hours, approvedBy, approvedByName, approvedAt
JournalRejectedPayload: Same as approved + rejectedBy, rejectedByName, rejectedAt, reason?
Expense Events
| Event | Severity | Persisted | Payload Interface |
|---|
EXPENSE_SUBMITTED | INFO | No | ExpenseSubmittedPayload |
EXPENSE_APPROVED | INFO | Yes | ExpenseApprovedPayload |
EXPENSE_REJECTED | WARNING | Yes | ExpenseRejectedPayload |
ExpenseSubmittedPayload: expenseId, userId, userName, projectId, projectName, amount, category, description, submittedAt
ExpenseApprovedPayload: Same core fields + approvedBy, approvedByName, approvedAt
ExpenseRejectedPayload: Same core fields + rejectedBy, rejectedByName, rejectedAt, reason?
Compliance Events
| Event | Severity | Persisted | Payload Interface |
|---|
COMPLIANCE_ALERT_RAISED | WARNING/ERROR | Yes | ComplianceAlertPayload |
COMPLIANCE_ALERT_RESOLVED | INFO | Yes | ComplianceAlertResolvedPayload |
COMPLIANCE_RULE_VIOLATED | ERROR | Yes | ComplianceAlertPayload |
ComplianceAlertPayload: alertId, projectId, projectName, ruleId, ruleName, violationType, severity (low/medium/high/critical), description, detectedBy?, detectedAt
ComplianceAlertResolvedPayload: alertId, projectId, projectName, ruleId, resolvedBy, resolvedByName, resolvedAt, resolution
Budget Events
| Event | Severity | Persisted | Payload Interface |
|---|
BUDGET_THRESHOLD_WARNING | WARNING | No | BudgetThresholdPayload |
BUDGET_THRESHOLD_EXCEEDED | WARNING | Yes | BudgetThresholdPayload |
BUDGET_DEPLETED | CRITICAL | Yes | BudgetDepletedPayload |
BudgetThresholdPayload: projectId, projectName, budgetLineId?, budgetLineName?, threshold (e.g., 80), currentUsage (percentage), totalBudget, spentAmount, remainingAmount, managerId?
BudgetDepletedPayload: projectId, projectName, budgetLineId?, budgetLineName?, totalBudget, overspentAmount, managerId?
Project Events
| Event | Severity | Persisted | Payload Interface |
|---|
PROJECT_DEADLINE_APPROACHING | WARNING | No | ProjectDeadlinePayload |
PROJECT_STATUS_CHANGED | INFO | No | ProjectStatusChangedPayload |
PROJECT_MILESTONE_COMPLETED | INFO | No | ProjectMilestonePayload |
ProjectDeadlinePayload: projectId, projectName, deadline, daysRemaining, phase, managerId?, teamMemberIds
ProjectStatusChangedPayload: projectId, projectName, oldStatus, newStatus, changedBy, changedByName, changedAt
ProjectMilestonePayload: projectId, projectName, milestoneId, milestoneName, completedBy, completedByName, completedAt
Project Lifecycle Events
| Event | Severity | Persisted | Payload Interface |
|---|
PROJECT_CREATED | INFO | Yes | ProjectCreatedPayload |
PROJECT_PHASE_ADVANCED | INFO | Yes | ProjectPhaseAdvancedPayload |
PROJECT_ARCHIVED | INFO | Yes | ProjectArchivedPayload |
PROJECT_UNARCHIVED | INFO | Yes | ProjectUnarchivedPayload |
PROJECT_CHECKLIST_COMPLETED | INFO | Yes | ProjectChecklistCompletedPayload |
ProjectCreatedPayload: projectId, projectName, projectCode, phase, fundingSource, createdBy, createdByName, templateId?, templateName?, createdAt
ProjectPhaseAdvancedPayload: projectId, projectName, fromPhase, toPhase, advancedBy, advancedByName, advancedAt, notes?, blockerCount, warningCount
ProjectArchivedPayload: projectId, projectName, archivedBy, archivedByName, archivedAt, finalPhase, totalHoursLogged, totalBudget
ProjectUnarchivedPayload: projectId, projectName, unarchivedBy, unarchivedByName, unarchivedAt, currentPhase
ProjectChecklistCompletedPayload: projectId, projectName, phase, completedBy, completedByName, completedAt, itemsCompleted, requiredItemsCompleted
Project Template Events
| Event | Severity | Persisted | Payload Interface |
|---|
PROJECT_TEMPLATE_CREATED | INFO | Yes | ProjectTemplateCreatedPayload |
PROJECT_TEMPLATE_USED | INFO | Yes | ProjectTemplateUsedPayload |
ProjectTemplateCreatedPayload: templateId, templateName, createdBy, createdByName, sourceProjectId?, sourceProjectName?, createdAt, isPublic
ProjectTemplateUsedPayload: templateId, templateName, projectId, projectName, usedBy, usedByName, usedAt, usageCount
User Events
| Event | Severity | Persisted | Payload Interface |
|---|
USER_ONBOARDED | INFO | Yes | UserOnboardedPayload |
USER_OFFBOARDED | WARNING | Yes | UserOffboardedPayload |
UserOnboardedPayload: userId, userName, email, role, department?, managerId?, onboardedAt
UserOffboardedPayload: userId, userName, email, offboardedBy, offboardedByName, offboardedAt, reason?
Time Off Events
| Event | Severity | Persisted | Payload Interface |
|---|
TIME_OFF_REQUEST_SUBMITTED | INFO | No | TimeOffRequestSubmittedPayload |
TIME_OFF_REQUEST_APPROVED | INFO | Yes | TimeOffRequestApprovedPayload |
TIME_OFF_REQUEST_REJECTED | WARNING | Yes | TimeOffRequestRejectedPayload |
TimeOffRequestSubmittedPayload: leaveRequestId, userId, userName, leaveType, startDate, endDate, daysRequested, managerId?, notes?, submittedAt
TimeOffRequestApprovedPayload: Same core fields + approvedBy, approvedByName, approvedAt
TimeOffRequestRejectedPayload: Same core fields + rejectedBy, rejectedByName, rejectedAt, reason?
Quota Events
| Event | Severity | Persisted | Payload Interface |
|---|
QUOTA_WARNING | WARNING | Yes | QuotaWarningPayload |
QUOTA_EXCEEDED | ERROR | Yes | QuotaExceededPayload |
QuotaWarningPayload: resourceType (users/projects/storage/ai_generations/agent_credits/agent_runs), limit, current, available, percentageUsed, subscriptionTier, threshold
QuotaExceededPayload: Same resource types + limit, current, available, attempted, subscriptionTier, suggestedTier?, requiresUpgrade
Note: organizationId goes in the event envelope, not the payload.
Audit Events
| Event | Severity | Persisted | Payload Interface |
|---|
AUDIT_LOG_CREATED | INFO/ERROR | Yes (always) | AuditLogPayload |
AuditLogPayload: action, resourceType, resourceId, resourceName?, result (success/failure), errorMessage?, userName?, userEmail?, changes?, ipAddress?, userAgent?
Grant Pipeline Events
| Event | Severity | Persisted | Payload Interface |
|---|
GRANT_ADDED_TO_PIPELINE | INFO | No | GrantAddedToPipelinePayload |
GRANT_PIPELINE_STAGE_CHANGED | INFO | No | GrantPipelineStageChangedPayload |
GRANT_APPLICATION_SUBMITTED | INFO | No | GrantApplicationSubmittedPayload |
GRANT_WON | INFO | No | GrantWonPayload |
GRANT_LOST | WARNING | No | GrantLostPayload |
GRANT_REPORT_DUE | WARNING | No | GrantReportDuePayload |
GRANT_REPORT_SUBMITTED | INFO | No | GrantReportSubmittedPayload |
GRANT_DISBURSEMENT_RECEIVED | INFO | No | GrantDisbursementReceivedPayload |
GrantAddedToPipelinePayload: pipelineId, opportunityId, grantTitle, grantorName, requestedAmount, currency, addedBy, addedByName, addedAt
GrantPipelineStageChangedPayload: pipelineId, opportunityId, grantTitle, previousStage, newStage, changedBy, changedByName, reason?, changedAt
GrantApplicationSubmittedPayload: applicationId, pipelineId, opportunityId, grantTitle, requestedAmount, currency, confirmationNumber?, submittedBy, submittedByName, submittedAt
GrantWonPayload: grantId, pipelineId, opportunityId, grantTitle, grantorName, awardedAmount, currency, startDate, endDate, recordedAt, projectId (2026-04-14: server-side convert now auto-creates a linked project and includes its id; see ADR #17)
GrantLostPayload: pipelineId, opportunityId, grantTitle, grantorName, requestedAmount, currency, reason?, recordedAt
GrantReportDuePayload: grantId, grantTitle, reportId, reportType, dueDate, daysUntilDue, assignedTo?
GrantReportSubmittedPayload: grantId, grantTitle, reportId, reportType, submittedBy, submittedByName, submittedAt
GrantDisbursementReceivedPayload: grantId, grantTitle, disbursementId, amount, currency, receivedAt, totalReceived, remainingAmount
Intelligence Events
| Event | Severity | Persisted | Payload Interface |
|---|
GRANT_APPLICATION_OUTCOME | INFO | Yes | GrantApplicationOutcomePayload |
INTELLIGENCE_CONSENT_CHANGED | INFO | Yes | IntelligenceConsentChangedPayload |
INTELLIGENCE_SNAPSHOT_GENERATED | INFO | Yes | IntelligenceSnapshotGeneratedPayload |
GrantApplicationOutcomePayload: pipelineId, opportunityId, outcome (won/lost/dead), requestedAmount, awardedAmount?, currency, grantorType, decisionDays, projectName?, recordedAt
IntelligenceConsentChangedPayload: action (granted/withdrawn), dataCategories, changedBy, changedByName, changedAt, withdrawalReason?
IntelligenceSnapshotGeneratedPayload: snapshotId, snapshotDate, metricsCount, qualityScore (0-100), generatedAt
Document Brain Events
| Event | Severity | Persisted | Payload Interface |
|---|
DOCUMENT_UPLOADED | INFO | No | Record<string, unknown> (TBD) |
DOCUMENT_APPROVED | INFO | No | Record<string, unknown> (TBD) |
DOCUMENT_REJECTED | WARNING | No | Record<string, unknown> (TBD) |
DOCUMENT_REVIEW_REQUESTED | INFO | No | Record<string, unknown> (TBD) |
DOCUMENT_VERSION_CREATED | INFO | No | Record<string, unknown> (TBD) |
DOCUMENT_CLASSIFIED | INFO | No | Record<string, unknown> (TBD) |
DOCUMENT_DEADLINE_EXTRACTED | INFO | No | Record<string, unknown> (TBD) |
Payload interfaces for document events are not yet defined. They use Record<string, unknown> in the EventPayloadMap.
Portal Events (Stakeholder Portal)
| Event | Severity | Persisted | Payload Interface |
|---|
PORTAL_REPORT_ACKNOWLEDGED | INFO | Yes | PortalReportAcknowledgedPayload |
PORTAL_REVISION_REQUESTED | WARNING | Yes | PortalRevisionRequestedPayload |
PORTAL_COMMENT_POSTED | INFO | Yes | PortalCommentPostedPayload |
PORTAL_REPORT_SUBMITTED | INFO | Yes | PortalReportSubmittedPayload |
PortalReportAcknowledgedPayload: reportId, reportName, projectId, projectName, status (received/approved), stakeholderName, stakeholderType (funder/partner/board/auditor), tokenId, acknowledgedAt
PortalRevisionRequestedPayload: reportId, reportName, projectId, projectName, stakeholderName, stakeholderType, revisionNotes, tokenId, requestedAt
PortalCommentPostedPayload: commentId, projectId, projectName, stakeholderName, stakeholderType, contentPreview, tokenId, postedAt
PortalReportSubmittedPayload: submissionId, submissionTitle, projectId, projectName, stakeholderName, stakeholderType, attachmentCount, tokenId, submittedAt
Agent Lifecycle Events
| Event | Severity | Persisted | Payload Interface |
|---|
AGENT_TASK_STARTED | INFO | Yes | AgentTaskStartedPayload |
AGENT_TASK_COMPLETED | INFO | Yes | AgentTaskCompletedPayload |
AGENT_TASK_FAILED | ERROR | Yes | AgentTaskFailedPayload |
AGENT_TASK_CANCELLED | WARNING | Yes | AgentTaskCancelledPayload |
AGENT_STEP_COMPLETED | INFO | Yes | AgentStepCompletedPayload |
AGENT_ESCALATION_REQUIRED | WARNING | Yes | AgentEscalationRequiredPayload |
AGENT_ESCALATION_RESOLVED | INFO | Yes | AgentEscalationResolvedPayload |
AGENT_BUDGET_CONSUMED | WARNING | Yes | AgentBudgetConsumedPayload |
AgentTaskStartedPayload: runId, agentType, triggeredBy, triggeredByName, input, creditsReserved, startedAt
AgentTaskCompletedPayload: runId, agentType, stepsCompleted, creditsConsumed, tokensUsed, durationMs, output, completedAt
AgentTaskFailedPayload: runId, agentType, error, failedAtStep, creditsConsumed, failedAt
AgentTaskCancelledPayload: runId, agentType, cancelledBy, cancelledByName, stepsCompleted, creditsConsumed, cancelledAt
AgentStepCompletedPayload: runId, agentType, stepId, stepIndex, toolName, creditsUsed, tokensUsed, durationMs, completedAt
AgentEscalationRequiredPayload: runId, agentType, stepId, reason, options (string[]), requiredPermission?, escalatedAt
AgentEscalationResolvedPayload: runId, agentType, stepId, resolvedBy, resolvedByName, resolution, resolvedAt
AgentBudgetConsumedPayload: runId, creditsConsumed, creditsRemaining, percentageUsed
Credit Events
| Event | Severity | Persisted | Payload Interface |
|---|
CREDITS_CONSUMED | INFO | Yes | Record<string, unknown> (TBD) |
CREDITS_EXHAUSTED | CRITICAL | Yes | CreditsExhaustedPayload |
CREDITS_PURCHASED | INFO | Yes | CreditsPurchasedPayload |
CreditsExhaustedPayload: organizationId, totalCredits, creditsUsed, lastAgentRunId?, suggestedTier?
CreditsPurchasedPayload: packSize, amount, currency, newBalance, stripePaymentIntentId?
Impact (M&E) Events
Core Indicator Events
| Event | Severity | Persisted | Payload Interface |
|---|
ME_INDICATOR_CREATED | INFO | Yes | MEIndicatorCreatedPayload |
ME_INDICATOR_UPDATED | INFO | Yes | MEIndicatorUpdatedPayload |
ME_INDICATOR_ARCHIVED | INFO | Yes | MEIndicatorArchivedPayload |
ME_TARGET_SET | INFO | Yes | METargetSetPayload |
ME_DATA_POINT_RECORDED | INFO | Yes | MEDataPointRecordedPayload |
ME_INDICATOR_STATUS_CHANGED | INFO | Yes | MEIndicatorStatusChangedPayload |
Approval Workflow Events
| Event | Severity | Persisted | Payload Interface |
|---|
ME_DATA_POINT_SUBMITTED | INFO | Yes | MEDataPointSubmittedPayload |
ME_DATA_POINT_APPROVED | INFO | Yes | MEDataPointApprovedPayload |
ME_DATA_POINT_REJECTED | WARNING | Yes | MEDataPointRejectedPayload |
| Event | Severity | Persisted | Payload Interface |
|---|
ME_KOBO_SYNC_COMPLETED | INFO | Yes | MEKoboSyncCompletedPayload |
ME_KOBO_SYNC_FAILED | ERROR | Yes | MEKoboSyncFailedPayload |
Grant-Impact Events (Phase 3)
| Event | Severity | Persisted | Payload Interface |
|---|
ME_GRANT_INDICATOR_LINKED | INFO | Yes | MEGrantIndicatorLinkedPayload |
ME_GRANT_INDICATOR_UNLINKED | INFO | Yes | MEGrantIndicatorUnlinkedPayload |
ME_DONOR_EXPORT_GENERATED | INFO | Yes | MEDonorExportGeneratedPayload |
ME_PORTFOLIO_VIEWED | INFO | Yes | MEPortfolioViewedPayload |
AI Assistant & Workflow Engine Events (Phase 4)
| Event | Severity | Persisted | Payload Interface |
|---|
ME_AI_INDICATORS_SUGGESTED | INFO | Yes | MEAIIndicatorsSuggestedPayload |
ME_AI_SUGGESTION_ACCEPTED | INFO | Yes | MEAISuggestionAcceptedPayload |
ME_AI_SUGGESTION_DISMISSED | INFO | Yes | MEAISuggestionDismissedPayload |
ME_AI_NARRATIVE_GENERATED | INFO | Yes | MEAINarrativeGeneratedPayload |
ME_AI_ANOMALY_DETECTED | WARNING | Yes | MEAIAnomalyDetectedPayload |
ME_WORKFLOW_RULE_CREATED | INFO | Yes | MEWorkflowRuleCreatedPayload |
ME_WORKFLOW_RULE_UPDATED | INFO | Yes | MEWorkflowRuleUpdatedPayload |
ME_WORKFLOW_RULE_DELETED | INFO | Yes | MEWorkflowRuleDeletedPayload |
ME_WORKFLOW_RULE_TRIGGERED | INFO | Yes | MEWorkflowRuleTriggeredPayload |
ME_WORKFLOW_RULE_FAILED | ERROR | Yes | MEWorkflowRuleFailedPayload |
Module Marketplace Events
| Event | Severity | Persisted | Payload Interface |
|---|
MODULE_INSTALLED | INFO | Yes | ModuleInstalledPayload |
MODULE_ACTIVATED | INFO | Yes | ModuleActivatedPayload |
MODULE_DEACTIVATED | INFO | Yes | ModuleDeactivatedPayload |
MODULE_UNINSTALLED | WARNING | Yes | ModuleUninstalledPayload |
MODULE_TRIAL_STARTED | INFO | Yes | ModuleTrialStartedPayload |
MODULE_TRIAL_EXPIRED | WARNING | Yes | ModuleTrialExpiredPayload |
MODULE_PAYMENT_FAILED | ERROR | Yes | ModulePaymentFailedPayload |
ModuleInstalledPayload: moduleId, moduleName, installedBy, trialDays?
ModuleActivatedPayload: moduleId, moduleName, activatedBy, previousStatus, stripeSubscriptionItemId?
ModuleDeactivatedPayload: moduleId, moduleName, deactivatedBy, reason?
ModuleUninstalledPayload: moduleId, moduleName, uninstalledBy, dataRetained
ModuleTrialStartedPayload: moduleId, moduleName, trialDays, trialEndsAt, startedBy
ModuleTrialExpiredPayload: moduleId, moduleName, trialStartedAt, trialEndedAt
ModulePaymentFailedPayload: moduleId, moduleName, stripeSubscriptionItemId?, failureReason?, retryCount?
Extension Health Events
| Event | Severity | Persisted | Payload Interface |
|---|
EXTENSION_AUTO_DISABLED | ERROR | Yes | ExtensionAutoDisabledPayload |
EXTENSION_HEALTH_CHECK_FAILED | WARNING | Yes | ExtensionHealthCheckFailedPayload |
EXTENSION_TENANT_SWITCHED | INFO | No | ExtensionTenantSwitchedPayload |
ExtensionAutoDisabledPayload: extensionId, extensionName, errorCount, windowMinutes, lastError, disabledBy (always 'health_monitor')
ExtensionHealthCheckFailedPayload: extensionId, extensionName, errorCount, lastError, threshold
ExtensionTenantSwitchedPayload: previousOrganizationId, newOrganizationId, activeExtensionIds
Tenant Classification Events
| Event | Severity | Persisted | Payload Interface |
|---|
TENANT_CLASSIFICATION_UPDATED | INFO | No | TenantClassificationUpdatedPayload |
TenantClassificationUpdatedPayload: fieldsChanged, completenessScore, previousScore, source (ONBOARDING/SETTINGS/MIGRATION/AI_SUGGESTION), isMigration
EventPayloadMap
The EventPayloadMap interface in events.ts provides compile-time type safety for the IEventBus.on() and emit() methods. When subscribing to a specific SystemEventType, the handler’s event.payload is automatically typed to the correct payload interface.
// Type-safe subscription — payload is automatically typed
eventBus.on(SystemEventType.EXPENSE_APPROVED, (event) => {
// event.payload is ExpenseApprovedPayload
console.log(event.payload.expenseId, event.payload.amount);
});
The utility type TypedSystemEvent<E> narrows a SystemEvent to a specific event type with its payload resolved from the map.
Summary Statistics
| Category | Event Count |
|---|
| Journal | 3 |
| Expense | 3 |
| Compliance | 3 |
| Budget | 3 |
| Project | 3 |
| Project Lifecycle | 5 |
| Project Template | 2 |
| User | 2 |
| Time Off | 3 |
| Quota | 2 |
| Audit | 1 |
| Grant Pipeline | 8 |
| Intelligence | 3 |
| Document Brain | 7 |
| Portal | 4 |
| Agent Lifecycle | 8 |
| Credit | 3 |
| Impact (M&E) | 25 |
| Module Marketplace | 7 |
| Extension Health | 3 |
| Tenant | 1 |
| Total | 100 |
Maintenance
Update this document when:
- Adding new
SystemEventType values
- Creating new payload interfaces
- Changing persistence rules in
requiresPersistence()
- Adding new type guard functions