Core Concepts
What this page covers
Section titled “What this page covers”This page defines the core abstractions in LatchGate: protected actions, the execution pipeline, and the key artifacts produced at each stage. For the higher-level motivation, see the Overview. For the system diagram and crate layout, see Architecture.
Protected actions
Section titled “Protected actions”A protected action is any operation whose side effect matters outside the agent process: an HTTP call, a database write, an email, a queue publish, a file store write.
If an operation is declared as a protected action in LatchGate, its side effect cannot occur outside LatchGate’s control path. This is the core no-bypass guarantee. It applies only to declared protected actions — LatchGate does not claim to sandbox the entire host.
The execution pipeline
Section titled “The execution pipeline”Every protected action follows the same deterministic path. If any step fails, the action is denied.
Request in │ ├─ Drain guard ├─ Authentication (Lease + DPoP proof + jti replay check) ├─ Registry lookup (ActionSpec by action_id) ├─ Trust verification (provider module digest check) ├─ Input schema validation ├─ Canonicalization + request_hash (JCS / RFC 8785) ├─ Domain pre-check (non-blocking optimization — early reject for unknown domains) ├─ Budget snapshot + policy evaluation (OPA/Rego) ├─ Approval hold (if policy returns PendingApproval, HTTP 202) ├─ Budget debit (atomic — Redis Lua or SQLite exclusive lock) ├─ ExecutionGrant construction + Ed25519 signing ├─ Secret resolution + template expansion + RunTask build ├─ Grant re-validation + signature verification ├─ ExecutionIntent write (pre-dispatch evidence marker) ├─ WASM provider dispatch (fresh sandbox) ├─ Response schema validation ├─ Effect verification ├─ ExecutionReceipt construction + signing ├─ Evidence finalization (receipt + final audit, single SQLite txn) │ ▼Response outThe execution tail — grant re-validation through evidence finalization — is shared: both the auto-allow path and the human-approved path converge into it. There is exactly one WASM dispatch code path in the kernel (execute_authorized_plan) — approval and auto-allow cannot diverge at dispatch time.
Key artifacts
Section titled “Key artifacts”A short-lived JWT issued at POST /v1/leases. The lease is bound to a caller-controlled key via DPoP (RFC 9449), meaning a stolen token without the private key is useless. The caller principal is determined server-side (never client-asserted), and scopes are constrained to the intersection of what the caller requests and what the identity provider permits.
ActionSpec
Section titled “ActionSpec”The immutable, versioned definition of a protected action. It specifies the provider WASM module (by SHA-256 digest), the required I/O imports, input/output schemas, risk level, budget and approval policies, resource limits, and verifier kind. Actions are append-only once published — you create new versions, never mutate existing ones.
Most HTTP actions use the built-in http_api provider with a template manifest. The manifest declares URL pattern, method, headers, and body templates with {{variable}} placeholders. The kernel resolves them from the validated request before dispatching:
# github_create_issue — high risk, requires approvalaction_id: "github_create_issue"provider_module_digest: "builtin:http_api"template: method: POST url_template: "https://api.github.com/repos/{{owner}}/{{repo}}/issues" headers: Accept: "application/vnd.github.v3+json" body_template: title: "{{title}}" body: "{{body}}"risk_level: "high"secrets: - name: "GITHUB_TOKEN" required: trueegress: profile: "proxy_allowlist" allowed_domains: ["api.github.com"]One provider binary, many actions. http_fetch (GET, low risk, no approval), github_read (GET template), and github_create_issue (POST template, high risk, approval required) all use the same http_api WASM module — each manifest configures it differently.
ExecutionGrant
Section titled “ExecutionGrant”A short-lived authorization artifact issued by the kernel after all pre-dispatch checks pass. The grant binds the exact approved execution plan: specific targets, secrets, egress rules, budget snapshot, provider module digest, and expiry. It is Ed25519-signed immediately after construction; any field mutation between construction and dispatch is detectable via signature verification.
For approved actions, the grant additionally carries:
approved_by— operator identity, integrity-bound into the signatureoperator_binding— JWK thumbprint of the operator’s DPoP key (cryptographic proof-of-possession)approval_hash— SHA-256 over(approval_id, plan_hash)tying the grant to the exact approved plan
ExecutionIntent
Section titled “ExecutionIntent”A pre-dispatch durable evidence marker. Written to SQLite before the WASM provider dispatches. If the process crashes between dispatch and receipt write, operators can detect intents without matching receipts and investigate whether the side effect occurred.
This is the difference between “we lost evidence” (detectable) and “we lost knowledge of what happened” (invisible). LatchGate makes it the former.
ExecutionReceipt
Section titled “ExecutionReceipt”The durable result envelope. It records the grant it was issued under, what the provider returned, whether verification succeeded, and any effect evidence. Receipts are SHA-256-hashed, Ed25519-signed, and written transactionally with the final audit event. Receipts are chained via the audit event prev_hash for tamper evidence.
The client receives a success response only if the receipt + audit transaction commits. If evidence cannot be persisted, the client receives evidence_persistence_failed — never a false success.
WASM sandbox
Section titled “WASM sandbox”Every provider executes as a .wasm module in a fresh wasmtime instance. The sandbox has zero ambient capabilities: no filesystem, no network, no syscalls. The provider communicates with external systems exclusively through host-mediated I/O imports. Secrets never enter the sandbox — the host I/O layer injects credentials into outgoing requests at the transport level.
Resource consumption is bounded by:
- Fuel metering (CPU) — deterministic per-instruction cost, terminates runaway computation
- Memory caps (linear memory) — allocation attempts beyond the cap fail
- I/O call budget — per-execution limit on host import invocations
- Epoch-based wall-clock deadline — interrupts pure-computation loops that have no
.awaitpoints, enforced by a dedicated OS thread ticker (works even when the tokio runtime is blocked)
Host I/O
Section titled “Host I/O”The host I/O layer is the bridge between a sandboxed WASM provider and external systems. It enforces:
- Sink validation — every target URL/address checked against the grant’s allowlist before executing, with proper domain matching (
allowed = "api.com"does NOT matchevil-api.com) - Credential injection — secrets read from the kernel’s store, injected into outgoing requests at the transport level
- SSRF protection — private IP blocking (loopback, RFC-1918, link-local, CGNAT, IPv6 loopback/ULA, IPv4-mapped IPv6), DNS pinning via
reqwest::ClientBuilder::resolve()to close the DNS TOCTOU window while preserving TLS SNI, redirect blocking at transport - Per-call timeouts and response size limits
Available I/O interfaces (defined in WIT):
| Interface | Transport | Maturity | Example |
|---|---|---|---|
latchgate:io/http | HTTP via reqwest | v0.1 (supported) | REST APIs, webhooks |
latchgate:io/fs | Filesystem via openat2 | v0.1 (supported) | File read, write, delete |
latchgate:io/log | Structured logging | v0.1 (supported) | Provider-side logging (always allowed) |
latchgate:io/smtp | SMTP via lettre | planned for future releases | Email delivery |
latchgate:io/database | SQL via sqlx | planned for future releases | PostgreSQL queries |
latchgate:io/queue | AMQP via lapin | planned for future releases | Message publishing |
latchgate:io/storage | Object store | planned for future releases | S3, GCS, Azure Blob |
In v0.1, io/http, io/fs, and io/log are linked at runtime. The other WIT interfaces are committed for forward compatibility and will activate when their host I/O backends ship in future releases.
A provider can only use the imports declared in its action manifest. Undeclared imports cause instantiation failure at the linker. Import gating is also enforced at runtime in check_import_allowed() as defense in depth — even if the linker had all interfaces available, a provider that did not declare an interface cannot call it.
Verification
Section titled “Verification”After a provider executes, the kernel runs a verifier appropriate to the action. Verifier output is one of:
verified— the effect was independently confirmedverification_failed— the effect could not be confirmed (for high-risk actions, this denies the response)unverifiable_declared— no verifier was configured (the action explicitly opts out)provider_failed_before_verification— the provider failed before reaching a verifiable stateskipped— verifier was skipped (e.g., provider returned non-success)
LatchGate never labels an action as verified if verification did not actually happen.
Evidence ledger
Section titled “Evidence ledger”All decisions, results, and verification outcomes are recorded in an append-only, hash-chained SQLite ledger. Each event’s prev_hash is the SHA-256 of the preceding event’s JSON bytes, enabling tamper detection without a blockchain.
Receipts are Ed25519-signed with key rotation support via signing_key_id (kid). Historical verifying keys are persisted in a JWKS file so old receipts remain verifiable after rotation. The grant signing key is separate from the receipt signing key (defense-in-depth).
JSONL export is available for SIEM / WORM integration.
Northbound and southbound
Section titled “Northbound and southbound”Northbound (above LatchGate): agent runtimes, IDE agents, MCP hosts, orchestrators. They integrate via the Action API (POST /v1/actions/{id}/execute), the MCP adapter, or thin SDKs.
Southbound (below LatchGate): WASM provider modules executing in sandboxed wasmtime instances, communicating through host-mediated I/O to external systems. This is where LatchGate’s core differentiation lives.
For the system layer diagram and crate layout, see Architecture. For the full threat model, see Security Model. For built-in actions and manifests, see Actions & Manifests. For the provider sandbox model and host I/O interfaces, see WASM Providers.