@drakon-systems/shieldcortex-realtime 4.51.0 → 4.52.0
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/dist/index.js +4 -0
- package/dist/interceptor.js +19 -2
- package/dist/openclaw.plugin.json +1 -1
- package/index.ts +5 -0
- package/interceptor.ts +50 -12
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2761,6 +2761,10 @@ function resolveBrokerRuntime(defenceMod, rawBrokerConfig, api) {
|
|
|
2761
2761
|
return {
|
|
2762
2762
|
config,
|
|
2763
2763
|
runJudge: defenceMod.runJudge,
|
|
2764
|
+
// #143 residual, and deliberately NOT in `needed`: an older shieldcortex
|
|
2765
|
+
// build has runJudge alone, and the interceptor falls back to it. Missing
|
|
2766
|
+
// it costs an audit field, never a gate.
|
|
2767
|
+
runJudgeDetailed: typeof defenceMod.runJudgeDetailed === 'function' ? defenceMod.runJudgeDetailed : undefined,
|
|
2764
2768
|
brokerDecision: defenceMod.brokerDecision,
|
|
2765
2769
|
timeoutOutcome: defenceMod.timeoutOutcome,
|
|
2766
2770
|
approvalTimeoutMs: typeof defenceMod.approvalTimeoutMs === 'function' ? defenceMod.approvalTimeoutMs : undefined,
|
package/dist/interceptor.js
CHANGED
|
@@ -602,13 +602,29 @@ export function createInterceptor(config, pipeline, options) {
|
|
|
602
602
|
timeoutMs: broker.config.judgeTimeoutMs,
|
|
603
603
|
});
|
|
604
604
|
let judge = null;
|
|
605
|
+
// Only set when a judge pass actually ran: "no seam on this build" and
|
|
606
|
+
// "budget spent" are not timeouts, and claiming otherwise would be the
|
|
607
|
+
// same overclaim in the audit that this residual removes from doctor.
|
|
608
|
+
let judgeMeta;
|
|
605
609
|
if (invoke && judgeLimiter.shouldAllow()) {
|
|
606
|
-
|
|
610
|
+
const request = {
|
|
607
611
|
tool: context.toolName,
|
|
608
612
|
toolInput: context.arguments,
|
|
609
613
|
verdict: { severity: v.severity, action: v.action, reason: v.reason, signals: v.signals },
|
|
610
614
|
sessionSummary: buildSessionSummary(),
|
|
611
|
-
}
|
|
615
|
+
};
|
|
616
|
+
const opts = { timeoutMs: broker.config.judgeTimeoutMs };
|
|
617
|
+
if (typeof broker.runJudgeDetailed === 'function') {
|
|
618
|
+
const detailed = await broker.runJudgeDetailed(request, invoke, opts);
|
|
619
|
+
judge = detailed?.result ?? null;
|
|
620
|
+
judgeMeta = {
|
|
621
|
+
timedOut: detailed?.timedOut === true,
|
|
622
|
+
error: typeof detailed?.error === 'string' ? detailed.error : null,
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
judge = await broker.runJudge(request, invoke, opts);
|
|
627
|
+
}
|
|
612
628
|
}
|
|
613
629
|
else if (invoke) {
|
|
614
630
|
log.warn(`[shieldcortex] approval broker: judge budget spent this minute — holding ${context.toolName} for the operator`);
|
|
@@ -618,6 +634,7 @@ export function createInterceptor(config, pipeline, options) {
|
|
|
618
634
|
toolInput: context.arguments,
|
|
619
635
|
verdict: v,
|
|
620
636
|
judge,
|
|
637
|
+
...(judgeMeta ? { judgeMeta } : {}),
|
|
621
638
|
policy: {
|
|
622
639
|
allowPreClear: broker.config.allowPreClear,
|
|
623
640
|
preClearConfidence: broker.config.preClearConfidence,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shieldcortex-realtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.52.0",
|
|
4
4
|
"name": "ShieldCortex Real-time Scanner",
|
|
5
5
|
"description": "Real-time defence scanning on LLM input, memory extraction on LLM output, and active tool call interception with approval gating.",
|
|
6
6
|
"kind": null,
|
package/index.ts
CHANGED
|
@@ -3300,6 +3300,11 @@ function resolveBrokerRuntime(
|
|
|
3300
3300
|
return {
|
|
3301
3301
|
config,
|
|
3302
3302
|
runJudge: defenceMod.runJudge,
|
|
3303
|
+
// #143 residual, and deliberately NOT in `needed`: an older shieldcortex
|
|
3304
|
+
// build has runJudge alone, and the interceptor falls back to it. Missing
|
|
3305
|
+
// it costs an audit field, never a gate.
|
|
3306
|
+
runJudgeDetailed:
|
|
3307
|
+
typeof defenceMod.runJudgeDetailed === 'function' ? defenceMod.runJudgeDetailed : undefined,
|
|
3303
3308
|
brokerDecision: defenceMod.brokerDecision,
|
|
3304
3309
|
timeoutOutcome: defenceMod.timeoutOutcome,
|
|
3305
3310
|
approvalTimeoutMs: typeof defenceMod.approvalTimeoutMs === 'function' ? defenceMod.approvalTimeoutMs : undefined,
|
package/interceptor.ts
CHANGED
|
@@ -53,8 +53,15 @@ export interface ToolGuardVerdictLike {
|
|
|
53
53
|
action: string;
|
|
54
54
|
reason: string;
|
|
55
55
|
signals: string[];
|
|
56
|
-
/** Rule → matched-span evidence behind `signals` (issue #192).
|
|
57
|
-
|
|
56
|
+
/** Rule → matched-span evidence behind `signals` (issue #192).
|
|
57
|
+
* #184: optional source/line/chain when the match came from folded script. */
|
|
58
|
+
matches?: Array<{
|
|
59
|
+
signal: string;
|
|
60
|
+
span: string;
|
|
61
|
+
source?: string;
|
|
62
|
+
line?: number;
|
|
63
|
+
chain?: string;
|
|
64
|
+
}>;
|
|
58
65
|
/** Files the reviewed-script allowlist exempted from folding (#189). */
|
|
59
66
|
reviewedScripts?: string[];
|
|
60
67
|
}
|
|
@@ -100,6 +107,10 @@ export interface BrokerAuditLike {
|
|
|
100
107
|
judgeConfidence: number | null;
|
|
101
108
|
injectionSuspected: boolean;
|
|
102
109
|
inContext: boolean | null;
|
|
110
|
+
/** #143 residual — "the judge never answered" told apart from "the judge said
|
|
111
|
+
* hold". Audit only; neither field can reach an outcome. */
|
|
112
|
+
judgeTimedOut?: boolean;
|
|
113
|
+
judgeUnavailableReason?: string | null;
|
|
103
114
|
reason: string;
|
|
104
115
|
}
|
|
105
116
|
|
|
@@ -135,11 +146,26 @@ export interface BrokerRuntime {
|
|
|
135
146
|
invoke: ModelInvokerLike,
|
|
136
147
|
opts?: { timeoutMs?: number },
|
|
137
148
|
) => Promise<JudgeResultLike | null>;
|
|
149
|
+
/** #143 residual, and OPTIONAL: this plugin is built across a package
|
|
150
|
+
* boundary, so a main package from before the residual injects `runJudge`
|
|
151
|
+
* alone and the pass below falls back to it. Absent costs an audit field,
|
|
152
|
+
* never a gate. */
|
|
153
|
+
runJudgeDetailed?: (
|
|
154
|
+
req: {
|
|
155
|
+
tool: string;
|
|
156
|
+
toolInput: unknown;
|
|
157
|
+
verdict: { severity: string; action: string; reason: string; signals: string[] };
|
|
158
|
+
sessionSummary?: string;
|
|
159
|
+
},
|
|
160
|
+
invoke: ModelInvokerLike,
|
|
161
|
+
opts?: { timeoutMs?: number },
|
|
162
|
+
) => Promise<{ result: JudgeResultLike | null; timedOut: boolean; error?: string }>;
|
|
138
163
|
brokerDecision: (input: {
|
|
139
164
|
tool: string;
|
|
140
165
|
toolInput: unknown;
|
|
141
166
|
verdict: ToolGuardVerdictLike;
|
|
142
167
|
judge: JudgeResultLike | null;
|
|
168
|
+
judgeMeta?: { timedOut?: boolean; error?: string | null };
|
|
143
169
|
policy?: { allowPreClear: boolean; preClearConfidence: number };
|
|
144
170
|
}) => BrokerDecisionLike;
|
|
145
171
|
timeoutOutcome: (decision: BrokerDecisionLike) => 'approve' | 'deny';
|
|
@@ -934,17 +960,28 @@ export function createInterceptor(
|
|
|
934
960
|
});
|
|
935
961
|
|
|
936
962
|
let judge: JudgeResultLike | null = null;
|
|
963
|
+
// Only set when a judge pass actually ran: "no seam on this build" and
|
|
964
|
+
// "budget spent" are not timeouts, and claiming otherwise would be the
|
|
965
|
+
// same overclaim in the audit that this residual removes from doctor.
|
|
966
|
+
let judgeMeta: { timedOut?: boolean; error?: string | null } | undefined;
|
|
937
967
|
if (invoke && judgeLimiter.shouldAllow()) {
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
968
|
+
const request = {
|
|
969
|
+
tool: context.toolName,
|
|
970
|
+
toolInput: context.arguments,
|
|
971
|
+
verdict: { severity: v.severity, action: v.action, reason: v.reason, signals: v.signals },
|
|
972
|
+
sessionSummary: buildSessionSummary(),
|
|
973
|
+
};
|
|
974
|
+
const opts = { timeoutMs: broker.config.judgeTimeoutMs };
|
|
975
|
+
if (typeof broker.runJudgeDetailed === 'function') {
|
|
976
|
+
const detailed = await broker.runJudgeDetailed(request, invoke, opts);
|
|
977
|
+
judge = detailed?.result ?? null;
|
|
978
|
+
judgeMeta = {
|
|
979
|
+
timedOut: detailed?.timedOut === true,
|
|
980
|
+
error: typeof detailed?.error === 'string' ? detailed.error : null,
|
|
981
|
+
};
|
|
982
|
+
} else {
|
|
983
|
+
judge = await broker.runJudge(request, invoke, opts);
|
|
984
|
+
}
|
|
948
985
|
} else if (invoke) {
|
|
949
986
|
log.warn(`[shieldcortex] approval broker: judge budget spent this minute — holding ${context.toolName} for the operator`);
|
|
950
987
|
}
|
|
@@ -954,6 +991,7 @@ export function createInterceptor(
|
|
|
954
991
|
toolInput: context.arguments,
|
|
955
992
|
verdict: v,
|
|
956
993
|
judge,
|
|
994
|
+
...(judgeMeta ? { judgeMeta } : {}),
|
|
957
995
|
policy: {
|
|
958
996
|
allowPreClear: broker.config.allowPreClear,
|
|
959
997
|
preClearConfidence: broker.config.preClearConfidence,
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shieldcortex-realtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.52.0",
|
|
4
4
|
"name": "ShieldCortex Real-time Scanner",
|
|
5
5
|
"description": "Real-time defence scanning on LLM input, memory extraction on LLM output, and active tool call interception with approval gating.",
|
|
6
6
|
"kind": null,
|
package/package.json
CHANGED