Event Catalog
All events share the envelope from event-driven-spine.md. This catalog defines the eventType values and their data payloads.
Audit status (2026-04-12, followup): This file is split into three sections. Published Events entries are verified against a
publish()call inapps/hub/src/**/*.ts; payload shapes are taken from the actual publish call. Subscribed-Only Events are subjects the hub listens on but does not publish itself (typically emitted by plugins viaPluginContext). Planned Events are documented schemas with no publisher or subscriber yet — they describe intended future behavior and are not wired. Only a subset of the hub's published events are cataloged here; domains such ascoordination.*,governance.*,marketplace.*,presence.*,dispute.*,wiki.*, and per-entity domain events (health.*,fitness.*, etc.) are published by the hub but documented in their own service references.
Published Events
connector.*
connector.DataReceived
Emitted by the Connector Service after a plugin returns raw items ready for ETL.
Publisher: apps/hub/src/services/connectors/ConnectorService.ts
{
connectorId: string,
entityType: string,
rawItems: unknown[],
syncId: string
}
connector.SyncCompleted
Emitted after a full sync cycle finishes.
Publisher: apps/hub/src/services/connectors/ConnectorService.ts
{
connectorId: string,
itemsProcessed: number,
syncId: string,
nextSyncAt: string
}
connector.BridgeProcessed
Emitted by the Connector Bridge after routing a plugin result into observations.
Publisher: apps/hub/src/services/connector/ConnectorBridgeService.ts
{
connectorId: string,
observationCount: number,
correlationId: string
}
communication.*
communication.MessageSent
Outbound message accepted by the provider.
Publisher: apps/hub/src/services/channels/ChannelService.ts
{
messageId: string,
conversationId: string,
channelId: string,
recipientPhone: string,
providerMessageId: string,
timestamp: string
}
communication.CallStarted
Inbound or outbound call began.
Publishers: apps/hub/src/services/calling/CallingService.ts, apps/hub/src/services/channels/ChannelService.ts
{
callId: string,
conversationId: string,
channelId: string,
direction: 'inbound' | 'outbound',
callerPhone: string,
calleePhone: string,
timestamp: string,
providerCallId: string
}
communication.VoicemailReceived
New voicemail recorded.
Publisher: apps/hub/src/services/calling/VoicemailService.ts
{
voicemailId: string,
ownerId: string,
fromNumber: string,
contactId: string | null,
durationSeconds: number,
phoneLineId: string | null
}
communication.NoteReceived
ActivityPub Note received from a federated peer.
Publisher: apps/hub/src/services/federation/ActivityPubService.ts
{
actorId: string,
noteId: string,
content: string,
receivedAt: string
}
data.*
data.EntityCreated
New entity persisted.
Publishers: apps/hub/src/services/calling/PhoneLineService.ts, apps/hub/src/services/contacts/ContactTimelineService.ts, apps/hub/src/services/entity-registry/EntityRegistryService.ts
{
entityType: string,
entityId: string,
sourceConnectorId: string | null
}
data.EntityEmbedded
Embedding pipeline produced a vector for an entity.
Publisher: apps/hub/src/services/embedding/EmbeddingPipelineService.ts
{
entityType: string,
entityId: string,
model: string,
dimensions: number
}
data.EntityMerged
Two records merged by the lineage service.
Publisher: apps/hub/src/services/lineage/EntityMergeService.ts
{
primaryId: string,
mergedId: string,
entityType: string
}
data.RuleMatched
A rule evaluated to true during Rules Service processing.
Publisher: apps/hub/src/services/rules/RulesService.ts
{
ruleId: string,
triggerEventId: string,
matchedAt: string
}
inbox.*
inbox.ItemCreated
New item landed in the unified inbox.
Publisher: apps/hub/src/services/inbox/InboxService.ts
{
inboxItemId: string,
ownerId: string,
type: 'call' | 'sms' | 'email' | 'voicemail' | 'video' | 'calendar_event',
channelType: string,
direction: 'inbound' | 'outbound',
contactId: string | null
}
inbox.ItemUpdated
Inbox item read/starred/archived state changed.
Publisher: apps/hub/src/services/inbox/InboxService.ts
{
inboxItemId: string,
ownerId: string,
changedFields: string[]
}
contact.*
contact.Resolved
Identifier matched to an existing contact.
Publisher: apps/hub/src/services/inbox/InboxService.ts
{
identifier: string,
identifierType: 'phone' | 'email',
contactId: string,
ownerId: string
}
contact.SuggestionCreated
Unrecognized identifier created a contact suggestion.
Publisher: apps/hub/src/services/inbox/InboxService.ts
{
identifier: string,
identifierType: 'phone' | 'email',
ownerId: string,
sourceEventType: string
}
contact.Merged
Two contact records merged.
Publisher: apps/hub/src/services/contacts/ContactTimelineService.ts
{
primaryId: string,
mergedId: string,
ownerId: string
}
email.*
email.Sent
Outbound email accepted by Microsoft Graph.
Publisher: apps/hub/src/services/email/EmailService.ts
{
messageId: string,
threadId: string,
to: Array<{ name: string, email: string }>,
subject: string,
sentAt: string
}
email.DraftSaved
Draft created or updated.
Publisher: apps/hub/src/services/email/EmailService.ts
{
messageId: string,
subject: string,
to: Array<{ name: string, email: string }>,
savedAt: string
}
email.SendRequested
Rule action requested that an outbound email be composed and sent.
Publisher: apps/hub/src/services/rules/RulesService.ts
{
ruleId: string,
to: string[],
subject: string,
body: string
}
video.*
video.MeetingCreated
New video meeting room provisioned.
Publisher: apps/hub/src/services/meeting/MeetingService.ts
{
meetingId: string,
ownerId: string,
title: string,
roomName: string,
scheduledStart: string | null,
scheduledEnd: string | null
}
video.MeetingStarted
First participant joined a meeting.
Publisher: apps/hub/src/services/meeting/MeetingService.ts
{
meetingId: string,
ownerId: string,
roomName: string,
startedAt: string
}
video.MeetingEnded
Last participant left.
Publisher: apps/hub/src/services/meeting/MeetingService.ts
{
meetingId: string,
ownerId: string,
roomName: string,
endedAt: string,
durationSeconds: number,
participantCount: number
}
audio.*
audio.SessionStarted
Windows audio sidecar began a recording session.
Publisher: apps/hub/src/api/routes/audio.ts
{
sessionId: string,
ownerId: string,
source: 'mic' | 'system' | 'both',
deviceId: string
}
audio.SessionEnded
Recording session completed.
Publisher: apps/hub/src/api/routes/audio.ts
{
sessionId: string,
ownerId: string,
durationSeconds: number,
segmentCount: number
}
audio.TranscriptChunk
A transcript chunk was persisted.
Publisher: apps/hub/src/api/routes/audio.ts
{
sessionId: string,
ownerId: string,
transcriptId: string,
pass: number,
segmentCount: number,
fullText: string
}
audio.CommandDetected
Wake-word command parsed from the transcript.
Publisher: apps/hub/src/api/routes/audio.ts
{
commandId: string,
sessionId: string,
ownerId: string,
rawTranscript: string,
commandText: string,
intent: string,
confidence: number
}
audio.CommandExecuted
Voice Command Service processed a command.
Publisher: apps/hub/src/services/voice-command/VoiceCommandService.ts
{
commandId: string,
sessionId: string,
ownerId: string,
intent: string,
jobId: string,
status: 'completed' | 'failed'
}
audio.IntelligenceExtracted
LLM extraction pass complete.
Publisher: apps/hub/src/services/audio-etl/AudioETLService.ts
{
sessionId: string,
ownerId: string,
transcriptId: string,
actionItemCount: number,
decisionCount: number,
commitmentCount: number,
entityMentionCount: number
}
audio.PassiveIntentDetected
Regex/LLM detected a passive user intent in an audio transcript.
Publisher: apps/hub/src/services/audio-etl/AudioETLService.ts
{
sessionId: string,
ownerId: string,
text: string,
intentType: string,
confidence: number,
context?: unknown
}
ai.*
ai.CallAnalyzed
AI analysis of a call transcript completed.
Publisher: apps/hub/src/services/calling/TranscriptionService.ts
{
analysisId: string,
callSessionId: string,
ownerId: string,
sentiment: 'positive' | 'neutral' | 'negative' | null,
actionItemCount: number,
keyTopics: string[]
}
ai.EmailSuggested
Email AI detected priority / follow-up opportunities.
Publisher: apps/hub/src/services/email/EmailAIService.ts
{
threadId: string,
priority: {
threadId: string,
score: number,
factors: string[],
generatedAt: string
},
followUps: Array<{
threadId: string,
messageId: string,
detectedPhrase: string,
suggestedDueDate: string,
description: string
}>
}
ai.QueryReceived
Published by AgentService.query before any work happens. One event per inbound agent query. Useful for tracking inbound query rate, length distribution, abandonment (queries received without a matching ai.ResponseGenerated), and per-user activity.
Publisher: apps/hub/src/services/agent/AgentService.ts
{
queryId: string, // correlates with the ResponseGenerated event
userId: string,
conversationId: string,
queryLength: number, // character length of the raw query
hasExistingConversation: boolean // true when the caller passed a conversationId
}
ai.ResponseGenerated
Published by AgentService.query after the LLM returns, the audit entry is written, and the conversation row is inserted. Correlates with ai.QueryReceived via queryId. Useful for dashboards that track provider mix, latency percentiles, response-length distribution, and routing-reason breakdown without reading the audit log.
Publisher: apps/hub/src/services/agent/AgentService.ts
{
queryId: string, // same as ai.QueryReceived.queryId
userId: string,
conversationId: string,
provider: string, // e.g. 'openrouter' | 'ollama'
model: string, // e.g. 'anthropic/claude-3.5-sonnet' | 'llama3.2'
routingReason: string, // LlmRouter decision rationale
contextSnippetCount: number, // how many Meilisearch hits were included in the prompt
responseLength: number, // character length of the LLM's response
latencyMs: number // wall time from QueryReceived to now
}
system.*
system.WorkflowCompleted
Workflow run reached a terminal state.
Publisher: apps/hub/src/services/workflow/WorkflowService.ts
{
workflowId: string,
runId: string,
status: 'completed' | 'failed' | 'cancelled'
}
system.ScheduledTrigger
Scheduler fired a schedule. Dual-published alongside scheduler.ScheduleFired so Rules and Workflow services can subscribe to a stable subject.
Publisher: apps/hub/src/services/scheduler/SchedulerService.ts
{
scheduleId: string,
scheduleName: string,
ownerId: string,
sourceType: string,
sourceId: string,
payload: unknown,
runId: string,
firedAt: string
}
system.IntentionTriggered
An active intention reached its trigger condition.
Publisher: apps/hub/src/services/intentions/IntentionsService.ts
{
intentionId: string,
ownerId: string,
title: string,
triggeredAt: string
}
system.plugin
Plugin lifecycle event (install/uninstall/update). The envelope's inner eventType distinguishes the specific action (e.g. plugin.Installed).
Publisher: apps/hub/src/services/plugins/PluginRegistryService.ts
{
pluginId: string,
ownerId: string
}
system.HealthCheckFailed
Published when CircuitBreakerService transitions a named circuit from CLOSED → OPEN (failure threshold exceeded) or HALF_OPEN → OPEN (probe failed). One event per state transition — not one per failure. willRetry is always true because the breaker will attempt a HALF_OPEN probe after retryAfterMs.
Publisher: apps/hub/src/services/circuit-breaker/CircuitBreakerService.ts
{
target: string, // circuit name, e.g. 'nats', 'meilisearch', 'openrouter'
reason: string, // message of the error that tripped the breaker
trigger: 'failure_threshold_exceeded' | 'half_open_probe_failed',
failureCount: number, // total failures recorded on this circuit
willRetry: boolean, // always true — breaker auto-probes after retryAfterMs
retryAfterMs: number // config.timeoutMs for this circuit
}
system.ServiceStarted
Published once at the tail of hub boot, after all services have started and the HTTP server is listening. One event per process — not per service — so subscribers (dashboards, alerting, audit log) have a durable record of every hub start without being drowned at startup.
Publisher: apps/hub/src/main.ts
{
serviceName: 'hub',
version: string, // from npm_package_version, defaults to 'dev'
nodeVersion: string, // process.version
pid: number,
port: number, // HTTP API port
startedAt: string // ISO-8601
}
system.PluginLoaded
Published by PluginManager.loadPlugin after a hub-side plugin (connector, channel, or operator) is successfully loaded from disk and its init() has returned. Distinct from the user-scoped system.plugin lifecycle event emitted by PluginRegistryService when a user installs a plugin.
Publisher: apps/hub/src/services/plugins/PluginManager.ts
{
pluginId: string, // manifest id, e.g. 'com.microsoft.graph'
pluginName: string,
pluginVersion: string,
pluginType: 'connector' | 'channel' | 'operator',
pluginPath: string // relative path passed to loadPlugin
}
credential.*
credential.CredentialAdded
Published by POST /api/credentials (apps/hub/src/api/routes/credentials.ts) after a credential is upserted into user_credentials and secrets are stored in Supabase Vault. Consumed by audit and capability-activation subscribers.
{
userId: string,
credentialId: string,
credentialType: string, // e.g. 'twilio' | 'microsoft365' | 'openrouter' | 'ollama'
displayInfo: string // human-readable, never a secret
}
credential.CredentialRemoved
Published by DELETE /api/credentials/:type after the vault secrets and metadata row are deleted. Consumed by audit and capability-deactivation subscribers.
{
userId: string,
credentialId: string,
credentialType: string
}
rule.*
rule.ConditionMatched
Published once per rule whose condition AST evaluates to true for an incoming event, immediately before actions fire. Useful for rule-engine observability and for subscribers that need to react to rule matches without running actions.
Publisher: apps/hub/src/services/rules/RulesService.ts
{
ruleId: string,
ruleName: string,
ownerId: string,
triggerEventType: string, // e.g. 'communication.MessageReceived'
triggerCorrelationId: string, // correlationId of the envelope that matched
actionCount: number // how many actions the rule declared
}
rule.ActionTriggered
Published once per action inside a matched rule, after the action handler returns. Emits with outcome: 'executed' on success or outcome: 'failed' on any thrown error. An error field is included on failure.
Publisher: apps/hub/src/services/rules/RulesService.ts
{
ruleId: string,
ruleName: string,
ownerId: string,
actionType: string, // e.g. 'send.Sms' | 'tag.Person' | 'route.Call'
triggerEventType: string,
outcome: 'executed' | 'failed',
error?: string // present only on failure
}
Subscribed-Only Events
Subjects the hub listens on but does not publish itself. These are expected to be emitted by plugins (via PluginContext.publish) or external webhooks.
connector.LocationUpdated
Device location fix. ContextEngine and StreamProcessingService subscribe. Expected emitter: device connector plugin.
{
deviceId: string,
lat: number,
lon: number,
accuracyMeters: number,
altitudeMeters?: number,
wifiSsid?: string,
recordedAt: string
}
connector.DeviceEventReceived
Generic device event (call log, SMS, active app, clipboard, notification). StreamProcessingService subscribes. Expected emitter: device connector plugin.
{
deviceId: string,
eventKind: 'call_log_entry' | 'sms' | 'active_app' | 'clipboard' | 'notification',
payload: unknown
}
communication.MessageReceived
Normalized inbound message. ActivityFeedService and others subscribe. Expected emitter: Twilio / WhatsApp / MS Graph channel plugins.
{
messageId: string,
conversationId: string,
channelId: string,
channelType: string,
senderPhone: string,
senderPersonId: string | null,
body: string,
timestamp: string,
providerMessageId: string
}
communication.CallEnded
Call finished. TranscriptionService, InboxService, ContextEngine, StreamProcessingService subscribe. Expected emitter: Twilio channel plugin via status webhook.
{
callId: string,
conversationId: string,
duration_seconds: number,
outcome: 'completed' | 'no-answer' | 'busy' | 'failed' | 'voicemail',
recordingUrl: string | null,
transcriptJobId: string | null,
timestamp: string
}
data.EntityUpdated
Existing entity updated. WikiService subscribes. Expected emitter: ETL service or entity-specific domain services (currently publish domain-specific events instead).
{
entityType: string,
entityId: string,
changedFields: string[],
sourceConnectorId: string | null
}
email.Received
New email arrival. EmailAIService and PushNotificationService subscribe. Expected emitter: MS Graph connector plugin.
{
messageId: string,
threadId: string,
folderId: string,
from: { name: string, email: string },
subject: string,
snippet: string,
hasAttachments: boolean,
receivedAt: string
}
Planned Events
These schemas are documented as roadmap intent. They are not yet emitted by the hub and have no active subscribers. Do not rely on them.
connector.AuthFailed
A connector could not authenticate.
{
connectorId: string,
reason: string,
requiresUserAction: boolean
}
communication.VideoRoomCreated
Superseded in practice by video.MeetingCreated.
{
roomId: string,
providerRoomId: string,
participants: string[],
createdAt: string
}
communication.CallTransferred
{
callSid: string,
ownerId: string,
transferType: 'warm' | 'cold',
targetNumber: string,
fromNumber: string
}
communication.CallParked
{
callSid: string,
ownerId: string,
slot: number,
fromNumber: string
}
communication.CallRetrieved
{
callSid: string,
ownerId: string,
slot: number,
retrievedBy: string
}
data.EntityDeleted
{
entityType: string,
entityId: string
}
job.Enqueued
{
jobId: string,
jobType: string,
queue: 'realtime' | 'interactive' | 'background',
triggeredByEventId: string
}
job.Completed
{
jobId: string,
jobType: string,
durationMs: number
}
job.Failed
{
jobId: string,
jobType: string,
attempts: number,
lastError: string
}
ai.MeetingAnalyzed
{
analysisId: string,
meetingId: string,
ownerId: string,
sentiment: 'positive' | 'neutral' | 'negative' | null,
actionItemCount: number,
keyTopics: string[]
}
audio.DailyBriefGenerated
{
briefId: string,
ownerId: string,
date: string,
sessionCount: number
}
video.RecordingReady
{
recordingId: string,
meetingId: string,
ownerId: string,
url: string,
durationSeconds: number
}