@tuent/sentinel 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -291,8 +291,16 @@ interface SecurityFinding {
291
291
  * its dominant real-world cause is a recognized-tool set gone stale after a
292
292
  * Claude Code update, not agent misbehavior — counting it would turn every
293
293
  * cc update into a restriction ratchet.
294
- */
295
- type: "scope_violation" | "temporal_anomaly" | "access_pattern" | "volume_spike" | "unauthorized_target" | "role_violation" | "behavioral_absence" | "agent_quarantined" | "agent_restricted" | "intent_drift" | "hook_block" | "bash_analysis" | "workspace_mismatch" | "unknown_tool";
294
+ *
295
+ * `enforcement_error` is likewise non-eligible: it records that Sentinel's
296
+ * OWN enforcement machinery threw an internal error while screening a call
297
+ * (so the call was decided by posture, not by policy). The cause is a
298
+ * Sentinel bug or broken config, not agent misbehavior — counting it would
299
+ * compound a Sentinel-internal failure into an agent lockout. It is HIGH +
300
+ * actionable so it alerts and demands operator attention, but it never
301
+ * moves the escalation ladder.
302
+ */
303
+ type: "scope_violation" | "temporal_anomaly" | "access_pattern" | "volume_spike" | "unauthorized_target" | "role_violation" | "behavioral_absence" | "agent_quarantined" | "agent_restricted" | "intent_drift" | "hook_block" | "bash_analysis" | "workspace_mismatch" | "unknown_tool" | "enforcement_error";
296
304
  agentId: string;
297
305
  agentName: string;
298
306
  description: string;
@@ -0,0 +1,10 @@
1
+ import {
2
+ Sentinel
3
+ } from "./chunk-7R6EA7JG.js";
4
+ import "./chunk-M5EEVMLU.js";
5
+ import "./chunk-SKE74CYZ.js";
6
+ import "./chunk-NUXSUSYY.js";
7
+ export {
8
+ Sentinel
9
+ };
10
+ //# sourceMappingURL=Sentinel-XP6NFG6Z.js.map
@@ -15,13 +15,13 @@ import {
15
15
  scanGlobPattern,
16
16
  tokenizePaths,
17
17
  unionWithDefaultForbiddenPatterns
18
- } from "./chunk-FIEIGBYL.js";
18
+ } from "./chunk-M5EEVMLU.js";
19
19
  import {
20
20
  DEFAULT_FORBIDDEN_PATTERNS,
21
21
  loadPolicy,
22
22
  policyToConfig,
23
23
  policyToRole
24
- } from "./chunk-KWZ7JKKO.js";
24
+ } from "./chunk-SKE74CYZ.js";
25
25
 
26
26
  // src/gateway/workspaceRouter.ts
27
27
  import { resolve, dirname, sep } from "path";
