Skip to content

Architecture

LoopGlitch26 edited this page Oct 20, 2026 · 1 revision

Architecture

The v2 signer's components and how evidence flows through them. The byte-level format is in format v2; what each component defends, and against whom, in the threat models (laptop, server).

flowchart LR
    subgraph clients [Clients: the agent's side]
        SDK[SDK client and framework integrations]
        Hook[Claude Code hook and transcript tailer]
        GW[LLM gateway and T2 executors]
    end
    SDK & Hook & GW -->|"Unix socket, loopback TCP or HTTPS"| Signer
    subgraph signer [Signer: tracekit signer serve]
        Signer[identity, policy, approvals] --> Writer[single writer]
    end
    Writer --> Store[(store: files or Postgres)]
    Store --> CP[checkpoints]
    CP --> Wit[witnesses]
    CP --> Rekor[Rekor + RFC 3161 anchors]
    Store --> Mon[monitor]
    Store --> Bundle[".tkb bundle"]
    Wit & Rekor & Mon -.-> Bundle
    Bundle --> Verify["tracekit verify + trust config"]
Loading

Clients

Everything that reports to the signer, none of it trusted: the SDK client (tracekit.sdk.client) and the framework integrations built on it (tracekit/integrations/, quickstarts), the Claude Code hook and the transcript tailer (tracekit.integrations.claude_code, tracekit.tailer; the tailer reports every prompt and model line, which tracekit analyze --v2 reads back from the content vault to compare what was asked, said and done; the hook also records each prompt as the harness submitted it, so a prompt line the agent writes into its own transcript stands out, and sends the constraints it states as live constraints), and the out-of-process recorders: the LLM gateway and T2 executors (approvals). A client registers a run, asks the signer to decide each tool call before it runs and reports it complete after. Clients hold a run token, never a signing key.

The tier of a record says where it came from: T1 in-process (hooks, adapters), T2 out-of-process (gateways, executors), T3 imported telemetry (OpenTelemetry).

Signer

tracekit signer serve (tracekit/signer/service.py), one program in every deployment mode.

  • Transport and identity (tracekit/transport/, tracekit/identity/): a Unix socket with the peer's uid, loopback TCP with a token (Windows dev), or HTTPS with Kubernetes service-account tokens, mTLS (SPIFFE) or named tokens. The signer's config maps each identity to a tenant and the calls it may make; the isolation it records comes from the transport, never from the client.
  • Policy (tracekit/policy2/): rules over the raw arguments, evaluated with the signer's own tool classes; allow, deny or ask (policy reference). An ask waits for an approval bound to the exact arguments, from an approver the config names (approvals).
  • Single writer (tracekit/signer/pipeline.py): one thread assigns every sequence number and previous hash, signs the record and appends it in a batch. A refused or failed write leaves no state; outages, lost transcripts and witness failures become signed gaps.
  • Keys (tracekit/signer/logkey.py, signing): a stable log key signs checkpoints (a file key or AWS KMS); record keys can be short-lived and certified by the issuer.

Store and checkpoints

The store (tracekit/storage/: files with fsync, or Postgres) holds the records and their Merkle tree as tiles (tracekit/merkle/). The signer periodically signs a checkpoint of the tree: a C2SP signed note of its size and root (tracekit/format/checkpoint.py), optionally hybrid with SLH-DSA.

Witnesses, anchors and the monitor

  • Witnesses (tracekit/tlog_witness.py, witnesses) cosign each checkpoint after checking it is consistent with the last one they saw, so a rewritten or forked log can't get a cosignature.
  • Anchors (tracekit/anchor/): Rekor v2 entries and RFC 3161 timestamps of a checkpoint, for an outside time.
  • The monitor (tracekit monitor, monitor) follows the log from outside and checks what witnesses can't (log and run chains, key records, that every run has its registry leaf, rollbacks and forks), and signs a report.

Analyzers and findings runs

tracekit analyze --v2 and tracekit why are operator tools, not the agent's clients. They run as an identity signer.yaml analyzers lists, read a finished run (its records and, with the content_read grant, the content vault, each read a signed content.accessed), and write what they found into a findings run of their own: register_run with analyzes: <run id>, which the signer allows only an analyzers identity, for a run of its tenant that is not itself a findings or replay run. Nothing is written into the analysed run. review_finding signs each finding as a review record that cites records of the analysed run by run_seq and hash; its closed schema keeps text of the run (excerpts, paths, reasons) out of signed records, which can't be erased. The finding's author is the identity the signer measured when the findings run registered. tracekit export --v2 --run R --with-findings bundles a run with its findings runs; the verifier checks each citation and labels the author (verdicts), and prints the findings on a Findings: line of their own: an opinion of the run, never part of its integrity. The analyzer's effect checks (TK-X206, TK-X207, tracekit/findings_effects.py) join each kernel sensor effect to the call that explains it, by the call the process names, the process that started it, or the call's window on the signer's clock, and flag what none explains and calls that caused nothing the sensor saw (findings).

Live constraints go the other way: a limit the person's request states ("don't touch billing.py", "don't push") is sent by the hook as constraint_add and kept in the run's state (a constraint.added record holds the kind and a commitment to the file name). After its policy, the signer raises a later call of the run that breaks one to an ask (TK-CONSTRAINT), never lowering a decision, so prevention needs no trust in whoever added the constraint.

Bundles and the verifier

tracekit export --v2 (tracekit/bundle_v2.py) writes one run, or a tenant's run-set, as a .tkb: the records, inclusion proofs into a checkpoint, its Rekor and timestamp anchors, and the policy snapshots its agent approvals and incidents are checked against. It holds no verification code.

tracekit verify (tracekit/verify/v2.py) checks it offline against a trust config the verifier brings: the pinned log keys, witnesses and their quorum, optionally a monitor, and the analyzers whose findings it takes as independent. Nothing in the bundle is trusted for that. The report gives Integrity (are these the signed records) and Assurance (who vouches for the checkpoint) (verdicts, auditor guide). v1 bundles go to the frozen v1 verifier (tracekit/verify/v1.py).

The v1 signer

The laptop signer tracekitd (tracekit/daemon.py, tracekit/ledger.py) and its hooks still ship: one JSONL hash chain per machine, checkpointed to git or file witnesses, verified with tracekit verify --key. tracekit signer bridge continues a v1 ledger into a v2 log (migration).

Home

Get started

How it works

Integrations

Policy and approvals

Deploy and operate

Verify the evidence

Security and privacy

Compliance

Evaluation

Demos

Help

Clone this wiki locally