> ## Documentation Index
> Fetch the complete documentation index at: https://memproof.kyberon.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Audit Trail

> Tamper-evident audit trail powered by Trailproof with SHA-256 hash chains

# Audit Trail

Every stage of the [control path](/concepts/control-path) emits an immutable event to the audit trail powered by [Trailproof](https://trailproof.kyberon.dev/docs/introduction). This produces a complete forensic record for every memory operation -- from the moment it is received through to its final committed or blocked state.

Trailproof provides SHA-256 hash chains, HMAC signing, query, and verification out of the box. Memproof delegates all audit trail responsibilities to Trailproof so you get tamper-evident logging without managing event storage internals.

## Event Types

Events are namespaced under `memproof.pipeline.*`:

| Event Type                             | Stage                        | Payload                  |
| -------------------------------------- | ---------------------------- | ------------------------ |
| `memproof.pipeline.received`           | Request accepted             | --                       |
| `memproof.pipeline.risk_assessed`      | Risk scoring complete        | `score`, `level`         |
| `memproof.pipeline.policy_decided`     | Policy rule matched          | `action`, `reason_codes` |
| `memproof.pipeline.approval_requested` | Sent to approval queue       | --                       |
| `memproof.pipeline.provider_attempted` | Adapter called               | --                       |
| `memproof.pipeline.committed`          | Operation succeeded          | --                       |
| `memproof.pipeline.blocked`            | Operation denied/quarantined | --                       |

## TrailEvent Structure

Each event is a Trailproof `TrailEvent` with the following fields:

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    class TrailEvent:
        event_id: str           # globally unique ID
        event_type: str         # e.g. "memproof.pipeline.received"
        timestamp: datetime     # UTC timestamp
        actor: str | None       # who triggered the event
        metadata: dict          # stage-specific data (operation_id, tenant_id, etc.)
        hash: str               # SHA-256 hash for chain integrity
        prev_hash: str | None   # hash of the previous event in the chain
        signature: str | None   # HMAC-SHA256 signature (if signing is enabled)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    interface TrailEvent {
      eventId: string;          // globally unique ID
      eventType: string;        // e.g. "memproof.pipeline.received"
      timestamp: Date;          // UTC timestamp
      actor: string | null;     // who triggered the event
      metadata: Record<string, unknown>; // stage-specific data
      hash: string;             // SHA-256 hash for chain integrity
      prevHash: string | null;  // hash of the previous event in the chain
      signature: string | null; // HMAC-SHA256 signature (if signing is enabled)
    }
    ```
  </Tab>
</Tabs>

<Note>
  The `metadata` field carries the `operation_id`, `tenant_id`, `project_id`, and any stage-specific payload. Querying by `operation_id` within metadata returns the full lifecycle trace for a single operation.
</Note>

## Storage Backends

Trailproof provides two storage backends:

<CardGroup cols={2}>
  <Card title="In-Memory Store" icon="memory">
    Default. Events are stored in memory. Fast and zero-dependency, but events are lost on process restart. Suitable for development and testing.
  </Card>

  <Card title="JSONL Store" icon="file-lines">
    Durable persistence using append-only JSONL (JSON Lines) files. Each event is written as a single line to disk. Suitable for production deployments.
  </Card>
</CardGroup>

### Configuring the Storage Backend

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    # In-memory (default)
    mp = Memproof(policy="./memproof.yaml")

    # JSONL with durable persistence
    mp = Memproof(
        policy="./memproof.yaml",
        trail_store="jsonl",
        trail_store_path="./memproof_audit.jsonl",
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    // In-memory (default)
    const mp = new Memproof({ policy: "./memproof.yaml" });

    // JSONL with durable persistence
    const mp = new Memproof({
      policy: "./memproof.yaml",
      trailStore: "jsonl",
      trailStorePath: "./memproof_audit.jsonl",
    });
    ```
  </Tab>
</Tabs>

## HMAC-SHA256 Signing

