Lattice Security Model
Execution Engine of our Agentic Operating System
Last Updated: May 8, 2026 | Version 1.0
Overview
Lattice is the execution engine of our agentic operating system. It currently uses a basic delegated signing model with two separate trust concerns:
- Action registration authority
- Invocation authenticity
The goal of the current model is not full production-grade isolation. The goal is to provide a simple first layer of security so that:
- Only trusted Lattice-key holders can register actions.
- Only Lattice-signed requests can invoke actions.
- Actions can verify invocations using the Lattice public key.
- The action surface does not need to contain the Lattice private key.
The system is based on a Lattice root signing secret, deterministic per-action identities, and Lattice public-key verification for invocations.
Core Idea
Lattice has a root private key:
This key is the current trust anchor for action registration.
During early development, a trusted SDK/runtime may also have access to this same root key. Using that key, the SDK derives an action-specific private key from the action's action_id. That derived action key signs the action registration claim.
Lattice receives the registration request, re-derives the expected action identity from the same root key and action_id, and verifies the signature.
Lattice root key
↓
derived action key
↓
signed action registration
↓
Lattice verifies against expected derived action identity
For invocation, the model is different:
Lattice private key
↓
signed invocation request
↓
action verifies using Lattice public key from Lattice Core
The action does not need the Lattice private key to verify invocations.
Registration Flow
1. SDK Holds the Root Key
The SDK has access to LATTICE_ROOT_PRIVATE_KEY and builds an action registration claim.
2. Derive Action Key
The SDK derives an action private key from:
3. Sign and Send
The SDK signs the registration claim with the derived action private key and sends the registration envelope to Lattice:
{
"claim_version": "lattice.action.registration.v1",
"claim": { "...": "action metadata" },
"signature": "...",
"signature_algorithm": "ed25519",
"action_identity_version": "v1"
}
4. Lattice Verifies
Lattice receives the request and re-derives the expected action key from:
Lattice verifies the signature over the claim. If verification succeeds, Lattice accepts the registration.
Invocation Flow
When Lattice invokes an action:
1. Lattice Signs
Lattice builds an invocation request and signs it with the Lattice private key.
2. Action Receives
Lattice sends the signed invocation request to the action. The action obtains or is configured with the Lattice public key from Lattice Core.
3. Action Verifies and Executes
The action verifies the request using the Lattice public key. The action executes only if the request is valid.
The action surface does not need:
LATTICE_ROOT_PRIVATE_KEY
LATTICE_PRIVATE_KEY
The action surface only needs the Lattice public key for invocation verification:
The invocation payload binds the signature to the exact request via fields like action_id, method, path, body_hash, timestamp, and nonce or request_id. This allows the action to verify that the request came from Lattice, was not modified, was intended for this action, and is fresh and not a replay.
Current Trust Boundary
The current registration trust boundary is:
Anyone with the Lattice root private key is considered inside the trusted authority domain for action registration. Anyone without that key cannot produce valid action registrations.
The current invocation trust boundary is different:
holder of Lattice invocation private key signs
holder of Lattice public key verifies
Actions do not need private signing authority to verify invocations. They only need the Lattice public key. The current model is closest to shared-authority delegated registration + public-key verified invocation—similar in spirit to early-stage systems that use a powerful internal signing secret for registration while relying on public-key verification for requests.
What This Model Protects Against
Unauthenticated Action Registration
A random external process cannot register an action unless it can produce a valid signature derived from the Lattice root key.
Action Metadata Tampering
The signed registration claim covers fields like action_id, name, service, version, protocol, base_url, path, method, schemas, timeouts, and other metadata. If someone changes any of these fields after signing, verification fails.
Stable Deterministic Action Identity
Each action_id maps to a stable derived action key. Same Lattice root + same action_id = same identity. Different action_id = different identity.
Lattice-Origin Invocation
An action can reject calls that were not signed by Lattice. The action verifies this using the Lattice public key. The Lattice private key is not required inside the action surface.
Reduced Invocation Secret Exposure
Because invocation verification only requires the Lattice public key, an action does not need access to Lattice's invocation private key. A compromised action runtime can verify requests, but it cannot sign new requests as Lattice.
Basic Registry Gate
Lattice can reject registrations that do not prove access to the Lattice authority domain.
What This Model Does Not Protect Against
Compromised Trusted SDK Hosts
Because the SDK currently has access to LATTICE_ROOT_PRIVATE_KEY, a compromised SDK host can derive action keys for any action_id and register arbitrary actions. The current registration boundary is "anyone with the root key is trusted"—not "each action is isolated from every other action."
Strong Per-Action Containment
Derived action keys are useful for structure, attribution, and future hardening, but if the root key is available to the runtime, the runtime can mint any derived action identity.
Invocation Signing by Actions
Actions can verify invocations using the Lattice public key. They should not sign invocations as Lattice. The Lattice private invocation key remains in Lattice-controlled infrastructure.
Encryption
Signatures prove authenticity and integrity. They do not hide the contents of registration claims, invocations, or responses. Use HTTPS/TLS for transport security.
Replay Prevention by Default
Signatures alone do not prevent replay. Invocation requests should include a timestamp and nonce or request_id, and the receiver must reject old timestamps and already-used identifiers.
Root Key Compromise
If LATTICE_ROOT_PRIVATE_KEY is leaked, an attacker can mint valid action identities and create valid action registrations. Root key protection is critical.
Lattice Invocation Key Compromise
If the Lattice invocation private key is leaked, an attacker can sign requests that actions may accept as Lattice-origin invocations. This key remains inside Lattice-controlled infrastructure—not inside action runtimes.
Current Security Invariant
The current system provides this registration invariant:
Only something with the Lattice root private key can create an action registration that Lattice will accept.
And this invocation invariant:
Only something with the Lattice invocation private key can produce invocation requests that actions should accept.
The action only needs the Lattice public key to verify that invariant.
Lattice root key proves registration authority.
Derived action key proves action registration.
Lattice private key signs invocation.
Lattice public key verifies invocation.
Why This Is Acceptable for Early Testing
For an early testing system, this is a reasonable basic security layer. It is simple to implement, avoids unauthenticated registry writes, prevents accidental or external spoofing, and establishes a clean signing and verification structure that can later be hardened without changing the whole conceptual model.
The biggest registration tradeoff is that the trusted SDK/runtime currently has too much authority if it holds LATTICE_ROOT_PRIVATE_KEY. That is acceptable only if the SDK host is considered trusted.
The invocation model is safer: actions do not need Lattice private signing authority. They only need the Lattice public key from Lattice Core.
Required Action Runtime Material
An action runtime may need:
- ACTION_ID
- Identifies the action.
- ACTION_PRIVATE_KEY
- Signs action-owned claims, such as registration or future result signing.
- LATTICE_PUBLIC_KEY
- Verifies invocations from Lattice.
An action runtime should not need:
LATTICE_ROOT_PRIVATE_KEY
LATTICE_PRIVATE_KEY
The root key and Lattice invocation private key remain in Lattice-controlled or provisioning infrastructure.
Potential Hardening Directions
1. Move root key out of the SDK runtime
Only Lattice or a trusted provisioner holds LATTICE_ROOT_PRIVATE_KEY. Lattice derives a singleton action key and gives only that key to the action runtime. A compromised action key compromises one action identity—not the entire registration authority.
2. Keep invocation private keys only in Lattice Core
Invocation signing happens inside Lattice-controlled infrastructure. Actions verify invocations using the Lattice public key from Lattice Core—e.g. LATTICE_PUBLIC_KEY_URL or LATTICE_CORE_JWKS_URL—or a versioned key reference.
3. Add an action key provisioning step
Introduce a provisioning command or endpoint such as lattice mint-action-key --action-id <id> or POST /provision/action-key to mint a scoped action credential before registration.
4. Add key IDs and versions
Explicit key metadata—key_id, lattice_public_key_id, action_identity_version, claim_version, signature_algorithm—makes future rotation easier and supports clean coexistence of v1/v2 schemes.
5. Add root key rotation
Support multiple trusted Lattice root keys (active, previous, revoked) and include a key_id in registrations so Lattice knows which verification path to use.
6. Add Lattice public key rotation
Invocation envelopes include a public key identifier so actions select the correct trusted Lattice public key. A mature design exposes a Lattice Core public key set (JWKS-style endpoint) or distributes pinned public keys via configuration.
{
"key_id": "lattice-core-2026-01",
"signature_algorithm": "ed25519",
"signature": "...",
"claim": { "...": "..." }
}
7. Add replay protection
Invocation requests include timestamp, request_id, nonce, and body_hash. Actions reject old timestamps, duplicate request IDs/nonces, body hash mismatches, and wrong action_id or audience values.
8. Add audience binding
Every signed invocation includes the intended action via audience = action_id—preventing a request signed for one action from being replayed against another.
9. Add registry policy
Signature verification proves the request came from a trusted key holder. Policy decides whether it should be accepted: allowed service names and base URL domains, manual approval gates, duplicate name blocks, restricted methods/paths, version bumps for schema changes.
10. Treat enablement as registry state
The action signs its callable descriptor. Lattice decides whether it is enabled. This avoids letting the action decide its own availability or trust level.
11. Add result signing
Actions sign their responses with their action private key. Lattice can verify the result came from the registered action identity—useful for auditability, durable logs, async execution, or workflows where results pass through intermediaries.
12. Move root key into a secret manager or KMS
Move toward secret manager, KMS, HSM, hardware-backed signing, or short-lived credentials to reduce accidental leakage.
13. Move Lattice invocation signing into controlled infrastructure
The Lattice invocation private key moves to controlled signing infrastructure (KMS/HSM/short-lived). Actions only ever receive the corresponding public verification material.
Maturity Path
Stage 1 — Current
Shared Lattice root key in trusted SDK/runtime. Basic signed registration. Lattice-signed invocation. Actions verify invocation using the Lattice public key from Lattice Core. The action surface does not contain the Lattice private key.
Stage 2
Lattice/provisioner mints per-action keys. SDK/runtime only receives ACTION_ID, ACTION_PRIVATE_KEY, and LATTICE_PUBLIC_KEY. Root key leaves the runtime. Lattice invocation private key remains only in Lattice Core.
Stage 3
Add key IDs, registration key rotation, Lattice public key rotation, replay protection, audience binding, and registry policy.
Stage 4
Use KMS/HSM or short-lived credentials. Add result signing and audit logs.
Stage 5
Optional certificate/delegation model instead of deterministic key derivation.
Summary
The current model is intentionally simple. It gives Lattice a basic trust boundary: only trusted holders of the Lattice root key can register actions, and only Lattice-signed requests should be executed by actions.
The updated invocation model is: Lattice signs invocations with a private key. Actions verify invocations using the Lattice public key from Lattice Core. The Lattice private key is not required in the action surface.
The model does not yet provide strong per-action isolation for registration if the SDK/runtime still has LATTICE_ROOT_PRIVATE_KEY, because that runtime can mint arbitrary action identities. The natural next hardening step is to keep the Lattice root key only in Lattice/provisioning infrastructure and give each action only its own singleton derived private key.
Current registration model: shared root authority
Next registration model: root authority mints scoped action credentials
Current invocation model: Lattice private key signs; action verifies with Lattice public key
The current design is a reasonable early-stage foundation as long as LATTICE_ROOT_PRIVATE_KEY is treated as a highly sensitive registration authority secret, Lattice invocation private keys remain inside Lattice-controlled infrastructure, and actions receive only the Lattice public key needed to verify invocations.
Questions?
Contact: will@covenantlabs.ai

