New:Socket for Asana Is Now Available.Learn more
Get Started

@trigguard/execution-sdk

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@trigguard/execution-sdk

Execution gateway client: POST /execute, local receipt verification via /.well-known/trigguard/keys.json

latest
Source
npmnpm
Version
0.2.0
Version published
Weekly downloads
55
-68.39%
Maintainers
1
Weekly downloads
 
Created
Source

@trigguard/execution-sdk

Node.js client for the execution gateway (POST /execute, GET /.well-known/trigguard/keys.json) with local Ed25519 receipt verification.

API

Authorize (decide) only:

import { authorize, verifyReceiptOffline, createExecutionClient } from "@trigguard/execution-sdk";

await authorize({
  gatewayUrl: process.env.TRIGGUARD_GATEWAY_URL!,
  surface: "deploy.release",
  actorId: "my-agent",
  apiKey: process.env.TRIGGUARD_API_KEY,
  // Required with API keys — sent as production `X-Consumer` (v0.1.3+).
  organizationId: process.env.TRIGGUARD_ORG_ID,
});

Recommended consequential path — authorize the exact envelope, then verify that same envelope at the execution boundary (executeBound). PERMIT is not enough:

import {
  authorize,
  executeBound,
  snapshotAuthorizedIntent,
} from "@trigguard/execution-sdk";

const context = { repository: "org/repo", commit: sha, environment: "staging" };
const executionIntent = snapshotAuthorizedIntent({
  actor: "ci",
  surface: "deploy.release",
  context,
});
const authorization = await authorize({
  gatewayUrl: process.env.TRIGGUARD_GATEWAY_URL!,
  apiKey: process.env.TRIGGUARD_API_KEY,
  organizationId: process.env.TRIGGUARD_ORG_ID,
  surface: "deploy.release",
  actorId: "ci",
  context,
});
if (authorization.decision !== "PERMIT") {
  return;
}
const verified = await executeBound({
  eat: authorization.eat!,
  executionIntent: authorization.authorizedExecutionIntent ?? executionIntent,
  binding: {
    repository: "org/repo",
    commit: sha,
    workflow: "release",
    environment: "staging",
  },
  gatewayUrl: process.env.TRIGGUARD_GATEWAY_URL!,
  requireExecutionBindingV2: process.env.TRIGGUARD_REQUIRE_EXECUTION_BINDING_V2 === "1",
});
if (!verified.ok) {
  throw new Error(verified.reason);
}
await doDeploy();

withExecute remains a compatibility helper: without binding it runs fn() on PERMIT and does not check execution_binding v2. That is policy permission, not exact execution authority. Pass binding (and requireExecutionBindingV2 when enforcing) or use executeBound.

Execution-binding semantics

snapshotAuthorizedIntent applies TG-EXEC-C14N-1: it normalizes the execution envelope (including actor, surface, environment, target, repository/commit/workflow/artifact, and consequential arguments) before SHA-256 binding. Object key order does not change the binding; a change to consequential material does. Pass the same complete intent to authorization and executeBound.

executeBound fails closed. A changed intent returns execution_binding_mismatch. With requireExecutionBindingV2: true, a legacy token without a v2 binding returns legacy_execution_binding_not_allowed. Replay protection is independent: provide a BoundReplayStore to atomically consume a verified token; a second use returns replayed_token.

On DENY / SILENCE, withExecute throws ExecutionNotPermittedError (see error.trigguardResult). Also re-exported from @trigguard/runtime.

Choosing an API shape

GoalAPINotes
Consequential side effect (bound EAT)authorize + executeBoundRecommended. Same intent at authorize and execute.
Compatibility PERMIT-then-runwithExecute with bindingVerifies v2 when the token carries execution_binding.
Policy-only gate (not exact execution)withExecute without bindingCompatibility. PERMIT ≠ bound execution.
Authorize, then branch yourselfcreateExecutionClientauthorizeSame HTTP surface; you handle DENY/SILENCE.

All paths accept gatewayUrl plus either apiKey (tg_live_…) or getBearerToken. Prefer apiKey for customer keys. Env cheat-sheet: docs/infrastructure/ENVIRONMENT_REFERENCE.md.

Typed failures (Wave 5)

As of Wave 5, the SDK exposes a categorical error vocabulary so integrators can route failures by category instead of by string-matching. All typed errors inherit from TrigGuardSdkError; the pre-existing ExecutionNotPermittedError is now also a TrigGuardSdkError (purely additive — existing instanceof Error and instanceof ExecutionNotPermittedError checks keep working).

