Skip to content

Audit Event Schema

Purpose: Define all audit event types with payload schemas for sequence mapping and validation.


Base Event Schema

All events extend this base:

interface BaseAuditEvent {
  id: string;                    // UUID
  sequence: number;              // Monotonic, no gaps
  timestamp: string;             // ISO 8601
  previousHash: string;          // Hash of previous event
  hash: string;                  // Hash of this event (excluding hash field)
  signature: string;             // Service key signature

  // Context
  type: EventType;               // Event type (see below)
  resourceType: 'vault' | 'document' | 'trigger' | 'access_grant';
  resourceId: string;            // UUID of affected resource

  // Attribution
  actor: {
    type: 'user' | 'system' | 'trigger' | 'executor';
    id: string;                  // User ID or 'system'
    ip?: string;                 // Client IP if user-initiated
  };
}

Event Types by Category

Trigger Lifecycle Events

trigger_created

{
  type: 'trigger_created',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    vaultId: string,
    triggerType: 'dead_man_switch' | 'scheduled' | 'death_verification',
    config: {
      checkInInterval?: number,    // ms
      gracePeriod?: number,        // ms
      challengeWindow?: number,    // ms
      abortWindow?: number,        // ms
      scheduledDate?: string,      // ISO 8601
    },
    initialState: 'draft',
  }
}

trigger_armed

{
  type: 'trigger_armed',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'draft',
    newState: 'armed',
    nextCheckInDue: string,        // ISO 8601
    executorId: string,
  }
}

trigger_updated

{
  type: 'trigger_updated',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    updatedFields: string[],       // ['checkInInterval', 'gracePeriod', etc.]
    previousConfig: object,        // Snapshot of changed fields before
    newConfig: object,             // Snapshot of changed fields after
    updatedBy: string,             // User ID
  }
}

trigger_disarmed

{
  type: 'trigger_disarmed',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'armed',
    newState: 'draft',
    disarmedBy: string,            // User ID
    reason?: string,               // Optional user-provided reason
  }
}

check_in_recorded

{
  type: 'check_in_recorded',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    checkInMethod: 'web' | 'email_link' | 'sms' | 'app',
    previousCheckIn: string | null,  // ISO 8601
    nextCheckInDue: string,          // ISO 8601
    signalCount: 0,                  // Reset to 0
  }
}

check_in_missed

{
  type: 'check_in_missed',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    expectedBy: string,              // ISO 8601
    missedAt: string,                // ISO 8601
    signalCount: number,             // Incremented (1)
    triggerState: 'armed',           // Still armed, not triggered yet
  }
}

reminder_sent

{
  type: 'reminder_sent',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    channel: 'email' | 'sms' | 'push',
    recipient: string,               // Masked email/phone
    reminderType: 'check_in_reminder' | 'challenge_notification' | 'final_warning',
    expiresAt: string,               // ISO 8601 (when reminder link expires)
  }
}

reminder_acknowledged

{
  type: 'reminder_acknowledged',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    channel: 'email' | 'sms' | 'push',
    acknowledgedAt: string,          // ISO 8601
    signalCount: 0,                  // Reset
    triggerState: 'armed',           // Back to normal armed state
  }
}

reminder_unacknowledged

{
  type: 'reminder_unacknowledged',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    channel: 'email' | 'sms' | 'push',
    sentAt: string,                  // ISO 8601
    expiredAt: string,               // ISO 8601
    signalCount: number,             // Incremented (2)
  }
}

secondary_signal_confirmed

{
  type: 'secondary_signal_confirmed',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    signalType: 'sms_failed' | 'contact_confirmed' | 'email_bounced',
    signalCount: number,             // Current count (2+)
    details: string,                 // Human-readable description
  }
}

trigger_fired

{
  type: 'trigger_fired',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'armed',
    newState: 'triggered',
    signalCount: number,             // Must be >= 2
    signals: string[],               // List of signal types that fired
    challengeWindowEnds: string,     // ISO 8601
  }
}

