Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Audit Log

The gateway records security-relevant activity as redacted, append-only SQLite rows. Audit is used for read operations, scope denials, preview/risk decisions, paper lifecycle transitions, remote auth events, sidecar forwarding, live submit/cancel/modify and bracket lifecycle events, and reconciled live lifecycle transitions.

Storage

The SQLite schema lives under src/internal/audit/migrations/. Live order reconciliation adds a live_orders_pending backlog keyed by account id and broker order id.

SqliteAuditWriter configures WAL journaling, writes redacted payload JSON, and stores a chained HMAC hash for tamper-evidence across appended rows.

Review and Export

ibkr-agent audit tail --limit 100 --json
ibkr-agent audit tail --database-url sqlite:/path/to/audit.db --limit 100 --json
ibkr-agent audit export --database-url sqlite:/path/to/audit.db --limit 500 --json
ibkr-agent audit verify --json
ibkr-agent audit verify --database-url sqlite:/path/to/audit.db --hmac-secret-env IBKR_AUDIT_HMAC_SECRET --json

MCP clients use ibkr_audit_tail with ibkr:audit:read. CLI audit tail, audit export, and audit verify are also scope-gated by ibkr:audit:read when a runtime config is supplied, and each command appends a redacted audit event for the audit read/verification action itself.

audit verify scans the full chained HMAC log and exits with code 2 when the chain is broken. External database verification requires the original audit HMAC key through --hmac-secret-env; the runtime database uses the active CLI configuration key automatically.

Redaction

Audit payloads must not store:

  • bearer tokens;
  • cookies;
  • credentials;
  • sensitive headers;
  • local secret paths;
  • raw Client Portal Gateway session material;
  • raw account ids.

Account and token correlation use HMAC-SHA256. Free-form audit metadata is scrubbed by sensitive field name before persistence. Field-name matching is case-insensitive and substring-based, so broad markers such as path and header intentionally redact conservative matches rather than risk leaking local paths or sensitive headers.

Denied, refused, failed, and completed operations keep a consistent correlation shape so review can reconstruct what happened without exposing broker secrets.

Live Reconciliation

Successful live submits and non-terminal live modifies are added to the reconciliation backlog. The MCP stdio runtime calls reconcile_live_orders_once on the configured interval (live_trading.reconciler_interval_seconds, default 5) to poll IbkrBackend::order_status, append live_order_lifecycle_changed events on status transitions, and remove filled/cancelled/refused orders from the backlog. On startup, the runtime also rebuilds the backlog from completed live idempotency records so existing non-terminal live orders remain tracked after a restart.

The same durable live idempotency records provide server-side frequency and session counters for live submit gates. CLI and MCP submit paths overwrite the caller context counters before evaluation.