import {
  attemptExecute,
  TrigGuardSdkError,
  TrigGuardAuthError,
  TrigGuardTimeoutError,
  ExecutionNotPermittedError,
} from "@trigguard/execution-sdk";

try {
  await attemptExecute("deploy.release", { gatewayUrl, apiKey });
} catch (e) {
  if (e instanceof ExecutionNotPermittedError) {
    /* policy DENY / SILENCE — do not retry */
  } else if (e instanceof TrigGuardAuthError) {
    /* expired or wrong credential — do not retry */
  } else if (e instanceof TrigGuardTimeoutError) {
    /* retryable */
  } else if (e instanceof TrigGuardSdkError) {
    /* any other typed failure — use e.category, e.retryable */
  }
}

Categories: auth | forbidden | network | timeout | malformed | http | trust | policy | verification | client-config. The retry-safety flag (e.retryable) is a deterministic function of the category — see docs/infrastructure/SDK_OPERATIONS.md for the full table.

Detailed receipt verification (Wave 5)

verifyReceiptSignatureDetailed returns a categorical reason instead of boolean:

import { verifyReceiptSignatureDetailed } from "@trigguard/execution-sdk";

const r = verifyReceiptSignatureDetailed(receipt, keysDoc);
if (!r.ok) {
  // r.reason is one of: unsigned | missing-signing-key | missing-key-id |
  // malformed-signature | signature-invalid | crypto-error
}

The legacy verifyReceiptSignature(...) boolean signature is unchanged.

Opt-in diagnostics (Wave 5)

Set TRIGGUARD_SDK_VERBOSE=1 to enable structured stderr diagnostics. Off by default. The SDK never logs the auth token, the request body, or the response body — only URL, HTTP status, decision string, classified failure category, and retryable flag.

TRIGGUARD_SDK_VERBOSE=1 node my-app.js
# trigguard-sdk: authorize decision=PERMIT, failureCategory=<none>, httpStatus=200, retryable=<none>, url=https://gateway

Safety notes

  • Local-vs-prod auth. The SDK accepts a missing auth provider (no apiKey, no getBearerToken) — convenient for local dev. In production this almost always indicates a misconfiguration. Enable TRIGGUARD_SDK_VERBOSE=1 during local development to surface a one-time no-auth-token warning.
  • Fail-closed contract. withExecute runs the protected function only on decision === "PERMIT". Any other outcome — DENY, SILENCE, missing decision, non-2xx HTTP, network failure, timeout — does not run the function.
  • COMPATIBILITY MODE != EXACT EXECUTION AUTHORITY. withExecute without binding does not verify the EAT execution-intent hash. Consequential executors must use executeBound (or withExecute + binding).
  • SIGNATURE VALID != AUTHORIZED EXECUTION. Gateway POST /v1/verify (trusted: true) is cryptographic trust of a TG-EAT, not permission to execute.
  • Receipt verification. verifyReceiptSignature / verifyReceiptSignatureDetailed perform Ed25519 verification locally using keys from /.well-known/trigguard/keys.json. No external network call is made during verification once the keys document is in hand.
  • No secrets in diagnostics. See above.

Migrating from 0.1.x to 0.2.0

There is no mandatory migration for applications intentionally using compatibility mode; its default behavior is unchanged. Applications performing consequential side effects should snapshot the complete intent and verify the issued EAT with executeBound immediately before the effect. Enable requireExecutionBindingV2 only after all relevant issuers and relying parties have migrated, because it deliberately rejects legacy tokens. Version 0.2.0 also makes these bound-execution APIs self-contained in the installed package; private TrigGuard workspace packages are not runtime dependencies.

Onboarding examples

Canonical, runnable, offline. From the repo root:

node examples/sdk-onboarding/00-minimal-authorize.mjs
node examples/sdk-onboarding/01-fail-closed-withexecute.mjs
node examples/sdk-onboarding/02-verify-receipt-locally.mjs
node examples/sdk-onboarding/03-local-dev-diagnostics.mjs
node examples/sdk-onboarding/04-typed-error-routing.mjs

See examples/sdk-onboarding/README.md for details and docs/infrastructure/SDK_OPERATIONS.md for the operator/integrator companion.

Build & test

npm ci && npm run build
npm test

Relationship to other packages

  • trigguard (sdk/trigguard-js) — hosted site verification API (/protocol/verify-receipt, etc.).
  • @trigguard/execution-sdkCloud Run execution gateway (authorize → receipt).

Protocol semantics remain in trigguard-protocol; this package is a thin HTTP + crypto wrapper.

Keywords

trigguard

FAQs

Package last updated on 02 Sep 2026

Related posts