challenge_window_started

{
  type: 'challenge_window_started',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    windowDuration: number,          // ms
    expiresAt: string,               // ISO 8601
    notificationsSent: string[],     // ['email', 'sms']
  }
}

challenge_window_elapsed

{
  type: 'challenge_window_elapsed',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'triggered',
    newState: 'pending_execution',
    startedAt: string,               // ISO 8601
    elapsedAt: string,               // ISO 8601
    abortWindowEnds: string,         // ISO 8601
  }
}

abort_requested

{
  type: 'abort_requested',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    requestedBy: string,             // User ID
    requestMethod: 'web' | 'email_link' | 'sms' | 'support_call',
    previousState: 'armed' | 'triggered' | 'pending_execution',
    verificationMethod: 'password' | 'mfa' | 'security_questions',
  }
}

trigger_aborted

{
  type: 'trigger_aborted',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'armed' | 'triggered' | 'pending_execution',
    newState: 'aborted',
    abortedBy: string,               // User ID
    reason: string,                  // User-provided or system
  }
}

execution_started

{
  type: 'execution_started',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'pending_execution',
    newState: 'executing',
    documentsToRelease: string[],    // Document IDs
    executorId: string,
  }
}

access_granted

{
  type: 'access_granted',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    executorId: string,
    documentIds: string[],
    accessType: 'download' | 'view',
    expiresAt: string,               // ISO 8601 (link expiry)
  }
}

executor_notified

{
  type: 'executor_notified',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    executorId: string,
    channel: 'email' | 'sms',
    recipient: string,               // Masked
    includesAccessLink: boolean,
  }
}

execution_completed

{
  type: 'execution_completed',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'executing',
    newState: 'released',
    documentsReleased: number,
    executorAccessGranted: boolean,
  }
}

trigger_released

{
  type: 'trigger_released',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    releasedAt: string,              // ISO 8601
    reversalWindowEnds: string,      // ISO 8601 (7 days)
    accessLinkExpiry: string,        // ISO 8601
  }
}

trigger_finalized

{
  type: 'trigger_finalized',
  resourceType: 'trigger',
  resourceId: string,
  payload: {
    previousState: 'released',
    newState: 'finalized',
    finalizedAt: string,             // ISO 8601
    reversalWindowElapsed: boolean,
    archiveLocation?: string,        // If archived
  }
}

Document Events

document_uploaded

{
  type: 'document_uploaded',
  resourceType: 'document',
  resourceId: string,
  payload: {
    vaultId: string,
    encryptionClass: 'A' | 'B' | 'C',
    filename: string,                // Original filename (Class A metadata)
    mimeType: string,
    sizeBytes: number,
    checksumSha256: string,          // Of ciphertext
    clientEncrypted: boolean,        // true for B/C
  }
}

document_downloaded

{
  type: 'document_downloaded',
  resourceType: 'document',
  resourceId: string,
  payload: {
    downloadedBy: string,            // User ID or executor ID
    downloadType: 'owner_access' | 'executor_access' | 'recovery_access',
    triggerId?: string,              // If executor access
    contentDelivered: 'ciphertext' | 'plaintext',  // C = always ciphertext
  }
}

document_deleted

{
  type: 'document_deleted',
  resourceType: 'document',
  resourceId: string,
  payload: {
    vaultId: string,
    deletedBy: string,               // User ID
    reason?: string,
    softDelete: boolean,             // Tombstone vs permanent
  }
}

document_version_created

{
  type: 'document_version_created',
  resourceType: 'document',
  resourceId: string,
  payload: {
    vaultId: string,
    versionNumber: number,           // Sequential version
    previousVersionId: string | null,
    encryptionClass: 'A' | 'B' | 'C',
    sizeBytes: number,
    checksumSha256: string,          // Of new ciphertext
    changeType: 'update' | 'restore',
  }
}

Vault Events

vault_created

