Repository navigation
Identity
Experimental: this works and is tested, but may change and gets less hardening than the stable core.
The signer's HTTPS transport (http in signer.yaml, tracekit/transport/http.py) establishes who calls it with one of
its authenticators: k8s_sa (Kubernetes service-account tokens), mtls (SPIFFE client certificates), token
(bearer secrets) and oidc (OpenID Connect tokens of the issuers you configure). An identity proves the workload or
person that calls, not the tenant or the end user a run acts for: those are attested only from inputs the signer can
verify, and labelled app-asserted otherwise.
http:
listen: 0.0.0.0:8443
cert: tls/server.crt
key: tls/server.key
authenticators: [oidc, k8s_sa] # oidc passes on a JWT whose issuer it does not know
oidc:
corp: # issuer alias
issuer: https://login.corp.example
audience: tracekit-signer
discovery: https://... # default <issuer>/.well-known/openid-configuration
ca: corp-ca.pem # default: the system CAs
person_claim: email # the stable person id (default sub); with email, tokens need email_verified: true
person_ns: corp # person ids are <person_ns>/<claim>; issuers that share it share people
groups_claim: groups # default groups
tenant_claim: tenant # optional: the identity's tenantA token is accepted when it is a JWT signed with RS256, ES256 or EdDSA under a kid of its issuer's JWKS, and its
iss is the pinned issuer, its aud the audience, and exp and nbf hold within 30 s. alg: none, HMAC algorithms,
a missing or unknown kid and a key of another algorithm than the header names are refused. The discovery document's
issuer must be the pinned one and its jwks_uri HTTPS. Keys are cached for 5 minutes, fetched again for an unknown
kid at most every 30 s (so a rotated key is picked up), and no longer trusted once a fetch has not succeeded for an
hour.
An OIDC token gives the identity oidc:<alias>/<sub> with:
- a person id
<person_ns>/<person_claim>: two tokens with the same person id are the same person, whatever their subjects (aliases), for every self-approval and requester check; - groups
<alias>/<name>; - a tenant, from
tenant_claim, whentenantsdoes not name one.
tenants, authorize and approvals match an OIDC identity by oidc:<alias>/<sub>, person:<person id> and
group:<alias>/<name> (exact, or a prefix ending in :* or /*):
authorize: {"group:corp/agents": [register_run, decide, approval_consume, complete, close_run, model_event,
approval_request, approval_wait, status], # + approval_list: TypeScript adapters
"group:corp/approvers": [approval_list, approval_get, approval_decide]}
approvals: {self_approval: deny, approvers: ["group:corp/approvers", "person:corp/ann@corp.example"],
break_glass: ["group:corp/oncall"]}register_run takes principal (app-asserted: recorded with principal_attested: false) or principal_token, the
end user's ID or access token for one of the oidc issuers. The signer checks the token as above and records the
user's person id as the run's principal with principal_attested: true; the token itself is never recorded. The
oidc section checks principal tokens also when oidc is not among the authenticators.
tracekit verify reports each run's principal as attested or app-asserted.
Approvals are answered with approval_decide over the RPC by an authenticated identity (approvals.md).
With OIDC: an approver is named by person id or group; the requester and the run's owner (and their aliases) answer
only with self_approval: allow; the run's attested principal never answers its run's approvals, as an approver or
under break glass; break glass (by group) needs a reason and is recorded break_glass. The approval record carries the
approver's identity with its person id.
tracekit view --config signer.yaml signs people in with one of the http.oidc issuers when the config has a view
section:
view:
oidc:
issuer: corp # an alias of http.oidc
client_id: tracekit-viewer # the ID token's audience
client_secret_file: viewer-secret # optional: a confidential client
redirect_uri: https://view.corp.example/callback
roles: {auditor: ["group:corp/auditors"], approver: ["group:corp/approvers"], operator-admin: ["group:corp/sre"]}
signer: https://signer.corp.example:8443 # optional: approval pages for approvers/login starts an authorization code flow with PKCE (S256), a state held in a login cookie and a nonce;
/callback exchanges the code, checks the ID token and opens a server-side session (a random HttpOnly; SameSite=Strict cookie, 8 hours). An auditor or approver needs the issuer's tenant claim and sees, read-only, the runs
of that tenant only; an operator-admin sees every tenant's, read-only, and answers no approval. A person in several roles
is an approver first, then an operator-admin. A central viewer (view.logs) reads every log: viewer.md. With view.signer, an approver (a person in both roles is an approver) also answers that
tenant's approvals at /approvals (approvals.md). The token URL the viewer prints
keeps working for the laptop. The viewer serves the redirect_uri host name besides its own; off loopback it needs
--tls-cert and --tls-key (security-checklist.md).
Generated from docs/ at v1.4.1. Edit the docs in the repository, not here.
Get started
- Quickstart: the v2 signer
- Quickstarts
- Quickstart: Claude Agent SDK
- Quickstart: a custom agent
- Quickstart: LangChain and LangGraph
- Quickstart: MCP client
- Quickstart: OpenAI Agents SDK
- Coding agents other than Claude Code
- tracekit doctor
- Walkthrough: Tracekit end to end
How it works
- How Tracekit works
- Overview
- The life of a tool call
- The evidence format
- Verification and assurance
- Witnesses and monitoring
- Policy
- Approvals
- Detection and containment
- Capture and completeness
- Custody
- Provenance and tracekit why
- Deployment and isolation
- Storage, durability and performance
- Integrations
- Security model
- Architecture
- tracekit why: architecture
Integrations
- Integrations
- Adapters
- OpenTelemetry
- Remote clients
- Kubernetes agent-sandbox
- agentgateway
- agentsh and Tracekit
- Browser Use
- Claude Agent SDK
- Claude Code's sandbox
- Codex's sandbox
- CrewAI
- Docker MCP Gateway
- E2B
- Falco
- Gemini CLI's sandbox
- Google ADK
- Haystack
- LangChain v1
- LiteLLM
- LlamaIndex
- MCP client
- microsandbox
- Microsoft Agent Framework
- OpenAI Agents SDK
- NVIDIA OpenShell
- Pydantic AI
- sandbox-runtime's proxy on its own
- Strands Agents
- Tetragon
- Vercel AI SDK
- Wassette
Policy and approvals
- Policy reference
- Approvals
- Findings
- Reading the model's reasoning
- Incidents and containment
- Webhooks
Deploy and operate
- Deploying the signer
- The signer as a container
- The signer on Kubernetes
- The compose stack
- Identity
- Tool executor
- MCP gateway
- LLM gateway
- Egress observation
- Witnesses
- Log monitor
- Record-key issuer
- Signer observability
- Viewer
- tracekit why: causal investigation and replay
- Migrating
- Platforms
Verify the evidence
- Reading a v2 verify report
- Evidence format v2
- Auditor guide
- Sample evidence bundle
- Signing
- What Tracekit guarantees
Security and privacy
- Threat model: the v2 signer
- Threat model: the v1 laptop signer
- HTTP security checklist
- Threat-model review packet
- Privacy
- Known limits and trade-offs
- What's stable
Compliance
- Compliance mapping
- EU AI Act
- ISO/IEC 42001
- NIST AI RMF and the Generative AI Profile
- OWASP Top 10 lists for LLM and agentic applications
Evaluation
Demos
- Demos
- Agent approvers within bounds
- Completeness and tamper evidence
- Detection and containment
- Network coverage: an egress observer
- Guardrails: allow, deny, or ask a person
- MCP tools, gated and recorded
- Prompt injection held by provenance
- Why: which input caused the action
Help