@tuent/sentinel 0.1.1 → 0.1.3
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.
- package/README.md +5 -1
- package/SECURITY_MODEL.md +94 -35
- package/dist/Sentinel-5CQ6HKXS.js +10 -0
- package/dist/{Sentinel-B_sv8Kiy.d.ts → Sentinel-BVoMEF3F.d.ts} +46 -1
- package/dist/{chunk-WPTJBRX5.js → chunk-2TJ5Z53T.js} +266 -73
- package/dist/{chunk-IYC5E7RL.js → chunk-G74MMDKA.js} +189 -43
- package/dist/{chunk-QHE56MEO.js → chunk-JTR2E7RD.js} +247 -60
- package/dist/{chunk-NS6ZLMDK.js → chunk-SSDIBY52.js} +84 -25
- package/dist/chunk-TKAKHSZ3.js +1 -0
- package/dist/{chunk-2FFMYSVC.js → chunk-WLIDSTS4.js} +18 -2
- package/dist/cli.js +22 -22
- package/dist/gateway/index.d.ts +33 -1
- package/dist/gateway/index.js +3 -3
- package/dist/gatewayDaemon.js +37 -15
- package/dist/index.d.ts +40 -9
- package/dist/index.js +8 -7
- package/dist/{policyLoader-6KR5VFVV.js → policyLoader-KZL2U4M2.js} +2 -2
- package/package.json +1 -1
- package/dist/Sentinel-QHMQ67W3.js +0 -10
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
DEFAULT_FORBIDDEN_PATTERNS,
|
|
9
9
|
FORBIDDEN_BASENAMES,
|
|
10
|
+
classifyDeny,
|
|
10
11
|
isPositionallySafeMention,
|
|
11
12
|
matchGlobInsensitive,
|
|
12
13
|
normalizeForbiddenPattern,
|
|
@@ -14,12 +15,12 @@ import {
|
|
|
14
15
|
scanContentForForbiddenBasenames,
|
|
15
16
|
scanGlobPattern,
|
|
16
17
|
tokenizePaths
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-JTR2E7RD.js";
|
|
18
19
|
import {
|
|
19
20
|
loadPolicy,
|
|
20
21
|
policyToConfig,
|
|
21
22
|
policyToRole
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-WLIDSTS4.js";
|
|
23
24
|
|
|
24
25
|
// src/gateway/workspaceRouter.ts
|
|
25
26
|
import { resolve, dirname } from "path";
|
|
@@ -646,7 +647,37 @@ var TOOL_MAP = {
|
|
|
646
647
|
WebSearch: { action: "network_request", targetKey: "query" },
|
|
647
648
|
Task: { action: "tool_invocation", targetKey: "description" },
|
|
648
649
|
Skill: { action: "tool_invocation", targetKey: "skill" },
|
|
649
|
-
NotebookEdit: { action: "file_write", targetKey: "notebook_path" }
|
|
650
|
+
NotebookEdit: { action: "file_write", targetKey: "notebook_path" },
|
|
651
|
+
// Sprint 26 Gate-A Item D (F-8) — TOOL_MAP refresh. The 11 names above were
|
|
652
|
+
// a stale subset of cc's native tool set; with the unknown-tool deny consumer
|
|
653
|
+
// live, every missing native name would hard-fail. Inventory taken from a
|
|
654
|
+
// live cc session (2026-06). Conservative mapping: tool_invocation, with a
|
|
655
|
+
// targetKey only where the input schema is known to carry a representative
|
|
656
|
+
// free-text field (scanned by Check 2 / sensitivity like Task.description).
|
|
657
|
+
// Subagent-spawning tools (Agent/Workflow/Task*) are orchestration-only here:
|
|
658
|
+
// each spawned agent's own tool calls hook through PreToolUse individually.
|
|
659
|
+
Agent: { action: "tool_invocation", targetKey: "prompt" },
|
|
660
|
+
SendMessage: { action: "tool_invocation" },
|
|
661
|
+
AskUserQuestion: { action: "tool_invocation" },
|
|
662
|
+
ScheduleWakeup: { action: "tool_invocation", targetKey: "prompt" },
|
|
663
|
+
ToolSearch: { action: "tool_invocation", targetKey: "query" },
|
|
664
|
+
Workflow: { action: "tool_invocation", targetKey: "script" },
|
|
665
|
+
Monitor: { action: "tool_invocation" },
|
|
666
|
+
EnterPlanMode: { action: "tool_invocation" },
|
|
667
|
+
ExitPlanMode: { action: "tool_invocation" },
|
|
668
|
+
EnterWorktree: { action: "tool_invocation" },
|
|
669
|
+
ExitWorktree: { action: "tool_invocation" },
|
|
670
|
+
CronCreate: { action: "tool_invocation" },
|
|
671
|
+
CronDelete: { action: "tool_invocation" },
|
|
672
|
+
CronList: { action: "tool_invocation" },
|
|
673
|
+
TaskCreate: { action: "tool_invocation" },
|
|
674
|
+
TaskGet: { action: "tool_invocation" },
|
|
675
|
+
TaskList: { action: "tool_invocation" },
|
|
676
|
+
TaskOutput: { action: "tool_invocation" },
|
|
677
|
+
TaskStop: { action: "tool_invocation" },
|
|
678
|
+
TaskUpdate: { action: "tool_invocation" },
|
|
679
|
+
PushNotification: { action: "tool_invocation" },
|
|
680
|
+
RemoteTrigger: { action: "tool_invocation" }
|
|
650
681
|
};
|
|
651
682
|
var AGENT_ID = "claude-code";
|
|
652
683
|
var AGENT_NAME = "Claude Code";
|
|
@@ -739,7 +770,7 @@ function extractTargets(toolName, toolInput, cwd) {
|
|
|
739
770
|
return extractGrepTargets(toolInput, cwd);
|
|
740
771
|
default: {
|
|
741
772
|
const mapping = TOOL_MAP[toolName];
|
|
742
|
-
if (!mapping) return [toolName];
|
|
773
|
+
if (!mapping || !mapping.targetKey) return [toolName];
|
|
743
774
|
const val = toolInput[mapping.targetKey];
|
|
744
775
|
if (typeof val === "string" && val.length > 0) return [val];
|
|
745
776
|
return [toolName];
|
|
@@ -755,29 +786,56 @@ function mcpVerbIsMutating(toolName) {
|
|
|
755
786
|
const tokens = seg.split(/[_-]/).filter((t) => t.length > 0);
|
|
756
787
|
return tokens.some((t) => MCP_MUTATING_VERBS.some((v) => t.startsWith(v)));
|
|
757
788
|
}
|
|
789
|
+
var MCP_MAX_DEPTH = 6;
|
|
790
|
+
var MCP_MAX_NODES = 1e3;
|
|
791
|
+
function collectMcpStrings(value, depth, state) {
|
|
792
|
+
if (state.nodes >= MCP_MAX_NODES) {
|
|
793
|
+
state.truncated = true;
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
state.nodes++;
|
|
797
|
+
if (typeof value === "string") {
|
|
798
|
+
if (value.length > 0) state.strings.push(value);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
if (value === null || typeof value !== "object") return;
|
|
802
|
+
if (depth >= MCP_MAX_DEPTH) {
|
|
803
|
+
state.truncated = true;
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const children = Array.isArray(value) ? value : Object.values(value);
|
|
807
|
+
for (const child of children) collectMcpStrings(child, depth + 1, state);
|
|
808
|
+
}
|
|
758
809
|
function extractMcpTargets(toolName, toolInput) {
|
|
759
810
|
const targets = [toolName];
|
|
760
811
|
const keys = Object.keys(toolInput);
|
|
761
|
-
|
|
762
|
-
for (const key of keys)
|
|
763
|
-
|
|
764
|
-
if (typeof value !== "string" || value.length === 0) continue;
|
|
765
|
-
extractedStrings++;
|
|
812
|
+
const state = { strings: [], nodes: 0, truncated: false };
|
|
813
|
+
for (const key of keys) collectMcpStrings(toolInput[key], 1, state);
|
|
814
|
+
for (const value of state.strings) {
|
|
766
815
|
targets.push(value);
|
|
767
816
|
const resolved = runResolverPipeline(value);
|
|
768
|
-
for (const r of resolved)
|
|
769
|
-
targets.push(r);
|
|
770
|
-
}
|
|
817
|
+
for (const r of resolved) targets.push(r);
|
|
771
818
|
}
|
|
772
819
|
return {
|
|
773
820
|
targets,
|
|
774
|
-
unextractable: keys.length > 0 &&
|
|
821
|
+
unextractable: keys.length > 0 && (state.strings.length === 0 || state.truncated),
|
|
775
822
|
mutating: mcpVerbIsMutating(toolName)
|
|
776
823
|
};
|
|
777
824
|
}
|
|
778
825
|
var UNKNOWN_TOOL_REASON = "tool schema unknown \u2014 sensitivity scoring and forbidden target patterns cannot evaluate this event";
|
|
779
826
|
var ClaudeCodeTranslator = class {
|
|
780
827
|
agentType = "claude-code";
|
|
828
|
+
/**
|
|
829
|
+
* Sprint 26 Gate-A Item D (F-8) — operator allowlist escape hatch. Names
|
|
830
|
+
* listed in the launch policy's enforcement.allowUnknownTools translate as
|
|
831
|
+
* KNOWN tool_invocation (no _unknownTool marker), so a new cc native tool
|
|
832
|
+
* can be unbricked with a one-line policy edit + daemon restart instead of
|
|
833
|
+
* waiting on a Sentinel release that refreshes TOOL_MAP.
|
|
834
|
+
*/
|
|
835
|
+
allowUnknownTools;
|
|
836
|
+
constructor(options) {
|
|
837
|
+
this.allowUnknownTools = new Set(options?.allowUnknownTools ?? []);
|
|
838
|
+
}
|
|
781
839
|
translatePreToolUse(payload) {
|
|
782
840
|
const p = payload;
|
|
783
841
|
if (!p || typeof p !== "object" || !p.tool_name) return null;
|
|
@@ -798,7 +856,7 @@ var ClaudeCodeTranslator = class {
|
|
|
798
856
|
metadata._policyEnforcementBypassed = "true";
|
|
799
857
|
metadata._policyBypassReason = UNKNOWN_TOOL_REASON;
|
|
800
858
|
console.warn(
|
|
801
|
-
`[SENTINEL] Unknown Claude Code tool "${toolName}" \u2014
|
|
859
|
+
`[SENTINEL] Unknown Claude Code tool "${toolName}" \u2014 flagged for gateway disposition (enforcement.unknownTools; default warn). ${UNKNOWN_TOOL_REASON}`
|
|
802
860
|
);
|
|
803
861
|
}
|
|
804
862
|
if (isMcp) {
|
|
@@ -956,6 +1014,14 @@ var ClaudeCodeTranslator = class {
|
|
|
956
1014
|
mcpMutating: mcp.mutating
|
|
957
1015
|
};
|
|
958
1016
|
}
|
|
1017
|
+
if (this.allowUnknownTools.has(toolName)) {
|
|
1018
|
+
return {
|
|
1019
|
+
action: "tool_invocation",
|
|
1020
|
+
targets: [toolName],
|
|
1021
|
+
isUnknown: false,
|
|
1022
|
+
isMcp: false
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
959
1025
|
return {
|
|
960
1026
|
action: "tool_invocation",
|
|
961
1027
|
targets: [toolName],
|
|
@@ -994,7 +1060,6 @@ function buildModifiedGrepInput(originalInput, exclusions) {
|
|
|
994
1060
|
import { timingSafeEqual } from "crypto";
|
|
995
1061
|
var DEFAULT_PORT = 7847;
|
|
996
1062
|
var MAX_BODY_SIZE = 1024 * 1024;
|
|
997
|
-
var GATEWAY_VERSION = "0.1.0";
|
|
998
1063
|
function isLoopbackAddress(addr) {
|
|
999
1064
|
if (!addr) return false;
|
|
1000
1065
|
return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1" || addr.startsWith("127.");
|
|
@@ -1049,6 +1114,11 @@ var SentinelGateway = class {
|
|
|
1049
1114
|
operatorCeiling;
|
|
1050
1115
|
home;
|
|
1051
1116
|
releaseToken;
|
|
1117
|
+
/** Item D (F-8): disposition for unknown (non-MCP, unrecognized) tool names. */
|
|
1118
|
+
unknownTools;
|
|
1119
|
+
/** Daemon-staleness build identity (content hash of the launched-from entry),
|
|
1120
|
+
* reported via /health. "unknown" when not supplied by the launcher. */
|
|
1121
|
+
buildId;
|
|
1052
1122
|
server = null;
|
|
1053
1123
|
running = false;
|
|
1054
1124
|
signalHandlersInstalled = false;
|
|
@@ -1063,6 +1133,8 @@ var SentinelGateway = class {
|
|
|
1063
1133
|
this.operatorCeiling = options.operatorCeiling ?? null;
|
|
1064
1134
|
this.home = options.home ?? "";
|
|
1065
1135
|
this.releaseToken = options.releaseToken ?? null;
|
|
1136
|
+
this.unknownTools = options.unknownTools ?? "warn";
|
|
1137
|
+
this.buildId = options.buildId ?? "unknown";
|
|
1066
1138
|
const internal = options;
|
|
1067
1139
|
if (internal.registry) {
|
|
1068
1140
|
this.registry = internal.registry;
|
|
@@ -1071,7 +1143,9 @@ var SentinelGateway = class {
|
|
|
1071
1143
|
this.registry.register(internal.translator);
|
|
1072
1144
|
} else {
|
|
1073
1145
|
this.registry = new TranslatorRegistry();
|
|
1074
|
-
this.registry.register(
|
|
1146
|
+
this.registry.register(
|
|
1147
|
+
new ClaudeCodeTranslator({ allowUnknownTools: options.allowUnknownTools })
|
|
1148
|
+
);
|
|
1075
1149
|
}
|
|
1076
1150
|
}
|
|
1077
1151
|
get port() {
|
|
@@ -1180,7 +1254,11 @@ var SentinelGateway = class {
|
|
|
1180
1254
|
const snap = this.telemetry.getSnapshot();
|
|
1181
1255
|
this.sendJson(res, 200, {
|
|
1182
1256
|
status: "running",
|
|
1183
|
-
|
|
1257
|
+
// Daemon-staleness build identity (content hash of the launched-from
|
|
1258
|
+
// entry). Replaces the former hardcoded GATEWAY_VERSION, which had
|
|
1259
|
+
// drifted from package.json and would have mismatched spuriously.
|
|
1260
|
+
// session-start compares this to the current on-disk entry hash.
|
|
1261
|
+
buildId: this.buildId,
|
|
1184
1262
|
uptime: snap.uptime_seconds
|
|
1185
1263
|
});
|
|
1186
1264
|
return;
|
|
@@ -1406,35 +1484,26 @@ var SentinelGateway = class {
|
|
|
1406
1484
|
routingId = routed.agentId;
|
|
1407
1485
|
event.agentId = routingId;
|
|
1408
1486
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
const decodedImplicated = event.targets.slice(1).some((t) => scanBashCommand(t, FORBIDDEN_BASENAMES).matched);
|
|
1413
|
-
suppressForbiddenBasename = isPositionallySafeMention(literalCommand) && !decodedImplicated;
|
|
1414
|
-
}
|
|
1415
|
-
if (event.action === "command_exec" && event.targets && event.targets.length > 0 && !suppressForbiddenBasename) {
|
|
1416
|
-
const allL2Hits = [];
|
|
1417
|
-
for (const scanTarget of event.targets) {
|
|
1418
|
-
const scan = scanBashCommand(scanTarget, FORBIDDEN_BASENAMES);
|
|
1419
|
-
if (scan.matched) allL2Hits.push(...scan.hits);
|
|
1420
|
-
}
|
|
1421
|
-
if (allL2Hits.length > 0) {
|
|
1487
|
+
if (event.metadata?._unknownTool === "true") {
|
|
1488
|
+
const unknownName = event.metadata.ccToolName ?? event.primaryTarget;
|
|
1489
|
+
if (this.unknownTools === "deny") {
|
|
1422
1490
|
const finding = {
|
|
1423
1491
|
severity: "HIGH",
|
|
1424
1492
|
kind: "actionable",
|
|
1425
|
-
type: "
|
|
1493
|
+
type: "unknown_tool",
|
|
1426
1494
|
agentId: event.agentId,
|
|
1427
1495
|
agentName: event.agentName,
|
|
1428
|
-
description: `
|
|
1496
|
+
description: `Unknown tool "${unknownName}" denied \u2014 not in Sentinel's recognized tool set, so policy checks cannot evaluate it. If this is a legitimate tool, add it to enforcement.allowUnknownTools in the operator launch policy file and restart the gateway daemon.`,
|
|
1429
1497
|
evidence: {
|
|
1430
1498
|
action: event.action,
|
|
1431
|
-
target:
|
|
1499
|
+
target: unknownName,
|
|
1432
1500
|
timestamp: event.timestamp,
|
|
1433
|
-
baselineComparison: "
|
|
1501
|
+
baselineComparison: "unknown_tool_denied"
|
|
1434
1502
|
},
|
|
1435
|
-
recommendation: "
|
|
1503
|
+
recommendation: `Add "${unknownName}" to enforcement.allowUnknownTools in the operator launch policy file and restart the daemon, or update @tuent/sentinel to a build whose recognized tool set includes it.`,
|
|
1436
1504
|
timestamp: event.timestamp,
|
|
1437
|
-
decision: "deny"
|
|
1505
|
+
decision: "deny",
|
|
1506
|
+
dedupKey: unknownName
|
|
1438
1507
|
};
|
|
1439
1508
|
await this.sentinel.handleGatewayDeny(routingId, finding);
|
|
1440
1509
|
this.telemetry.recordToolCall(event.action, "pre", "blocked", 0);
|
|
@@ -1442,6 +1511,38 @@ var SentinelGateway = class {
|
|
|
1442
1511
|
this.sendJson(res, 200, response);
|
|
1443
1512
|
return;
|
|
1444
1513
|
}
|
|
1514
|
+
const warnFinding = {
|
|
1515
|
+
severity: "LOW",
|
|
1516
|
+
kind: "informational",
|
|
1517
|
+
type: "unknown_tool",
|
|
1518
|
+
agentId: event.agentId,
|
|
1519
|
+
agentName: event.agentName,
|
|
1520
|
+
description: `Unknown tool "${unknownName}" allowed (enforcement.unknownTools: warn) \u2014 not in Sentinel's recognized tool set; policy checks could not evaluate it.`,
|
|
1521
|
+
evidence: {
|
|
1522
|
+
action: event.action,
|
|
1523
|
+
target: unknownName,
|
|
1524
|
+
timestamp: event.timestamp,
|
|
1525
|
+
baselineComparison: "unknown_tool_allowed_warn"
|
|
1526
|
+
},
|
|
1527
|
+
recommendation: `Add "${unknownName}" to enforcement.allowUnknownTools (or update @tuent/sentinel) to clear this warning, or switch enforcement.unknownTools to deny.`,
|
|
1528
|
+
timestamp: event.timestamp,
|
|
1529
|
+
decision: "allow",
|
|
1530
|
+
dedupKey: unknownName
|
|
1531
|
+
};
|
|
1532
|
+
await this.sentinel.logFinding(routingId, warnFinding);
|
|
1533
|
+
}
|
|
1534
|
+
let suppressForbiddenBasename = false;
|
|
1535
|
+
if (event.action === "command_exec" && event.targets && event.targets.length > 0) {
|
|
1536
|
+
const literalCommand = event.targets[0] ?? "";
|
|
1537
|
+
const decodedImplicated = event.targets.slice(1).some((t) => scanBashCommand(t, FORBIDDEN_BASENAMES).matched);
|
|
1538
|
+
suppressForbiddenBasename = isPositionallySafeMention(literalCommand) && !decodedImplicated;
|
|
1539
|
+
}
|
|
1540
|
+
if (event.action === "command_exec" && event.targets && event.targets.length > 0 && !suppressForbiddenBasename) {
|
|
1541
|
+
const allL2Hits = [];
|
|
1542
|
+
for (const scanTarget of event.targets) {
|
|
1543
|
+
const scan = scanBashCommand(scanTarget, FORBIDDEN_BASENAMES);
|
|
1544
|
+
if (scan.matched) allL2Hits.push(...scan.hits);
|
|
1545
|
+
}
|
|
1445
1546
|
const allTokenPaths = [];
|
|
1446
1547
|
let anyUnparseable = false;
|
|
1447
1548
|
let anyDangerousConstruct = false;
|
|
@@ -1463,6 +1564,40 @@ var SentinelGateway = class {
|
|
|
1463
1564
|
}
|
|
1464
1565
|
if (matchedPath) break;
|
|
1465
1566
|
}
|
|
1567
|
+
if (allL2Hits.length > 0) {
|
|
1568
|
+
const { mentionOnly } = classifyDeny(event.targets[0] ?? "", {
|
|
1569
|
+
l2Hits: allL2Hits,
|
|
1570
|
+
hasL1Hit: matchedPath !== null,
|
|
1571
|
+
unparseable: anyUnparseable,
|
|
1572
|
+
hasDangerousConstruct: anyDangerousConstruct
|
|
1573
|
+
});
|
|
1574
|
+
const targetKey = matchedPath ?? `l2:${[...new Set(allL2Hits)].sort().join(",")}`;
|
|
1575
|
+
const finding = {
|
|
1576
|
+
severity: "HIGH",
|
|
1577
|
+
kind: "actionable",
|
|
1578
|
+
type: "unauthorized_target",
|
|
1579
|
+
agentId: event.agentId,
|
|
1580
|
+
agentName: event.agentName,
|
|
1581
|
+
description: `Bash command references forbidden basename: ${allL2Hits.join(", ")}`,
|
|
1582
|
+
evidence: {
|
|
1583
|
+
action: event.action,
|
|
1584
|
+
target: allL2Hits[0],
|
|
1585
|
+
timestamp: event.timestamp,
|
|
1586
|
+
baselineComparison: "credentials_exfil_attempt"
|
|
1587
|
+
},
|
|
1588
|
+
recommendation: "Review the command for credential access or exfiltration. If legitimate, use existing policy exception mechanisms.",
|
|
1589
|
+
timestamp: event.timestamp,
|
|
1590
|
+
decision: "deny",
|
|
1591
|
+
mentionOnly,
|
|
1592
|
+
dedupKey: event.primaryTarget,
|
|
1593
|
+
targetKey
|
|
1594
|
+
};
|
|
1595
|
+
await this.sentinel.handleGatewayDeny(routingId, finding);
|
|
1596
|
+
this.telemetry.recordToolCall(event.action, "pre", "blocked", 0);
|
|
1597
|
+
const response = translator.formatPreToolUseResponse({ blocked: true, finding });
|
|
1598
|
+
this.sendJson(res, 200, response);
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1466
1601
|
if (matchedPath) {
|
|
1467
1602
|
const finding = {
|
|
1468
1603
|
severity: "HIGH",
|
|
@@ -1479,7 +1614,12 @@ var SentinelGateway = class {
|
|
|
1479
1614
|
},
|
|
1480
1615
|
recommendation: "Review the command for credential or sensitive file access. If legitimate, use existing policy exception mechanisms.",
|
|
1481
1616
|
timestamp: event.timestamp,
|
|
1482
|
-
decision: "deny"
|
|
1617
|
+
decision: "deny",
|
|
1618
|
+
// A resolved path-glob hit is a file target — never a mention.
|
|
1619
|
+
mentionOnly: false,
|
|
1620
|
+
dedupKey: event.primaryTarget,
|
|
1621
|
+
// F-5a: the resolved forbidden path IS the target identity here.
|
|
1622
|
+
targetKey: matchedPath
|
|
1483
1623
|
};
|
|
1484
1624
|
await this.sentinel.handleGatewayDeny(routingId, finding);
|
|
1485
1625
|
this.telemetry.recordToolCall(event.action, "pre", "blocked", 0);
|
|
@@ -1909,17 +2049,20 @@ var SentinelGateway = class {
|
|
|
1909
2049
|
};
|
|
1910
2050
|
async function runGatewayDaemon({
|
|
1911
2051
|
policyPath,
|
|
1912
|
-
port = DEFAULT_PORT
|
|
2052
|
+
port = DEFAULT_PORT,
|
|
2053
|
+
buildId
|
|
1913
2054
|
}) {
|
|
1914
|
-
const { Sentinel: SentinelClass } = await import("./Sentinel-
|
|
2055
|
+
const { Sentinel: SentinelClass } = await import("./Sentinel-5CQ6HKXS.js");
|
|
1915
2056
|
const { writePidFile, writeReleaseToken } = await import("./pidManager-DOGVN6ZT.js");
|
|
1916
2057
|
const { homedir } = await import("os");
|
|
1917
2058
|
const { randomBytes } = await import("crypto");
|
|
1918
|
-
const { loadPolicy: loadPolicy2, policyToRole: policyToRole2 } = await import("./policyLoader-
|
|
2059
|
+
const { loadPolicy: loadPolicy2, policyToRole: policyToRole2, policyToConfig: policyToConfig2 } = await import("./policyLoader-KZL2U4M2.js");
|
|
1919
2060
|
const sentinel = await SentinelClass.fromPolicy(policyPath);
|
|
1920
2061
|
const baseline = await sentinel.computeBaseline("claude-code");
|
|
1921
2062
|
sentinel.setBaseline("claude-code", baseline);
|
|
1922
|
-
const
|
|
2063
|
+
const operatorPolicy = await loadPolicy2(policyPath);
|
|
2064
|
+
const operatorCeiling = policyToRole2(operatorPolicy);
|
|
2065
|
+
const operatorConfig = policyToConfig2(operatorPolicy);
|
|
1923
2066
|
const releaseToken = randomBytes(32).toString("hex");
|
|
1924
2067
|
const gateway = new SentinelGateway({
|
|
1925
2068
|
port,
|
|
@@ -1929,7 +2072,10 @@ async function runGatewayDaemon({
|
|
|
1929
2072
|
workspaceIsolation: process.env.SENTINEL_WORKSPACE_ISOLATION !== "0",
|
|
1930
2073
|
operatorCeiling,
|
|
1931
2074
|
home: homedir(),
|
|
1932
|
-
releaseToken
|
|
2075
|
+
releaseToken,
|
|
2076
|
+
unknownTools: operatorConfig.enforcement?.unknownTools,
|
|
2077
|
+
allowUnknownTools: operatorConfig.enforcement?.allowUnknownTools,
|
|
2078
|
+
buildId
|
|
1933
2079
|
});
|
|
1934
2080
|
await gateway.start();
|
|
1935
2081
|
const home = homedir();
|
|
@@ -1942,4 +2088,4 @@ export {
|
|
|
1942
2088
|
SentinelGateway,
|
|
1943
2089
|
runGatewayDaemon
|
|
1944
2090
|
};
|
|
1945
|
-
//# sourceMappingURL=chunk-
|
|
2091
|
+
//# sourceMappingURL=chunk-G74MMDKA.js.map
|