@@ -254,7 +254,15 @@ async function resolveWorkspace(cwd, home) {
254
254
  let workspaceRole = null;
255
255
  const warnings = [];
256
256
  if (policyPath) {
257
- const policy = await loadPolicy(policyPath);
257
+ let policy;
258
+ try {
259
+ policy = await loadPolicy(policyPath);
260
+ } catch (err) {
261
+ return {
262
+ ok: false,
263
+ reason: `the workspace's policy file failed to load (${err instanceof Error ? err.message : String(err)}) \u2014 refusing to serve the workspace without its policy`
264
+ };
265
+ }
258
266
  const policyDir = dirname(resolve(policyPath));
259
267
  root = policyDir;
260
268
  const repoRoot = policyToConfig(policy).repo?.root;
@@ -1145,6 +1153,8 @@ var SentinelGateway = class {
1145
1153
  releaseToken;
1146
1154
  /** Item D (F-8): disposition for unknown (non-MCP, unrecognized) tool names. */
1147
1155
  unknownTools;
1156
+ /** Posture for an internal wrap() error: allow (fail-open, default) or block. */
1157
+ onInternalError;
1148
1158
  /** Daemon-staleness build identity (content hash of the launched-from entry),
1149
1159
  * reported via /health. "unknown" when not supplied by the launcher. */
1150
1160
  buildId;
@@ -1163,6 +1173,7 @@ var SentinelGateway = class {
1163
1173
  this.home = options.home ?? "";
1164
1174
  this.releaseToken = options.releaseToken ?? null;
1165
1175
  this.unknownTools = options.unknownTools ?? "warn";
1176
+ this.onInternalError = options.onInternalError ?? "fail-open";
1166
1177
  this.buildId = options.buildId ?? "unknown";
1167
1178
  const internal = options;
1168
1179
  if (internal.registry) {
@@ -1509,7 +1520,37 @@ var SentinelGateway = class {
1509
1520
  this.sendJson(res, 400, { error: "invalid JSON" });
1510
1521
  return;
1511
1522
  }
1512
- const event = translator.translatePreToolUse(payload);
1523
+ let event;
1524
+ try {
1525
+ event = translator.translatePreToolUse(payload);
1526
+ } catch (err) {
1527
+ console.error("[SENTINEL GATEWAY] translator error (pre-tool-use):", err);
1528
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
1529
+ const finding = {
1530
+ severity: "HIGH",
1531
+ kind: "actionable",
1532
+ type: "enforcement_error",
1533
+ agentId: this.agentId,
1534
+ agentName: this.agentId,
1535
+ description: `Enforcement error \u2014 the ${translator.agentType} translator threw while parsing a pre-tool-use payload: ${err instanceof Error ? err.message : String(err)}. The request was answered with an error (HTTP 500), not an allow.`,
1536
+ evidence: {
1537
+ action: "tool_invocation",
1538
+ target: "(untranslatable pre-tool-use payload)",
1539
+ timestamp: ts,
1540
+ baselineComparison: "enforcement_internal_error"
1541
+ },
1542
+ recommendation: "Investigate the gateway daemon log for the underlying translator exception \u2014 the payload could not be screened.",
1543
+ timestamp: ts,
1544
+ decision: "deny"
1545
+ };
1546
+ try {
1547
+ await this.sentinel.logFinding(this.agentId, finding);
1548
+ } catch (logErr) {
1549
+ console.error("[SENTINEL GATEWAY] failed to persist enforcement_error finding:", logErr);
1550
+ }
1551
+ this.sendJson(res, 500, { error: "translator error" });
1552
+ return;
1553
+ }
1513
1554
  if (!event) {
1514
1555
  this.sendJson(res, 400, { error: "unable to translate payload" });
1515
1556
  return;
@@ -1934,7 +1975,37 @@ var SentinelGateway = class {
1934
1975
  this.sendJson(res, 200, response);
1935
1976
  } catch (err) {
1936
1977
  console.error("[SENTINEL GATEWAY] wrap() error:", err);
1937
- const response = translator.formatPreToolUseResponse({ blocked: false });
1978
+ const failClosed = this.onInternalError === "fail-closed";
1979
+ const errMessage = err instanceof Error ? err.message : String(err);
1980
+ const finding = {
1981
+ severity: "HIGH",
1982
+ kind: "actionable",
1983
+ type: "enforcement_error",
1984
+ agentId: routingId,
1985
+ agentName: event.agentName,
1986
+ description: `Enforcement error \u2014 sentinel.wrap() threw while screening "${event.action}": ${errMessage}. The call was ${failClosed ? "BLOCKED" : "ALLOWED WITHOUT SCREENING"} (enforcement.onInternalError: ${this.onInternalError}).`,
1987
+ evidence: {
1988
+ action: event.action,
1989
+ target: event.primaryTarget,
1990
+ timestamp: event.timestamp,
1991
+ baselineComparison: "enforcement_internal_error"
1992
+ },
1993
+ recommendation: `Investigate the gateway daemon log for the underlying exception \u2014 Sentinel's own enforcement failed, so this call was decided by posture, not policy. Set enforcement.onInternalError: "fail-closed" to block instead of allow while the cause is open.`,
1994
+ timestamp: event.timestamp,
1995
+ decision: failClosed ? "deny" : "allow"
1996
+ };
1997
+ try {
1998
+ await this.sentinel.logFinding(routingId, finding);
1999
+ } catch (logErr) {
2000
+ console.error("[SENTINEL GATEWAY] failed to persist enforcement_error finding:", logErr);
2001
+ }
2002
+ this.telemetry.recordToolCall(
2003
+ event.action,
2004
+ "pre",
2005
+ failClosed ? "blocked" : "allowed",
2006
+ Date.now() - start
2007
+ );
2008
+ const response = failClosed ? translator.formatPreToolUseResponse({ blocked: true, finding }) : translator.formatPreToolUseResponse({ blocked: false });
1938
2009
  this.sendJson(res, 200, response);
1939
2010
  }
1940
2011
  }
@@ -2103,11 +2174,11 @@ async function runGatewayDaemon({
2103
2174
  port = DEFAULT_PORT,
2104
2175
  buildId
2105
2176
  }) {
2106
- const { Sentinel: SentinelClass } = await import("./Sentinel-4QKPFHTI.js");
2177
+ const { Sentinel: SentinelClass } = await import("./Sentinel-XP6NFG6Z.js");
2107
2178
  const { writePidFile, writeReleaseToken } = await import("./pidManager-DOGVN6ZT.js");
2108
2179
  const { homedir } = await import("os");
2109
2180
  const { randomBytes } = await import("crypto");
2110
- const { loadPolicy: loadPolicy2, policyToRole: policyToRole2, policyToConfig: policyToConfig2 } = await import("./policyLoader-XX6BQXNB.js");
2181
+ const { loadPolicy: loadPolicy2, policyToRole: policyToRole2, policyToConfig: policyToConfig2 } = await import("./policyLoader-NUPBBRKH.js");
2111
2182
  const sentinel = await SentinelClass.fromPolicy(policyPath);
2112
2183
  const baseline = await sentinel.computeBaseline("claude-code");
2113
2184
  sentinel.setBaseline("claude-code", baseline);
@@ -2126,6 +2197,7 @@ async function runGatewayDaemon({
2126
2197
  releaseToken,
2127
2198
  unknownTools: operatorConfig.enforcement?.unknownTools,
2128
2199
  allowUnknownTools: operatorConfig.enforcement?.allowUnknownTools,
2200
+ onInternalError: operatorConfig.enforcement?.onInternalError,
2129
2201
  buildId,
2130
2202
  // The operator policy's custom forbid targets must reach the gateway's own
2131
2203
  // bash-L1/Grep layers (defaults-as-floor union, same chokepoint as role
@@ -2143,4 +2215,4 @@ export {
2143
2215
  SentinelGateway,
2144
2216
  runGatewayDaemon
2145
2217
  };
2146
- //# sourceMappingURL=chunk-HRI2Y326.js.map
2218
+ //# sourceMappingURL=chunk-3WT3K5TH.js.map
@@ -16,7 +16,7 @@ import {
16
16
  saveOverlay,
17
17
  unionWithDefaultForbiddenPatterns,
18
18
  walkForbiddenInodeRoots
19
- } from "./chunk-FIEIGBYL.js";
19
+ } from "./chunk-M5EEVMLU.js";
20
20
  import {
21
21
  DEFAULT_MEDIUM_DISPOSITION,
22
22
  DEFAULT_QUARANTINE_AFTER,
@@ -25,7 +25,7 @@ import {
25
25
  policyToConfig,
26
26
  policyToRole,
27
27
  withPolicyReadExceptions
28
- } from "./chunk-KWZ7JKKO.js";
28
+ } from "./chunk-SKE74CYZ.js";
29
29
  import {
30
30
  publicKeyToBase64,
31
31
  reconstructSigningPayload,
@@ -7618,4 +7618,4 @@ export {
7618
7618
  createCliApproval,
7619
7619
  Sentinel
7620
7620
  };
7621
- //# sourceMappingURL=chunk-I2FVDDSG.js.map
7621
+ //# sourceMappingURL=chunk-7R6EA7JG.js.map
@@ -4,7 +4,7 @@ import {
4
4
  DEFAULT_NETWORK_DENYLIST_CIDRS,
5
5
  checkSaneNumber,
6
6
  suggestKey
7
- } from "./chunk-KWZ7JKKO.js";
7
+ } from "./chunk-SKE74CYZ.js";
8
8
 
9
9
  // src/repoSensitivityOverlay.ts
10
10
  import * as fs from "fs/promises";
@@ -1933,4 +1933,4 @@ export {
1933
1933
  findMatchingException,
1934
1934
  RoleValidator
1935
1935
  };
1936
- //# sourceMappingURL=chunk-FIEIGBYL.js.map
1936
+ //# sourceMappingURL=chunk-M5EEVMLU.js.map
@@ -343,7 +343,8 @@ function validatePolicy(data) {
343
343
  "promote",
344
344
  "baselineMaturity",
345
345
  "unknownTools",
346
- "allowUnknownTools"
346
+ "allowUnknownTools",
347
+ "onInternalError"
347
348
  ]);
348
349
  if (enforcement.restrictAfter !== void 0) {
349
350
  requireSaneNumber("enforcement.restrictAfter", enforcement.restrictAfter, {
@@ -399,6 +400,11 @@ function validatePolicy(data) {
399
400
  fail("enforcement.allowUnknownTools must be an array of tool name strings");
400
401
  }
401
402
  }
403
+ if (enforcement.onInternalError !== void 0) {
404
+ if (enforcement.onInternalError !== "fail-open" && enforcement.onInternalError !== "fail-closed") {
405
+ fail('enforcement.onInternalError must be "fail-open" or "fail-closed"');
406
+ }
407
+ }
402
408
  if (enforcement.baselineMaturity !== void 0) {
403
409
  if (typeof enforcement.baselineMaturity !== "object" || enforcement.baselineMaturity === null) {
404
410
  fail("enforcement.baselineMaturity must be an object");
@@ -566,7 +572,7 @@ function policyToRole(policy) {
566
572
  function policyToConfig(policy) {
567
573
  const config = {};
568
574
  if (policy.enforcement) {
569
- if (policy.enforcement.restrictAfter !== void 0 || policy.enforcement.quarantineAfter !== void 0 || policy.enforcement.promote !== void 0 || policy.enforcement.baselineMaturity !== void 0 || policy.enforcement.unknownTools !== void 0 || policy.enforcement.allowUnknownTools !== void 0) {
575
+ if (policy.enforcement.restrictAfter !== void 0 || policy.enforcement.quarantineAfter !== void 0 || policy.enforcement.promote !== void 0 || policy.enforcement.baselineMaturity !== void 0 || policy.enforcement.unknownTools !== void 0 || policy.enforcement.allowUnknownTools !== void 0 || policy.enforcement.onInternalError !== void 0) {
570
576
  config.enforcement = {};
571
577
  if (policy.enforcement.restrictAfter !== void 0) {
572
578
  config.enforcement.restrictAfter = policy.enforcement.restrictAfter;
@@ -586,6 +592,9 @@ function policyToConfig(policy) {
586
592
  if (policy.enforcement.allowUnknownTools !== void 0) {
587
593
  config.enforcement.allowUnknownTools = policy.enforcement.allowUnknownTools;
588
594
  }
595
+ if (policy.enforcement.onInternalError !== void 0) {
596
+ config.enforcement.onInternalError = policy.enforcement.onInternalError;
597
+ }
589
598
  }
590
599
  }
591
600
  if (policy.alerts) {
@@ -635,4 +644,4 @@ export {
635
644
  policyToRole,
636
645
  policyToConfig
637
646
  };
638
- //# sourceMappingURL=chunk-KWZ7JKKO.js.map
647
+ //# sourceMappingURL=chunk-SKE74CYZ.js.map
@@ -7,11 +7,11 @@ import {
7
7
  } from "./chunk-B6S2PBS4.js";
8
8
  import {
9
9
  FORBIDDEN_BASENAMES
10
- } from "./chunk-FIEIGBYL.js";
10
+ } from "./chunk-M5EEVMLU.js";
11
11
  import {
12
12
  loadPolicy,
13
13
  loadPolicyFromString
14
- } from "./chunk-KWZ7JKKO.js";
14
+ } from "./chunk-SKE74CYZ.js";
15
15
 
16
16
  // src/setup/initClaudeCode.ts
17
17
  import { access, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
@@ -768,4 +768,4 @@ export {
768
768
  computeBuildId,
769
769
  runSessionStart
770
770
  };
771
- //# sourceMappingURL=chunk-LTBVWF5H.js.map
771
+ //# sourceMappingURL=chunk-UVNRPML4.js.map
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import"./chunk-TKAKHSZ3.js";import{AgentProfileManager as B,AlertManager as me,AuditTrail as b,BaselineBuilder as x,CorrelationDetector as he,DeviationDetector as _,FileStorageBackend as ye,ProfileStore as we,ReportGenerator as ve,Sentinel as E,SentinelRunner as $e,generateFleetReport as Ae}from"./chunk-I2FVDDSG.js";import{runInitClaudeCode as be}from"./chunk-LTBVWF5H.js";import{readReleaseToken as Ie}from"./chunk-LATQNIRW.js";import{deriveAgentId as Se}from"./chunk-B5QKJHSV.js";import"./chunk-B6S2PBS4.js";import"./chunk-FIEIGBYL.js";import{checkSaneNumber as P,loadPolicy as De,suggestKey as Te}from"./chunk-KWZ7JKKO.js";import{getOrCreateKeyPair as R}from"./chunk-NUXSUSYY.js";import{join as g}from"path";import{homedir as h}from"os";import{readFile as N,writeFile as C,access as G,mkdir as U}from"fs/promises";function ke(t){const o=new Date(t);if(isNaN(o.getTime()))return"unknown";const e=Date.now()-o.getTime();if(e<0)return"just now";const s=Math.floor(e/6e4);if(s<1)return"just now";if(s<60)return`${s} minute${s===1?"":"s"} ago`;const i=Math.floor(s/60);if(i<24)return`${i} hour${i===1?"":"s"} ago`;const a=Math.floor(i/24);if(a<14)return`${a} day${a===1?"":"s"} ago`;const d=Math.floor(a/7);if(a<60)return`${d} week${d===1?"":"s"} ago`;if(a>=365)return"over a year ago";const c=Math.floor(a/30);return`${c} month${c===1?"":"s"} ago`}function Ee(t,o){const n=new Date(o),e=isNaN(n.getTime())?1/0:Math.floor((Date.now()-n.getTime())/864e5);return t<.3||e>30?"declining":t>.7&&e<7?"rising":"stable"}function Ce(t){return t<.3?"inner":t<.65?"middle":"outer"}function J(t){if(t.length===0)return"No petals selected.";const o=new Map;for(const e of t)o.set(e.id,e.label);const n=[`Selected petals (${t.length}):
2
+ import"./chunk-TKAKHSZ3.js";import{AgentProfileManager as B,AlertManager as me,AuditTrail as b,BaselineBuilder as x,CorrelationDetector as he,DeviationDetector as _,FileStorageBackend as ye,ProfileStore as we,ReportGenerator as ve,Sentinel as E,SentinelRunner as $e,generateFleetReport as Ae}from"./chunk-7R6EA7JG.js";import{runInitClaudeCode as be}from"./chunk-UVNRPML4.js";import{readReleaseToken as Ie}from"./chunk-LATQNIRW.js";import{deriveAgentId as Se}from"./chunk-B5QKJHSV.js";import"./chunk-B6S2PBS4.js";import"./chunk-M5EEVMLU.js";import{checkSaneNumber as P,loadPolicy as De,suggestKey as Te}from"./chunk-SKE74CYZ.js";import{getOrCreateKeyPair as R}from"./chunk-NUXSUSYY.js";import{join as g}from"path";import{homedir as h}from"os";import{readFile as N,writeFile as C,access as G,mkdir as U}from"fs/promises";function ke(t){const o=new Date(t);if(isNaN(o.getTime()))return"unknown";const e=Date.now()-o.getTime();if(e<0)return"just now";const s=Math.floor(e/6e4);if(s<1)return"just now";if(s<60)return`${s} minute${s===1?"":"s"} ago`;const i=Math.floor(s/60);if(i<24)return`${i} hour${i===1?"":"s"} ago`;const a=Math.floor(i/24);if(a<14)return`${a} day${a===1?"":"s"} ago`;const d=Math.floor(a/7);if(a<60)return`${d} week${d===1?"":"s"} ago`;if(a>=365)return"over a year ago";const c=Math.floor(a/30);return`${c} month${c===1?"":"s"} ago`}function Ee(t,o){const n=new Date(o),e=isNaN(n.getTime())?1/0:Math.floor((Date.now()-n.getTime())/864e5);return t<.3||e>30?"declining":t>.7&&e<7?"rising":"stable"}function Ce(t){return t<.3?"inner":t<.65?"middle":"outer"}function J(t){if(t.length===0)return"No petals selected.";const o=new Map;for(const e of t)o.set(e.id,e.label);const n=[`Selected petals (${t.length}):
3
3
  `];for(const e of t){const s=Ce(e.layer),i=e.isRichData?"":" [filler]";n.push(`- ${e.label}${i}`),n.push(` Category: ${e.category}`),n.push(` Layer zone: ${s} (${(e.layer*100).toFixed(0)}%)`),n.push(` Openness: ${(e.openness*100).toFixed(0)}%`),n.push(` Description: ${e.description}`),n.push(` Last active: ${e.lastActive}`);const a=ke(e.lastActive),d=e.weight!=null?Ee(e.weight,e.lastActive):"stable";if(n.push(` Temporal: Last active ${a} | Weight trend: ${d}`),e.source){const c={seed:"seed data",agent:"observed from activity",manual:"filesystem scan",diary:"personal diary entry",conversation:"created from conversation","agent-monitor":"monitored agent activity"};n.push(` Source: ${c[e.source]??e.source}`)}if(e.weight!=null&&n.push(` Weight: ${e.weight.toFixed(2)}`),e.connections.length>0){const c=e.connections.map(r=>o.get(r)??je(r));n.push(` Connections: ${c.join(", ")}`)}if(e.files&&e.files.length>0){const c=e.files.slice(0,10).map(r=>r.split("/").pop()??r);n.push(` Key files: ${c.join(", ")}`)}if(e.fileContents&&e.fileContents.length>0){n.push(" File contents:");for(const c of e.fileContents)n.push(` --- ${c.name} ---`),n.push(c.content.split(`
4
4
  `).map(r=>` ${r}`).join(`
5
5
  `))}n.push("")}return n.join(`
@@ -1,4 +1,4 @@
1
- import { v as Sentinel, e as AgentRole, S as SecurityFinding } from '../Sentinel-DT0IyGQi.js';
1
+ import { v as Sentinel, e as AgentRole, S as SecurityFinding } from '../Sentinel-CJJ4iYDh.js';
2
2
  import 'node:crypto';
3
3
 
4
4
  /**
@@ -75,6 +75,20 @@ interface SentinelGatewayOptions {
75
75
  * Operator-only, same channel as unknownTools.
76
76
  */
77
77
  allowUnknownTools?: string[];
78
+ /**
79
+ * Posture when the core enforcement call (sentinel.wrap()) throws an
80
+ * INTERNAL error during pre-tool-use screening. This is distinct from the
81
+ * hook script's tiered fail-closed, which only covers an UNREACHABLE
82
+ * gateway — here the gateway is reachable and must decide what a clean
83
+ * response says about an unscreened call. "fail-open" (default) allows it,
84
+ * preserving the pre-knob availability-over-security behavior; "fail-closed"
85
+ * is the hardened opt-in that blocks it. Either way an enforcement_error
86
+ * finding is persisted to the audit trail — observability is unconditional,
87
+ * only the allow/block decision is configurable. Operator-only, same
88
+ * channel as unknownTools (enforcement.onInternalError in the launch
89
+ * --policy yaml).
90
+ */
91
+ onInternalError?: "fail-open" | "fail-closed";
78
92
  /**
79
93
  * Build identity reported via /health (daemon-staleness fix). Content hash of
80
94
  * the daemon entry file this process was launched from; session-start compares
@@ -97,6 +111,8 @@ declare class SentinelGateway {
97
111
  private readonly releaseToken;
98
112
  /** Item D (F-8): disposition for unknown (non-MCP, unrecognized) tool names. */
99
113
  private readonly unknownTools;
114
+ /** Posture for an internal wrap() error: allow (fail-open, default) or block. */
115
+ private readonly onInternalError;
100
116
  /** Daemon-staleness build identity (content hash of the launched-from entry),
101
117
  * reported via /health. "unknown" when not supplied by the launcher. */
102
118
  private readonly buildId;
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  SentinelGateway
3
- } from "../chunk-HRI2Y326.js";
3
+ } from "../chunk-3WT3K5TH.js";
4
4
  import "../chunk-B5QKJHSV.js";
5
5
  import "../chunk-B6S2PBS4.js";
6
- import "../chunk-FIEIGBYL.js";
7
- import "../chunk-KWZ7JKKO.js";
6
+ import "../chunk-M5EEVMLU.js";
7
+ import "../chunk-SKE74CYZ.js";
8
8
  export {
9
9
  SentinelGateway
10
10
  };
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runGatewayDaemon
4
- } from "./chunk-HRI2Y326.js";
4
+ } from "./chunk-3WT3K5TH.js";
5
5
  import {
6
6
  computeBuildId,
7
7
  runSessionStart
8
- } from "./chunk-LTBVWF5H.js";
8
+ } from "./chunk-UVNRPML4.js";
9
9
  import "./chunk-LATQNIRW.js";
10
10
  import "./chunk-B5QKJHSV.js";
11
11
  import "./chunk-B6S2PBS4.js";
12
- import "./chunk-FIEIGBYL.js";
13
- import "./chunk-KWZ7JKKO.js";
12
+ import "./chunk-M5EEVMLU.js";
13
+ import "./chunk-SKE74CYZ.js";
14
14
 
15
15
  // src/gatewayDaemon.ts
16
16
  import { fileURLToPath } from "url";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AgentActivityEvent, S as SecurityFinding } from './Sentinel-DT0IyGQi.js';
2
- export { a as AcceptableAction, b as AdapterConfig, c as AgentBaseline, d as AgentMode, e as AgentRole, f as AlertChannel, g as AlertConfig, h as AllowResponse, i as AuditEntry, j as AuditQueryOptions, B as BlockResponse, C as CorrelationFinding, E as ExceptionApprovalContext, k as ExceptionApprovalFn, G as GuideResponse, H as HookCheckpoint, l as HookContext, m as HookHandler, n as HookRegistration, o as HookResponse, I as IntentAlignmentConfig, p as IntentAlignmentResult, M as ModifiableEventFields, q as MonitorOptions, O as OverlayDecisionType, R as RepoSensitivityMap, r as ReportOptions, s as RoleException, t as SecuritySeverity, u as SensitivityOverlay, v as Sentinel, w as SentinelConfig, T as TaskIntent } from './Sentinel-DT0IyGQi.js';
1
+ import { A as AgentActivityEvent, S as SecurityFinding } from './Sentinel-CJJ4iYDh.js';
2
+ export { a as AcceptableAction, b as AdapterConfig, c as AgentBaseline, d as AgentMode, e as AgentRole, f as AlertChannel, g as AlertConfig, h as AllowResponse, i as AuditEntry, j as AuditQueryOptions, B as BlockResponse, C as CorrelationFinding, E as ExceptionApprovalContext, k as ExceptionApprovalFn, G as GuideResponse, H as HookCheckpoint, l as HookContext, m as HookHandler, n as HookRegistration, o as HookResponse, I as IntentAlignmentConfig, p as IntentAlignmentResult, M as ModifiableEventFields, q as MonitorOptions, O as OverlayDecisionType, R as RepoSensitivityMap, r as ReportOptions, s as RoleException, t as SecuritySeverity, u as SensitivityOverlay, v as Sentinel, w as SentinelConfig, T as TaskIntent } from './Sentinel-CJJ4iYDh.js';
3
3
  import 'node:crypto';
4
4
 
5
5
  interface SentinelPolicy {
@@ -60,6 +60,16 @@ interface SentinelPolicy {
60
60
  unknownTools?: "deny" | "warn";
61
61
  /** Item D escape hatch: native-shaped names to treat as known. */
62
62
  allowUnknownTools?: string[];
63
+ /**
64
+ * Posture when the gateway's core enforcement call (sentinel.wrap())
65
+ * throws an INTERNAL error during pre-tool-use screening. "fail-open"
66
+ * (default) allows the unscreened call — availability over security,
67
+ * today's behavior; "fail-closed" is the hardened opt-in that blocks it.
68
+ * Either way the gateway persists an enforcement_error finding — only
69
+ * the allow/block decision is configurable, never the observability.
70
+ * Operator launch policy only — the gateway reads it once at start.
71
+ */
72
+ onInternalError?: "fail-open" | "fail-closed";
63
73
  };
64
74
  alerts?: {
65
75
  channels: (string | {
package/dist/index.js CHANGED
@@ -2,20 +2,20 @@ import "./chunk-TKAKHSZ3.js";
2
2
  import {
3
3
  Sentinel,
4
4
  createCliApproval
5
- } from "./chunk-I2FVDDSG.js";
5
+ } from "./chunk-7R6EA7JG.js";
6
6
  import {
7
7
  runInitClaudeCode,
8
8
  runSessionStart
9
- } from "./chunk-LTBVWF5H.js";
9
+ } from "./chunk-UVNRPML4.js";
10
10
  import "./chunk-LATQNIRW.js";
11
11
  import {
12
12
  discoverPolicy
13
13
  } from "./chunk-B6S2PBS4.js";
14
- import "./chunk-FIEIGBYL.js";
14
+ import "./chunk-M5EEVMLU.js";
15
15
  import {
16
16
  loadPolicy,
17
17
  loadPolicyFromString
18
- } from "./chunk-KWZ7JKKO.js";
18
+ } from "./chunk-SKE74CYZ.js";
19
19
  import "./chunk-NUXSUSYY.js";
20
20
  export {
21
21
  Sentinel,
@@ -6,7 +6,7 @@ import {
6
6
  policyToConfig,
7
7
  policyToRole,
8
8
  suggestKey
9
- } from "./chunk-KWZ7JKKO.js";
9
+ } from "./chunk-SKE74CYZ.js";
10
10
  export {
11
11
  LOCKED_ACTIONABLE_TYPES,
12
12
  checkSaneNumber,
@@ -16,4 +16,4 @@ export {
16
16
  policyToRole,
17
17
  suggestKey
18
18
  };
19
- //# sourceMappingURL=policyLoader-XX6BQXNB.js.map
19
+ //# sourceMappingURL=policyLoader-NUPBBRKH.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuent/sentinel",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "AI agent behavioral security monitoring SDK",
5
5
  "author": "Tuent LLC",
6
6
  "keywords": [
@@ -1,10 +0,0 @@
1
- import {
2
- Sentinel
3
- } from "./chunk-I2FVDDSG.js";
4
- import "./chunk-FIEIGBYL.js";
5
- import "./chunk-KWZ7JKKO.js";
6
- import "./chunk-NUXSUSYY.js";
7
- export {
8
- Sentinel
9
- };
10
- //# sourceMappingURL=Sentinel-4QKPFHTI.js.map