@trigguard/decision
v0.2.1
Published
TrigGuard HTTP decision client: authorize() → POST /decide (no policy in-process)
Maintainers
Readme
@trigguard/decision
Thin Node client: authorize() → POST /decide → remote authority returns PERMIT or DENY. No policy logic in this package.
Contract: /decide → PERMIT | DENY only — see decision-output.md.
Install
npm install @trigguard/decisionThe unscoped npm name trigguard is a different package. Use @trigguard/decision for this HTTP client.
From the monorepo:
npm install file:./sdk/nodeCommonJS (recommended)
const { authorize } = require("@trigguard/decision");
const decision = await authorize({
surface: "deployCommit",
context: {
repository: "org/repo",
ref: "refs/heads/main",
sha: "abc123",
},
});
if (decision.decision !== "PERMIT") {
throw new Error("TrigGuard denied execution");
}Optional second argument: { endpoint, token, timeoutMs, signal, maxRetries }. Defaults: TRIGGUARD_ENDPOINT / TRIGGUARD_TOKEN from the environment.
ESM usage (Node interop)
This package is published as CommonJS ("type": "commonjs"). In Node, use a default import and call .authorize:
import tg from "@trigguard/decision";
const decision = await tg.authorize({
surface: "deployCommit",
context: { repository: "org/repo", ref: "refs/heads/main", sha: "abc123" },
});
if (decision.decision !== "PERMIT") {
throw new Error("TrigGuard denied execution");
}Named imports are not supported in 0.2.x (import { authorize } from "…" may fail or behave inconsistently) because there is no separate exports.import entry yet. A dual ESM surface is planned for a future minor (e.g. 0.3).
Architecture
TrigGuard uses a remote decision authority (policy decision point).
authorize() sends JSON to TRIGGUARD_ENDPOINT (default https://decision.trigguard.ai/decide). The service evaluates the payload and returns PERMIT or DENY (and often reasonCode / human-readable fields).
CI integrations (e.g. trigguard-github-action/decision-gate) fail closed when the decision is not PERMIT.
Standard policy shape:
Policy Enforcement Point (your CI job, app, or SDK caller)
→ Policy Decision Point (TrigGuard /decide)
→ PERMIT | DENY
signals and context
The SDK forwards the object you pass: surface (string), optional signals, optional context. The authority runs remotely; richer structured fields allow stronger policy without embedding rules in the client.
Example:
{
"surface": "merge.pull_request",
"signals": {
"event_type": "pull_request",
"actor": "dev123"
},
"context": {
"repository": "org/repo",
"branch": "feature-x"
}
}What we are not doing in 0.2.x: no built-in diff extraction, no automatic surface inference from GitHub events, and no mandated signal schema — integrators supply evidence explicitly.
Resilience (0.2.x)
The client uses fetch with a default 5s timeout, optional AbortSignal, limited retries on transient errors, and typed errors: TrigGuardNetworkError, TrigGuardTimeoutError, TrigGuardDecisionServiceError.
Environment
| Variable | Purpose |
|----------|---------|
| TRIGGUARD_ENDPOINT | Decision URL (default: https://decision.trigguard.ai/decide) |
| TRIGGUARD_TOKEN | Bearer token when not passed in options.token |
Publish (maintainers)
cd sdk/node && npm login && npm publish --access publicSee docs/distribution/PUBLISH_DECISION_CLIENT.md.
Related package: packages/trigguard-sdk (npm trigguard) is the broader unified SDK — different artifact from @trigguard/decision.