{
  type: 'vault_created',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    ownerId: string,
    vaultType: 'witness' | 'estate' | 'exit' | 'legacy',
    defaultEncryptionClass: 'B' | 'C',
  }
}

executor_assigned

{
  type: 'executor_assigned',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    executorId: string,
    executorEmail: string,           // Masked
    assignedBy: string,              // User ID
    permissions: string[],           // ['download', 'view_metadata']
    notificationSent: boolean,
  }
}

executor_removed

{
  type: 'executor_removed',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    executorId: string,
    removedBy: string,               // User ID
    reason?: string,
  }
}

vault_updated

{
  type: 'vault_updated',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    updatedFields: string[],         // ['name', 'defaultEncryptionClass', etc.]
    previousValues: object,          // Snapshot before
    newValues: object,               // Snapshot after
    updatedBy: string,               // User ID
  }
}

vault_deleted

{
  type: 'vault_deleted',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    deletedBy: string,               // User ID
    documentCount: number,           // Documents affected
    triggerCount: number,            // Triggers affected
    softDelete: boolean,             // Tombstone vs permanent
    retentionDays?: number,          // Days before permanent deletion
  }
}

Encryption Events

master_key_unwrapped

Vault-level event: Logged when master key is retrieved for trigger execution

This event is logged BEFORE any document decryption occurs. It records how and why the vault's master key was obtained.

{
  type: 'master_key_unwrapped',
  resourceType: 'vault',
  resourceId: string,                // Vault ID
  payload: {
    triggerId: string,               // Trigger that initiated unwrap
    keySource: 'server_escrow' | 'quorum_shares' | 'user_password',
    // Phase 0.5: always 'server_escrow'
    // Phase 1+: 'quorum_shares' if M-of-N recovery used
    escrowMethod: 'sealed_secret' | 'hsm' | 'shamir_combine',
    sharesUsed?: number,             // Only for quorum mode
    sharesRequired?: number,         // Only for quorum mode
  }
}

class_b_decryption

Document-level event: Logged for EACH document decrypted

CRITICAL: Must only appear inside trigger execution handler, AFTER master_key_unwrapped.

{
  type: 'class_b_decryption',
  resourceType: 'document',
  resourceId: string,                // Document ID
  payload: {
    triggerId: string,               // REQUIRED
    vaultId: string,                 // Parent vault
    reason: 'trigger_execution',     // Only valid reason
    jurisdiction: {
      country: string,
      state?: string,
      legalNotes?: string,
    },
    decryptedFor: 'executor_delivery' | 'pdf_generation',
    keySource: 'server_escrow' | 'quorum_shares',  // Must match master_key_unwrapped
  }
}

Expected sequence for Class B release:

1. master_key_unwrapped (vault-level, once)
2. class_b_decryption (document-level, per document)
3. class_b_decryption (document-level, per document)
...

class_c_document_released

Note: No content fields - ciphertext delivery only

{
  type: 'class_c_document_released',
  resourceType: 'document',
  resourceId: string,
  payload: {
    triggerId: string,
    executorId: string,
    deliveryMethod: 'download_link',
    contentType: 'ciphertext_only',  // Always ciphertext
    accessLinkExpiry: string,        // ISO 8601
    // NO content, NO decryption key, NO plaintext reference
  }
}

encryption_class_violation_attempt

Security event - always logged, always blocked

{
  type: 'encryption_class_violation_attempt',
  resourceType: 'document',
  resourceId: string,
  payload: {
    encryptionClass: 'A' | 'B' | 'C',
    attemptedOperation: string,      // e.g., 'decrypt', 'generatePDF'
    blockedBy: 'middleware' | 'runtime_check',
    codeLocation: string,            // File:line for debugging
    severity: 'critical',
  }
}

Access Events

