PRIV ProtocolPRIV Docs
Compliance SDK

Audit Log

API reference for the AuditLog class - immutable logging of all consent events for GDPR compliance.

Audit Log

The AuditLog maintains an immutable record of all consent-related events, essential for GDPR compliance audits.


Initialization

import { AuditLog, createAuditLog } from '@priv/compliance-sdk';

// Using class
const audit = new AuditLog({
  siteId: 'your-site-id',
  api: {
    endpoint: 'https://api.priv.io/v1',
    apiKey: 'your-api-key',
  },
});

// Using factory function
const audit = createAuditLog({
  siteId: 'your-site-id',
});

Configuration

AuditLogConfig

interface AuditLogConfig {
  /** Unique site identifier (required) */
  siteId: string;

  /** API configuration for server sync */
  api?: {
    endpoint: string;
    apiKey: string;
    timeout?: number; // Default: 5000ms
  };

  /** Max entries stored locally */
  maxLocalEntries?: number; // Default: 1000

  /** Entries before auto-flush to API */
  batchSize?: number; // Default: 50

  /** Flush interval in milliseconds */
  flushInterval?: number; // Default: 30000 (30s)

  /** Capture user agent string */
  captureUserAgent?: boolean; // Default: true
}

Audit Actions

The SDK tracks these audit actions:

ActionDescription
consent_givenUser gives initial consent
consent_updatedUser updates consent preferences
consent_revokedUser revokes all consent
banner_shownConsent banner displayed
banner_closedBanner dismissed without action
preferences_openedPreferences modal opened
dsar_requestedData subject request created
dsar_completedData subject request fulfilled
data_exportedUser data exported
data_deletedUser data deleted

Methods

log(action, data?)

Log a generic audit event.

await audit.log('consent_given', {
  userIdHash: 'abc123...',
  categories: {
    analytics: true,
    marketing: false,
  },
  metadata: {
    source: 'banner',
  },
});

Parameters:

NameTypeDescription
actionAuditActionType of action
dataPartial<AuditLogEntry>Additional data

Returns: Promise<void>


Convenience Methods

// Log consent given
await audit.logConsentGiven('user-hash', {
  analytics: true,
  marketing: true,
});

// Log consent updated
await audit.logConsentUpdated('user-hash', {
  marketing: false,
});

// Log consent revoked
await audit.logConsentRevoked('user-hash');

// Log banner events
await audit.logBannerShown();
await audit.logBannerClosed();
await audit.logPreferencesOpened();

// Log DSAR events
await audit.logDSARRequested('user-hash', 'access', 'request-123');
await audit.logDSARCompleted('user-hash', 'access', 'request-123');

getLocalEntries()

Get all locally stored audit entries.

const entries = audit.getLocalEntries();

entries.forEach((entry) => {
  console.log(`${entry.timestamp}: ${entry.action}`);
});

Returns: ReadonlyArray<AuditLogEntry>


getEntriesForUser(userIdHash)

Get audit entries for a specific user.

const userEntries = audit.getEntriesForUser('abc123...');

console.log(`User has ${userEntries.length} audit entries`);

Parameters:

NameTypeDescription
userIdHashstringUser identifier hash

Returns: ReadonlyArray<AuditLogEntry>


flush()

Immediately send pending entries to the API.

// Force sync to server
await audit.flush();

Returns: Promise<void>

Useful for:

  • Before page unload
  • After critical consent events
  • Periodic manual sync

clear()

Clear all local audit entries.

// Clear local storage
audit.clear();

Returns: void

Warning: This only clears local storage. Entries already synced to the API are preserved.


export()

Export audit log as JSON string.

const jsonString = audit.export();

// Parse for processing
const data = JSON.parse(jsonString);
console.log(`Exported ${data.entries.length} entries`);

Returns: string

Export format:

{
  "exportedAt": 1706000000000,
  "siteId": "your-site-id",
  "entries": [
    {
      "id": "abc123",
      "timestamp": 1706000000000,
      "action": "consent_given",
      "userIdHash": "def456...",
      "categories": { "analytics": true },
      "userAgent": "Mozilla/5.0..."
    }
  ]
}

exportAsBlob()

Export as a downloadable Blob.

const blob = audit.exportAsBlob();

// Trigger download
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'audit-log.json';
a.click();
URL.revokeObjectURL(url);

Returns: Blob


setUserIdHash(hash)

Set the user ID hash for this session.

// Called automatically when connected to ConsentManager
audit.setUserIdHash('abc123...');

Parameters:

NameTypeDescription
hashstringUser identifier hash

Returns: void


destroy()

Clean up resources and flush pending entries.

// Before cleanup
audit.destroy();

Returns: void


Audit Log Entry

Each entry contains:

interface AuditLogEntry {
  /** Unique entry ID */
  id: string;

  /** Unix timestamp */
  timestamp: number;

  /** Action type */
  action: AuditAction;

  /** Hashed user identifier */
  userIdHash: string;

  /** Site identifier */
  siteId: string;

  /** Consent categories (for consent events) */
  categories?: Partial<ConsentState>;

  /** Additional metadata */
  metadata?: Record<string, unknown>;

  /** User agent (truncated) */
  userAgent?: string;

  /** Hashed IP address (from API) */
  ipHash?: string;
}

The audit log automatically tracks consent events when connected:

import { ConsentManager, AuditLog } from '@priv/compliance-sdk';

const audit = new AuditLog({ siteId: 'my-site' });
const consent = new ConsentManager({ siteId: 'my-site' });

// Connect audit log to consent manager
consent.onConsentChange((prefs) => {
  audit.setUserIdHash(prefs.userIdHash);
});

Or use the full SDK which handles this automatically:

import { init } from '@priv/compliance-sdk';

// Audit log is automatically connected
const priv = init({
  siteId: 'my-site',
});

// Access audit log
const entries = priv.audit.getLocalEntries();

Example: Export for Compliance

// Generate compliance report
function generateComplianceReport() {
  const entries = audit.getLocalEntries();

  const report = {
    generatedAt: new Date().toISOString(),
    totalEvents: entries.length,
    consentEvents: entries.filter((e) =>
      ['consent_given', 'consent_updated', 'consent_revoked'].includes(e.action)
    ).length,
    dsarEvents: entries.filter((e) =>
      e.action.startsWith('dsar_')
    ).length,
    entries: entries.map((e) => ({
      date: new Date(e.timestamp).toISOString(),
      action: e.action,
      userIdHash: e.userIdHash.slice(0, 8) + '...',
    })),
  };

  return report;
}

// Export as file
function downloadReport() {
  const report = generateComplianceReport();
  const blob = new Blob([JSON.stringify(report, null, 2)], {
    type: 'application/json',
  });

  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `compliance-report-${Date.now()}.json`;
  a.click();
  URL.revokeObjectURL(url);
}

Type Definitions

/** Auditable action types */
type AuditAction =
  | 'consent_given'
  | 'consent_updated'
  | 'consent_revoked'
  | 'banner_shown'
  | 'banner_closed'
  | 'preferences_opened'
  | 'dsar_requested'
  | 'dsar_completed'
  | 'data_exported'
  | 'data_deleted';

/** Audit log interface */
interface IAuditLog {
  log(action: AuditAction, data?: Partial<AuditLogEntry>): Promise<void>;
  getLocalEntries(): ReadonlyArray<AuditLogEntry>;
  flush(): Promise<void>;
  clear(): void;
  export(): string;
}

Next Steps