Data Governance

What governance covers

The governance system handles four concerns: consent management, data retention, conversation export, and the right to delete. It gives your app a single API surface for GDPR-style data operations without requiring you to build the plumbing yourself.

DataGovernancePolicy

Pass a governance object when creating the client:

import { createChatClient, tokenEndpointAuth } from 'gecx-chat';

const client = createChatClient({
  auth: tokenEndpointAuth({ endpoint: '/api/chat-token' }),
  governance: {
    consent: {
      initial: 'functional',
      onWithdrawn: 'clear_and_block',
    },
    retention: {
      mode: 'ttl',
      sessionTtlMs: 24 * 60 * 60 * 1000, // 24 hours
    },
    requireServerAck: {
      delete: true,
      forget: true,
    },
    export: {
      localFallback: true,
    },
    audit: (event) => console.log('governance:', event.kind, event.sessionId),
  },
});

All fields are optional. Defaults are designed to be safe: consent starts at functional, retention is session (cleared when the tab closes), and withdrawn consent clears local state and blocks further sends.

ChatGovernance methods

The client exposes governance operations through client.governance. These work across all sessions.

forgetMe({ userId, sessionIds?, reason? }): Promise<ForgetResult> -- right-to-be-forgotten. Tells the server to erase all data for the user, clears local state for every listed session, and marks those sessions as erased so further sends throw.

deleteConversation({ sessionId, reason? }): Promise<DeleteResult> -- deletes a single conversation. Stops the active stream, clears in-memory and local state, then requests server-side deletion. Returns { serverAcknowledged, localCleared, deletedAt }.

exportConversation({ sessionId, format? }): Promise<ExportBundle> -- exports conversation data. Tries the server first. If the server export fails and localFallback is enabled (the default), returns an in-memory snapshot instead. The bundle includes messages, metadata, and a source field ('server', 'local', or 'merged').

clearLocalState({ sessionId?, preserveInput? }): Promise<ClearLocalResult> -- clears local storage for a session (or all sessions if sessionId is omitted). Set preserveInput: true to keep the user's unsent draft. Returns the number of keys removed.

purgeExpired(): Promise<PurgeResult> -- removes expired entries when using TTL retention. Call this on a timer or at app startup.

updateConsent({ posture }): Promise<void> -- changes the consent posture at runtime. Emits a governance.consent_changed audit event.

revokeConsent(): Promise<void> -- withdraws consent entirely. If onWithdrawn is clear_and_block, this clears all local state and blocks further sends. If clear_only, it clears state but allows sends to resume after a new consent grant.

getConsent(): ConsentPosture -- returns the current consent posture.

SessionGovernanceFacade

Each ChatSession has a thin facade that defaults the sessionId argument. You can call governance methods on the session directly:

await session.deleteConversation({ reason: 'user requested' });
await session.exportConversation({ format: 'json' });

These are convenience wrappers around client.governance.deleteConversation(...) with the session's ID pre-filled.

PostureMeaning
noneNo consent granted. If onWithdrawn is clear_and_block, sends are blocked.
functionalConsent for core chat functionality (storage, session continuity). Default.
analyticsConsent for analytics event collection in addition to functional.
allFull consent for all SDK features.

Retention modes

ModeBehavior
sessionData cleared when the tab/session ends. Default.
ttlData expires after sessionTtlMs (per session) and historyTtlMs (conversation list). Call purgeExpired() to clean up.
foreverData persists until explicitly deleted.

Use defineRetention for readable config:

import { defineRetention } from 'gecx-chat';

governance: {
  retention: defineRetention({ mode: 'ttl', sessionTtlMs: 86_400_000 }),
}

Audit events

Every governance operation emits a typed audit event. The audit callback in the policy receives a GovernanceAuditEvent:

interface GovernanceAuditEvent {
  kind: GovernanceAuditKind;
  timestamp: string;
  actor: 'sdk';
  sessionId?: string;
  userId?: string;
  details?: Record<string, unknown>;
}

Audit event kinds include: governance.delete_requested, governance.delete_completed, governance.delete_failed, governance.export_requested, governance.export_completed, governance.export_failed, governance.forget_requested, governance.forget_completed, governance.forget_failed, governance.consent_changed, governance.local_state_cleared, governance.retention_purged.

You can also subscribe to audit events after client creation:

const unsubscribe = client.governance.on((event) => {
  sendToSIEM(event);
});

Capability permissions

Four new ConsentFlag values cover device permissions: microphone_capture, camera_capture, screen_capture, and geolocation_capture. They are managed by PermissionManager, which auto-grants the flag on capability grant and withdraws it on revoke. Two new GovernanceAuditKind values surface in the audit log: permission_granted and permission_revoked. The existing voice_recording flag is untouched — it governs retention of audio bytes (separate from capture permission).

See Permissions.

Computer-use governance

When the computer-use server tool is enabled, governance.computerUse carries the policy:

governance: {
  computerUse: {
    enabled: true,
    allowlist: ['acme-orders.example.com'],
    maxDurationMs: 5 * 60_000,
    maxActionsPerSession: 30,
    highRiskActions: ['submit_form', 'download', 'navigate_external'],
    killSwitch: false,
  },
}

Every action emits a governance.computer_use.* audit event with request-id correlation. The kill switch (killSwitch: true) plus the proxy's admin endpoint halts every session immediately. See Computer-use and the threat model.

Commerce governance (PCI / PII)

For commerce surfaces, configure governance.commerce to fail-close on PCI/PII leaks. Strict mode throws COMMERCE_PII_LEAK on PAN (Luhn-validated), CVV, SSN, email, phone, address, and EIN findings before the data can land in transcripts, debug bundles, approval surfaces, or analytics. The companion gecx validate CLI applies a static PCI lint over your source tree — comment-aware, flags Luhn-valid card literals, CVV literals, and unguarded payment-method fields. Run it in CI.

What's next

Source: docs/guides/data-governance.md