Local invocation
Kernel call contract
The Execution Plane and Local Secret Kernel communicate through a fixed, typed interface of five call types. Everything that crosses the boundary is a typed context, a one-time permit, an opaque handle, a public descriptor, or a stable denial reason; the kernel retains raw secret material on its side of the boundary.
(node_id, operation_id, key_id, session_id, epoch_id, phase, slot, permit_handle, request_digest)expected epoch_id is the active oneAdmissionDecision checked against policy_root_setthe decision is still inside its validity windowpermit_handle belongs to this session and keyoperation_id + request_digest match the expected stepconsistent with mpc_session_handlenonce / presign in Prepared / Reservedany mismatch denies and records a reasonopaque handle · public descriptor · stable reason codeCallContext
Every local call is bound to node id, operation id, key id, session id, epoch id, phase, slot, permit handle, and request digest. The secret kernel checks that the request belongs to the local node and active epoch before any secret material is touched. The Execution Plane replays and explains execution using the public parts; the kernel owns the secret-bearing state.
The five call types are BindDecision (creates the operation permit), PrepareStep (reserves one-time local material), AdvanceStep (consumes a step permit and returns public output), PublishGate (checks disclosure of an already computed result), and AbortSession (poisons local artifacts with a reason code).
The kernel verifies the right to continue
Admission runs in two stages. The external admission contour performs the full evaluation — actor checks, approvals, limits, risk scoring, intent normalization — and emits an AdmissionDecision. The kernel consumes that decision as-is. Before it opens the secret layer it runs a local authorization over fixed bindings: the expected epoch is active, the AdmissionDecision verifies against the policy_root_set and is still inside its time window, the permit_handle belongs to this session and key, operation_id and request_digest match the expected protocol transition, phase and slot are consistent with the mpc_session_handle, and the one-shot nonce / presign sits in Prepared or Reserved.
Any mismatch fails closed with a stable reason; the kernel originates no new actions and only authorizes continuation of an already-admitted session. Keeping business logic outside and a small local check inside keeps the certifiable computing base minimal.
Boundary failure is a state
When the local boundary fails, it fails cleanly. BOUNDARY_UNAVAILABLE, STEP_PERMIT_REUSED, STALE_EPOCH, BINDING_MISMATCH, and PUBLICATION_DENIED are stable reason codes rather than exceptions. The contract explains what happened, the receipt records it, and the evidence package carries the proof. API status, architecture documentation, and support tooling all use the same vocabulary.
Permit lifecycle
step_permit has its own lifecycle inside the kernel: Issued when the kernel creates the permit for an admitted operation, Active while the session is alive and the step is eligible, and then one of Consumed (the step executed and the permit was spent), Expired (the validity window closed before the step ran), or Revoked (an operator or policy directive cancelled it).
The one-shot guarantee is the invariant: a permit in Consumed state is a terminal, and any subsequent call presenting the same permit handle gets STEP_PERMIT_REUSED. If the consuming call arrives and a consumed marker is already present — the crash-recovery scenario — the kernel returns the committed effect rather than re-executing. Every permit authorizes at most one execution.
Kernel refusals
The kernel's scope is fixed to three functions: permit and context verification, secret-bearing computation, and one-time artifact lifecycle. Admission policy is evaluated before the kernel is called and is read-only from the kernel's perspective. Shares, nonces, presign inputs, and private scalars stay on the kernel side of the boundary in every observable type. The local journal is scoped to session_id + epoch_id; a caller presenting a different operation_id receives a denial.
This fixed scope keeps the certifiable computing base minimal. The kernel verifies that an already-admitted operation has the right to continue a specific step, performs the secret-bearing computation, and returns opaque handles or public artifacts.
Key material at rest: mechanism depends on deployment
Each node stores only its own key share — no node ever holds a complete private key. At rest, the share is encrypted with a node-specific data encryption key (DEK) and plaintext never appears on disk. How the DEK is protected depends on the deployment. In cloud setups the DEK is wrapped by a cloud KMS (AWS KMS, GCP KMS, Azure Key Vault); the wrapped DEK is stored alongside the encrypted share, and on startup the node authenticates with the KMS using its cloud identity — in TEE deployments this includes a hardware attestation of the code running inside the enclave. In on-prem setups the equivalent role is played by a local KMS (HashiCorp Vault, a network-attached HSM, or an operator-managed key encryption key). The invariant is the same in both cases: the DEK is never stored in plaintext next to the share it protects, and unwrapping requires proof of node identity.
In memory, the key share is held only for the duration of the MPC step and cleared immediately after use. The same authorization gate covers the operational envelope: permits and step-permit lifecycle records are protected under the same node identity before they reach the kernel. The specific authorization mechanism — cloud IAM, TEE attestation, HSM identity certificate, or local Vault role — varies by deployment but the architectural contract is identical.