{
  type: 'access_link_generated',
  resourceType: 'document',
  resourceId: string,
  payload: {
    linkId: string,                  // UUID
    generatedFor: string,            // Executor ID
    expiresAt: string,               // ISO 8601
    maxUses: number,                 // Usually 1
    documentsIncluded: string[],     // Document IDs
  }
}
{
  type: 'access_link_used',
  resourceType: 'document',
  resourceId: string,
  payload: {
    linkId: string,
    usedBy: string,                  // Executor ID
    usedAt: string,                  // ISO 8601
    remainingUses: number,
    downloadedDocuments: string[],
  }
}

access_denied

{
  type: 'access_denied',
  resourceType: 'document',
  resourceId: string,
  payload: {
    attemptedBy: string,             // User/executor ID
    reason: 'not_released' | 'link_expired' | 'unauthorized' | 'max_uses_exceeded',
    triggerState?: string,           // Current trigger state
  }
}
{
  type: 'access_link_expired',
  resourceType: 'document',
  resourceId: string,
  payload: {
    linkId: string,                  // UUID
    generatedFor: string,            // Executor ID
    generatedAt: string,             // ISO 8601
    expiredAt: string,               // ISO 8601
    wasUsed: boolean,                // Whether link was ever used
    usageCount: number,              // Times used before expiry
  }
}

Recovery Events

recovery_requested

{
  type: 'recovery_requested',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    requestedBy: string,             // User ID or system
    recoveryType: 'password_lost' | 'executor_recovery',
    contactsNotified: number,        // M-of-N contacts
    threshold: number,               // Required shares
    expiresAt: string,               // ISO 8601
  }
}

recovery_share_submitted

{
  type: 'recovery_share_submitted',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    recoveryRequestId: string,
    submittedBy: string,             // Contact ID
    shareIndex: number,              // Which share (1-N)
    sharesCollected: number,         // Current count
    thresholdMet: boolean,
  }
}

recovery_completed

{
  type: 'recovery_completed',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    recoveryRequestId: string,
    completedAt: string,             // ISO 8601
    sharesUsed: number,
    newKeyWrapped: boolean,          // User set new password
  }
}

recovery_cancelled

{
  type: 'recovery_cancelled',
  resourceType: 'vault',
  resourceId: string,
  payload: {
    recoveryRequestId: string,
    cancelledBy: string,             // User ID, contact ID, or 'system'
    cancelledAt: string,             // ISO 8601
    reason: 'user_request' | 'timeout' | 'owner_login' | 'suspicious_activity',
    sharesCollectedAtCancellation: number,
  }
}

Expected Event Sequences

North Star Test: Happy Path (Steps 1-5)

1. Setup:
   vault_created
   document_uploaded
   executor_assigned
   trigger_created
   trigger_armed

2. Check-in Missed:
   check_in_missed
   reminder_sent

3. Reminder Ignored:
   reminder_unacknowledged
   trigger_fired
   challenge_window_started
   reminder_sent (challenge notification)

4. Challenge Window Passes:
   challenge_window_elapsed
   reminder_sent (final warning)

5. Execution:
   execution_started
   [master_key_unwrapped + class_b_decryption] OR [class_c_document_released]  // Based on class
   access_granted
   access_link_generated
   executor_notified
   execution_completed
   trigger_released

North Star Test: Abort Path (Step 6)

1-3. (Same as happy path through trigger_fired)

4. User Aborts:
   abort_requested
   trigger_aborted

(No execution_started, no access_granted, no executor_notified)

Class C vs Class B Divergence (Step 5)

Class B:

execution_started
master_key_unwrapped (keySource: server_escrow, escrowMethod: sealed_secret)
class_b_decryption (reason: trigger_execution, keySource: server_escrow)  // Per document
access_granted
access_link_generated
executor_notified
execution_completed

Class C:

execution_started
class_c_document_released (contentType: ciphertext_only)
access_granted
access_link_generated
executor_notified
execution_completed

Key difference: Class C has NO class_b_decryption event. If one appears for a Class C document, the test fails.


This schema defines all audit events. Use for sequence assertions in integration tests.