For tamper-evident audit trails, provide a signing key. Trailproof signs each event with HMAC-SHA256 and includes the signature in the `TrailEvent`:

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    mp = Memproof(
        policy="./memproof.yaml",
        trail_store="jsonl",
        trail_store_path="./memproof_audit.jsonl",
        trail_signing_key="your-secret-key",
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    const mp = new Memproof({
      policy: "./memproof.yaml",
      trailStore: "jsonl",
      trailStorePath: "./memproof_audit.jsonl",
      trailSigningKey: "your-secret-key",
    });
    ```
  </Tab>
</Tabs>

<Warning>
  In production, source the signing key from a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.) rather than hardcoding it. If the key is compromised, all signatures become untrustworthy.
</Warning>

## Hash Chain Verification

Trailproof links every event to its predecessor via SHA-256 hashes, forming an append-only chain. If any event is tampered with, the chain breaks and verification fails. Use the `verify_audit_trail()` / `verifyAuditTrail()` method to validate the entire chain:

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    result = mp.verify_audit_trail()

    if result.valid:
        print(f"Audit trail verified: {result.event_count} events")
    else:
        print(f"Tampering detected: {result.error}")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    const result = mp.verifyAuditTrail();

    if (result.valid) {
      console.log(`Audit trail verified: ${result.eventCount} events`);
    } else {
      console.log(`Tampering detected: ${result.error}`);
    }
    ```
  </Tab>
</Tabs>

<Tip>
  Run verification periodically (e.g., in a health check or scheduled job) to detect any tampering early. See [Production Hardening](/guides/production-hardening) for more guidance.
</Tip>

## Querying the Audit Trail

Use the `query_audit_trail()` / `queryAuditTrail()` method to search events with filtering:

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    events = mp.query_audit_trail(
        event_type="memproof.pipeline.committed",
        metadata={"tenant_id": "acme"},
        limit=50,
    )

    for event in events:
        print(f"{event.event_type} at {event.timestamp}")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    const events = mp.queryAuditTrail({
      eventType: "memproof.pipeline.committed",
      metadata: { tenantId: "acme" },
      limit: 50,
    });

    for (const event of events) {
      console.log(`${event.eventType} at ${event.timestamp}`);
    }
    ```
  </Tab>
</Tabs>

### Retrieving a Full Operation Trace

To get every event for a single operation in chronological order, filter by `operation_id` in the metadata:

<Tabs>
  <Tab title="Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    events = mp.query_audit_trail(
        metadata={"operation_id": "op-abc123"},
    )

    for event in events:
        print(f"{event.event_type}: {event.timestamp}")
    # memproof.pipeline.received: 2026-01-15T10:00:00+00:00
    # memproof.pipeline.risk_assessed: 2026-01-15T10:00:00.001+00:00
    # memproof.pipeline.policy_decided: 2026-01-15T10:00:00.002+00:00
    # memproof.pipeline.provider_attempted: 2026-01-15T10:00:00.003+00:00
    # memproof.pipeline.committed: 2026-01-15T10:00:00.050+00:00
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    const events = mp.queryAuditTrail({
      metadata: { operationId: "op-abc123" },
    });

    for (const event of events) {
      console.log(`${event.eventType}: ${event.timestamp}`);
    }
    // memproof.pipeline.received: 2026-01-15T10:00:00.000Z
    // memproof.pipeline.risk_assessed: 2026-01-15T10:00:00.001Z
    // memproof.pipeline.policy_decided: 2026-01-15T10:00:00.002Z
    // memproof.pipeline.provider_attempted: 2026-01-15T10:00:00.003Z
    // memproof.pipeline.committed: 2026-01-15T10:00:00.050Z
    ```
  </Tab>
</Tabs>

## Learn More

For full details on Trailproof's capabilities -- including custom stores, advanced querying, and chain semantics -- see the [Trailproof documentation](https://trailproof.kyberon.dev/docs/introduction).
