@intutic/mcp-governance-proxy 2.2.0 → 2.4.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/README.md +8 -7
- package/dist/agentTools.d.ts +83 -0
- package/dist/agentTools.d.ts.map +1 -0
- package/dist/agentTools.js +170 -0
- package/dist/agentTools.js.map +1 -0
- package/dist/anomaly/detectors.js +1 -1
- package/dist/anomaly/detectors.js.map +1 -1
- package/dist/approvalHold.d.ts +8 -7
- package/dist/approvalHold.d.ts.map +1 -1
- package/dist/approvalHold.js +7 -6
- package/dist/approvalHold.js.map +1 -1
- package/dist/budget.d.ts +133 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +191 -0
- package/dist/budget.js.map +1 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/daemon/healthMonitor.d.ts.map +1 -1
- package/dist/daemon/healthMonitor.js +0 -1
- package/dist/daemon/healthMonitor.js.map +1 -1
- package/dist/daemon/index.d.ts +0 -2
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +0 -2
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/policyCache.d.ts +22 -3
- package/dist/daemon/policyCache.d.ts.map +1 -1
- package/dist/daemon/policyCache.js +38 -15
- package/dist/daemon/policyCache.js.map +1 -1
- package/dist/daemon/socketServer.d.ts +0 -1
- package/dist/daemon/socketServer.d.ts.map +1 -1
- package/dist/daemon/socketServer.js +0 -1
- package/dist/daemon/socketServer.js.map +1 -1
- package/dist/daemon/statusReporter.d.ts.map +1 -1
- package/dist/daemon/statusReporter.js +0 -1
- package/dist/daemon/statusReporter.js.map +1 -1
- package/dist/daemon/telemetryBatcher.d.ts.map +1 -1
- package/dist/daemon/telemetryBatcher.js +0 -1
- package/dist/daemon/telemetryBatcher.js.map +1 -1
- package/dist/daemonClient.d.ts.map +1 -1
- package/dist/daemonClient.js +0 -1
- package/dist/daemonClient.js.map +1 -1
- package/dist/dlp.d.ts +32 -3
- package/dist/dlp.d.ts.map +1 -1
- package/dist/dlp.js +116 -18
- package/dist/dlp.js.map +1 -1
- package/dist/dlpPii.d.ts +66 -0
- package/dist/dlpPii.d.ts.map +1 -0
- package/dist/dlpPii.js +235 -0
- package/dist/dlpPii.js.map +1 -0
- package/dist/emitter.d.ts +65 -3
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +13 -1
- package/dist/emitter.js.map +1 -1
- package/dist/guardedValkey.d.ts +40 -0
- package/dist/guardedValkey.d.ts.map +1 -0
- package/dist/guardedValkey.js +84 -0
- package/dist/guardedValkey.js.map +1 -0
- package/dist/httpJson.d.ts +7 -0
- package/dist/httpJson.d.ts.map +1 -1
- package/dist/httpJson.js +39 -0
- package/dist/httpJson.js.map +1 -1
- package/dist/injection.js +1 -1
- package/dist/interceptor.d.ts +65 -10
- package/dist/interceptor.d.ts.map +1 -1
- package/dist/interceptor.js +190 -69
- package/dist/interceptor.js.map +1 -1
- package/dist/policy.d.ts +37 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +62 -3
- package/dist/policy.js.map +1 -1
- package/dist/proxy.d.ts +30 -9
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +127 -57
- package/dist/proxy.js.map +1 -1
- package/dist/refusals.d.ts +26 -0
- package/dist/refusals.d.ts.map +1 -0
- package/dist/refusals.js +43 -0
- package/dist/refusals.js.map +1 -0
- package/dist/registryObserver.d.ts +9 -5
- package/dist/registryObserver.d.ts.map +1 -1
- package/dist/registryObserver.js +19 -8
- package/dist/registryObserver.js.map +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +1 -1
- package/dist/sessionScope.d.ts +1 -1
- package/dist/sessionScope.js +1 -1
- package/dist/sessionStore.d.ts +10 -23
- package/dist/sessionStore.d.ts.map +1 -1
- package/dist/sessionStore.js +17 -76
- package/dist/sessionStore.js.map +1 -1
- package/dist/wasm/cloudRules.d.ts +138 -0
- package/dist/wasm/cloudRules.d.ts.map +1 -0
- package/dist/wasm/cloudRules.js +242 -0
- package/dist/wasm/cloudRules.js.map +1 -0
- package/dist/wasm/context.d.ts +10 -0
- package/dist/wasm/context.d.ts.map +1 -1
- package/dist/wasm/context.js +27 -0
- package/dist/wasm/context.js.map +1 -1
- package/dist/wasm/hostImports.d.ts +3 -3
- package/dist/wasm/hostImports.d.ts.map +1 -1
- package/dist/wasm/hostImports.js +8 -7
- package/dist/wasm/hostImports.js.map +1 -1
- package/dist/wasm/loader.d.ts +10 -1
- package/dist/wasm/loader.d.ts.map +1 -1
- package/dist/wasm/loader.js +2 -0
- package/dist/wasm/loader.js.map +1 -1
- package/dist/wasm/referencedFiles.d.ts +29 -4
- package/dist/wasm/referencedFiles.d.ts.map +1 -1
- package/dist/wasm/referencedFiles.js +48 -21
- package/dist/wasm/referencedFiles.js.map +1 -1
- package/dist/wasm/runner.d.ts +169 -31
- package/dist/wasm/runner.d.ts.map +1 -1
- package/dist/wasm/runner.js +298 -83
- package/dist/wasm/runner.js.map +1 -1
- package/dist/wasm/watch.js +1 -1
- package/dist/wasm/worker.d.ts +10 -6
- package/dist/wasm/worker.d.ts.map +1 -1
- package/dist/wasm/worker.js +93 -9
- package/dist/wasm/worker.js.map +1 -1
- package/package.json +5 -4
- package/dist/toolPoison.d.ts +0 -32
- package/dist/toolPoison.d.ts.map +0 -1
- package/dist/toolPoison.js +0 -81
- package/dist/toolPoison.js.map +0 -1
- package/dist/wasm/fuel.d.ts +0 -35
- package/dist/wasm/fuel.d.ts.map +0 -1
- package/dist/wasm/fuel.js +0 -299
- package/dist/wasm/fuel.js.map +0 -1
- package/dist/wasm/memoryCap.d.ts +0 -21
- package/dist/wasm/memoryCap.d.ts.map +0 -1
- package/dist/wasm/memoryCap.js +0 -54
- package/dist/wasm/memoryCap.js.map +0 -1
- package/dist/wasm/wasmBinary.d.ts +0 -25
- package/dist/wasm/wasmBinary.d.ts.map +0 -1
- package/dist/wasm/wasmBinary.js +0 -100
- package/dist/wasm/wasmBinary.js.map +0 -1
package/dist/registryObserver.js
CHANGED
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* the proxy ever sees a server's tools/list. So the proxy reports its own
|
|
8
8
|
* server: once at start (so a server refused under a `deny` default still
|
|
9
9
|
* reaches the approval queue, even if its tools/list never gets through) and
|
|
10
|
-
* again whenever the
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* again whenever the tools it sees change — a tool added or removed, or a
|
|
11
|
+
* description or input schema changed. The report carries the tool names (for
|
|
12
|
+
* the registry's per-tool toggles) and the definitions as the server declared
|
|
13
|
+
* them, before curation, which the control plane compares with the last ones
|
|
14
|
+
* it stored to score the change's risk. The control plane creates a candidate
|
|
15
|
+
* on first sight and notifies the workspace.
|
|
13
16
|
*
|
|
14
17
|
* Best-effort and quiet: a failed report costs one registry refresh, never a
|
|
15
18
|
* tool call.
|
|
@@ -32,22 +35,30 @@ export class RegistryObserver {
|
|
|
32
35
|
this.transport = transport;
|
|
33
36
|
}
|
|
34
37
|
/**
|
|
35
|
-
* Reports the server, with
|
|
38
|
+
* Reports the server, with its tools when known. A report identical to the
|
|
36
39
|
* last successful one is skipped. Without an API key, or without a
|
|
37
40
|
* `--server-name` to report, there is nothing the registry could record.
|
|
38
41
|
*/
|
|
39
42
|
async observe(tools) {
|
|
40
43
|
if (!this.apiKey || this.serverName === 'unknown')
|
|
41
44
|
return;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
let definitions;
|
|
46
|
+
if (tools) {
|
|
47
|
+
// One entry per name, the first declared — the rule the risk score matches by.
|
|
48
|
+
const byName = new Map();
|
|
49
|
+
for (const t of tools)
|
|
50
|
+
if (!byName.has(t.name))
|
|
51
|
+
byName.set(t.name, t);
|
|
52
|
+
definitions = [...byName.values()].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
53
|
+
}
|
|
54
|
+
const key = JSON.stringify(definitions ?? null);
|
|
55
|
+
if (key === this.lastReported || (definitions === undefined && this.lastReported !== null))
|
|
45
56
|
return;
|
|
46
57
|
try {
|
|
47
58
|
await postJson(`${this.controlPlaneUrl}/api/v1/mcp/servers/observe`, this.apiKey, {
|
|
48
59
|
serverName: this.serverName,
|
|
49
60
|
transport: this.transport,
|
|
50
|
-
...(
|
|
61
|
+
...(definitions ? { tools: definitions.map((t) => t.name), toolDefinitions: definitions } : {}),
|
|
51
62
|
});
|
|
52
63
|
this.lastReported = key;
|
|
53
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registryObserver.js","sourceRoot":"","sources":["../src/registryObserver.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registryObserver.js","sourceRoot":"","sources":["../src/registryObserver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,kBAAkB,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,MAAM,GAAG,GAAG,YAAY,CAAC,oBAAoB,CAAC,CAAA;AAE9C,MAAM,OAAO,gBAAgB;IAIR;IACA;IACA;IACA;IANX,YAAY,GAAkB,IAAI,CAAA;IAE1C,YACmB,eAAuB,EACvB,MAAc,EACd,UAAkB,EAClB,SAAmC;QAHnC,oBAAe,GAAf,eAAe,CAAQ;QACvB,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAQ;QAClB,cAAS,GAAT,SAAS,CAA0B;IACnD,CAAC;IAEJ;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,KAAoC;QAChD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE,OAAM;QACzD,IAAI,WAA4C,CAAA;QAChD,IAAI,KAAK,EAAE,CAAC;YACV,+EAA+E;YAC/E,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAA;YACnD,KAAK,MAAM,CAAC,IAAI,KAAK;gBAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YACrE,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACrG,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,IAAI,CAAC,CAAA;QAC/C,IAAI,GAAG,KAAK,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC;YAAE,OAAM;QAClG,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC,eAAe,6BAA6B,EAAE,IAAI,CAAC,MAAM,EAAE;gBAChF,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChG,CAAC,CAAA;YACF,IAAI,CAAC,YAAY,GAAG,GAAG,CAAA;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,yBAAyB,EAAE,GAAG,EAAG,GAAa,CAAC,OAAO,EAAE,EAAE,kDAAkD,CAAC,CAAA;QACnI,CAAC;IACH,CAAC;CACF"}
|
package/dist/session.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* process (`mcpAutoWrite.ts`'s `wrapWithProxy`, in both `per-session` and
|
|
9
9
|
* `daemon` mode), so one harness session runs one proxy per wrapped server.
|
|
10
10
|
* This class holds the tool-call sequence and the per-detector reask counters
|
|
11
|
-
* the anomaly detectors read. Until Wave 5.3
|
|
11
|
+
* the anomaly detectors read. Until Wave 5.3 that state was
|
|
12
12
|
* per-process only — a cross-server ping-pong was invisible, a reask budget
|
|
13
13
|
* reset per server and per restart — and the module doc claimed there was
|
|
14
14
|
* "no second instance to share state with", which was never true of the
|
package/dist/session.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* process (`mcpAutoWrite.ts`'s `wrapWithProxy`, in both `per-session` and
|
|
9
9
|
* `daemon` mode), so one harness session runs one proxy per wrapped server.
|
|
10
10
|
* This class holds the tool-call sequence and the per-detector reask counters
|
|
11
|
-
* the anomaly detectors read. Until Wave 5.3
|
|
11
|
+
* the anomaly detectors read. Until Wave 5.3 that state was
|
|
12
12
|
* per-process only — a cross-server ping-pong was invisible, a reask budget
|
|
13
13
|
* reset per server and per restart — and the module doc claimed there was
|
|
14
14
|
* "no second instance to share state with", which was never true of the
|
package/dist/sessionScope.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* sessionScope.ts — the shared-window scope a proxy process derives for
|
|
3
|
-
* itself (
|
|
3
|
+
* itself (Wave 5.3).
|
|
4
4
|
*
|
|
5
5
|
* The sync daemon wraps EACH MCP server entry with its own proxy process, so
|
|
6
6
|
* one harness session runs several `McpGovernanceProxy` processes at once —
|
package/dist/sessionScope.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* sessionScope.ts — the shared-window scope a proxy process derives for
|
|
3
|
-
* itself (
|
|
3
|
+
* itself (Wave 5.3).
|
|
4
4
|
*
|
|
5
5
|
* The sync daemon wraps EACH MCP server entry with its own proxy process, so
|
|
6
6
|
* one harness session runs several `McpGovernanceProxy` processes at once —
|
package/dist/sessionStore.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* sessionStore.ts — the Valkey-backed session window the sibling proxy
|
|
3
|
-
* processes of one harness session share (
|
|
3
|
+
* processes of one harness session share (Wave 5.3).
|
|
4
4
|
*
|
|
5
5
|
* The Rust LLM proxy keeps a session's tool-call history in Valkey
|
|
6
6
|
* (`store/valkey.rs`: a capped LIST for the sequence, a ZSET for the 60 s
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Never a hard dependency. Every operation fails open to `undefined`/`false`
|
|
14
14
|
* and the caller (`SessionState`) falls back to its in-process window: when
|
|
15
|
-
* no URL is configured, when the client is not connected (
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* no URL is configured, when the client is not connected (so an absent
|
|
16
|
+
* Valkey adds no latency), when a call takes longer than
|
|
17
|
+
* `VALKEY_COMMAND_TIMEOUT_MS`, or on any error — the guard every command on
|
|
18
|
+
* the proxy's one Valkey connection goes through (guardedValkey.ts). The
|
|
19
|
+
* proxy behaves exactly as before Wave 5.3 in every one of those cases.
|
|
19
20
|
*
|
|
20
21
|
* @module
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
-
export declare const SHARED_WINDOW_TIMEOUT_MS = 200;
|
|
23
|
+
import type { GuardedValkey } from './guardedValkey.js';
|
|
24
24
|
/** Sliding lifetime of the sequence and call-window keys — the Rust `TOOL_SEQUENCE_TTL_SECS`. */
|
|
25
25
|
export declare const SESSION_WINDOW_TTL_SECS = 86400;
|
|
26
26
|
/** Lifetime of a reask allowance, set when the counter is created and never refreshed —
|
|
@@ -44,26 +44,13 @@ export interface SharedSessionStore {
|
|
|
44
44
|
recordCall(scope: string, toolName: string, nowMs: number): Promise<boolean>;
|
|
45
45
|
/** The count including this trip, or `undefined` when unavailable. */
|
|
46
46
|
incrReaskAttempt(scope: string, key: string): Promise<number | undefined>;
|
|
47
|
-
close(): Promise<void>;
|
|
48
|
-
}
|
|
49
|
-
export interface ValkeySessionStoreOptions {
|
|
50
|
-
timeoutMs?: number;
|
|
51
47
|
}
|
|
52
48
|
export declare class ValkeySessionStore implements SharedSessionStore {
|
|
53
|
-
private readonly
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
constructor(url: string, opts?: ValkeySessionStoreOptions);
|
|
49
|
+
private readonly valkey;
|
|
50
|
+
/** The proxy's one Valkey connection, shared with its call budgets; the proxy closes it. */
|
|
51
|
+
constructor(valkey: GuardedValkey);
|
|
57
52
|
readWindow(scope: string, nowMs: number, windowMs: number): Promise<SharedWindowSnapshot | undefined>;
|
|
58
53
|
recordCall(scope: string, toolName: string, nowMs: number): Promise<boolean>;
|
|
59
54
|
incrReaskAttempt(scope: string, key: string): Promise<number | undefined>;
|
|
60
|
-
close(): Promise<void>;
|
|
61
|
-
/**
|
|
62
|
-
* The fail-open wrapper every operation goes through: nothing is attempted
|
|
63
|
-
* unless the client is connected, nothing waits longer than the timeout,
|
|
64
|
-
* and any failure is `undefined`.
|
|
65
|
-
*/
|
|
66
|
-
private guarded;
|
|
67
|
-
private warnOnce;
|
|
68
55
|
}
|
|
69
56
|
//# sourceMappingURL=sessionStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../src/sessionStore.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../src/sessionStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGvD,iGAAiG;AACjG,eAAO,MAAM,uBAAuB,QAAS,CAAA;AAC7C;0EAC0E;AAC1E,eAAO,MAAM,iBAAiB,OAAQ,CAAA;AAEtC,eAAO,MAAM,WAAW;4BACP,MAAM;4BACN,MAAM;4BACN,MAAM,OAAO,MAAM;CAC1B,CAAA;AAEV,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAA;IACrG,sEAAsE;IACtE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5E,sEAAsE;IACtE,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAC1E;AAED,qBAAa,kBAAmB,YAAW,kBAAkB;IAE/C,OAAO,CAAC,QAAQ,CAAC,MAAM;IADnC,4FAA4F;gBAC/D,MAAM,EAAE,aAAa;IAE5C,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC;IAcrG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB5E,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAQhF"}
|
package/dist/sessionStore.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* sessionStore.ts — the Valkey-backed session window the sibling proxy
|
|
3
|
-
* processes of one harness session share (
|
|
3
|
+
* processes of one harness session share (Wave 5.3).
|
|
4
4
|
*
|
|
5
5
|
* The Rust LLM proxy keeps a session's tool-call history in Valkey
|
|
6
6
|
* (`store/valkey.rs`: a capped LIST for the sequence, a ZSET for the 60 s
|
|
@@ -12,21 +12,16 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Never a hard dependency. Every operation fails open to `undefined`/`false`
|
|
14
14
|
* and the caller (`SessionState`) falls back to its in-process window: when
|
|
15
|
-
* no URL is configured, when the client is not connected (
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* no URL is configured, when the client is not connected (so an absent
|
|
16
|
+
* Valkey adds no latency), when a call takes longer than
|
|
17
|
+
* `VALKEY_COMMAND_TIMEOUT_MS`, or on any error — the guard every command on
|
|
18
|
+
* the proxy's one Valkey connection goes through (guardedValkey.ts). The
|
|
19
|
+
* proxy behaves exactly as before Wave 5.3 in every one of those cases.
|
|
19
20
|
*
|
|
20
21
|
* @module
|
|
21
22
|
*/
|
|
22
23
|
import * as node_crypto from 'node:crypto';
|
|
23
|
-
import { Redis } from 'ioredis';
|
|
24
|
-
import { createStderrLogger } from './stderrLog.js';
|
|
25
|
-
import { describeConnectionError } from './valkeyErrors.js';
|
|
26
24
|
import { TOOL_SEQUENCE_CAP } from './session.js';
|
|
27
|
-
const log = createStderrLogger('mcp-proxy.sessionStore');
|
|
28
|
-
/** A shared read or write that takes longer than this loses to the local window. */
|
|
29
|
-
export const SHARED_WINDOW_TIMEOUT_MS = 200;
|
|
30
25
|
/** Sliding lifetime of the sequence and call-window keys — the Rust `TOOL_SEQUENCE_TTL_SECS`. */
|
|
31
26
|
export const SESSION_WINDOW_TTL_SECS = 86_400;
|
|
32
27
|
/** Lifetime of a reask allowance, set when the counter is created and never refreshed —
|
|
@@ -38,26 +33,14 @@ export const sessionKeys = {
|
|
|
38
33
|
reask: (scope, key) => `v2:mcpsession:${scope}:reask:${key}`,
|
|
39
34
|
};
|
|
40
35
|
export class ValkeySessionStore {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.timeoutMs = opts.timeoutMs ?? SHARED_WINDOW_TIMEOUT_MS;
|
|
46
|
-
this.client = new Redis(url, {
|
|
47
|
-
lazyConnect: true,
|
|
48
|
-
// No offline queue: a command issued before the connection is up must
|
|
49
|
-
// fail now, not wait for a Valkey that may never answer.
|
|
50
|
-
enableOfflineQueue: false,
|
|
51
|
-
maxRetriesPerRequest: 1,
|
|
52
|
-
connectTimeout: 1000,
|
|
53
|
-
retryStrategy: (times) => Math.min(1000 * 2 ** Math.min(times, 5), 30_000),
|
|
54
|
-
});
|
|
55
|
-
this.client.on('error', (err) => this.warnOnce('Valkey session store unreachable', err));
|
|
56
|
-
void this.client.connect().catch((err) => this.warnOnce('Valkey session store connect failed', err));
|
|
36
|
+
valkey;
|
|
37
|
+
/** The proxy's one Valkey connection, shared with its call budgets; the proxy closes it. */
|
|
38
|
+
constructor(valkey) {
|
|
39
|
+
this.valkey = valkey;
|
|
57
40
|
}
|
|
58
41
|
async readWindow(scope, nowMs, windowMs) {
|
|
59
|
-
return this.
|
|
60
|
-
const results = await
|
|
42
|
+
return this.valkey.run(async (client) => {
|
|
43
|
+
const results = await client
|
|
61
44
|
.pipeline()
|
|
62
45
|
.lrange(sessionKeys.tools(scope), 0, -1)
|
|
63
46
|
.zcount(sessionKeys.calls(scope), nowMs - windowMs, '+inf')
|
|
@@ -70,10 +53,10 @@ export class ValkeySessionStore {
|
|
|
70
53
|
});
|
|
71
54
|
}
|
|
72
55
|
async recordCall(scope, toolName, nowMs) {
|
|
73
|
-
const done = await this.
|
|
56
|
+
const done = await this.valkey.run(async (client) => {
|
|
74
57
|
const tools = sessionKeys.tools(scope);
|
|
75
58
|
const calls = sessionKeys.calls(scope);
|
|
76
|
-
await
|
|
59
|
+
await client
|
|
77
60
|
.pipeline()
|
|
78
61
|
.rpush(tools, toolName)
|
|
79
62
|
.ltrim(tools, -TOOL_SEQUENCE_CAP, -1)
|
|
@@ -89,55 +72,13 @@ export class ValkeySessionStore {
|
|
|
89
72
|
return done === true;
|
|
90
73
|
}
|
|
91
74
|
async incrReaskAttempt(scope, key) {
|
|
92
|
-
return this.
|
|
75
|
+
return this.valkey.run(async (client) => {
|
|
93
76
|
const k = sessionKeys.reask(scope, key);
|
|
94
|
-
const n = await
|
|
77
|
+
const n = await client.incr(k);
|
|
95
78
|
if (n === 1)
|
|
96
|
-
await
|
|
79
|
+
await client.expire(k, REASK_WINDOW_SECS);
|
|
97
80
|
return n;
|
|
98
81
|
});
|
|
99
82
|
}
|
|
100
|
-
async close() {
|
|
101
|
-
try {
|
|
102
|
-
await this.client.quit();
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
this.client.disconnect();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* The fail-open wrapper every operation goes through: nothing is attempted
|
|
110
|
-
* unless the client is connected, nothing waits longer than the timeout,
|
|
111
|
-
* and any failure is `undefined`.
|
|
112
|
-
*/
|
|
113
|
-
async guarded(op) {
|
|
114
|
-
if (this.client.status !== 'ready')
|
|
115
|
-
return undefined;
|
|
116
|
-
let timer;
|
|
117
|
-
const timeout = new Promise((resolve) => {
|
|
118
|
-
timer = setTimeout(() => resolve(undefined), this.timeoutMs);
|
|
119
|
-
timer.unref();
|
|
120
|
-
});
|
|
121
|
-
try {
|
|
122
|
-
return await Promise.race([op(), timeout]);
|
|
123
|
-
}
|
|
124
|
-
catch (err) {
|
|
125
|
-
this.warnOnce('Valkey session store operation failed', err);
|
|
126
|
-
return undefined;
|
|
127
|
-
}
|
|
128
|
-
finally {
|
|
129
|
-
if (timer)
|
|
130
|
-
clearTimeout(timer);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
warnOnce(msg, err) {
|
|
134
|
-
const detail = { err: describeConnectionError(err) };
|
|
135
|
-
if (this.warned) {
|
|
136
|
-
log.debug(detail, msg);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
this.warned = true;
|
|
140
|
-
log.warn(detail, `${msg} — falling back to the per-process session window`);
|
|
141
|
-
}
|
|
142
83
|
}
|
|
143
84
|
//# sourceMappingURL=sessionStore.js.map
|
package/dist/sessionStore.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../src/sessionStore.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sessionStore.js","sourceRoot":"","sources":["../src/sessionStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wasm/cloudRules.ts — the workspace's custom rules from the control plane:
|
|
3
|
+
* the rules uploaded from the dashboard, the CLI or Terraform, which the LLM
|
|
4
|
+
* proxy enforces too.
|
|
5
|
+
*
|
|
6
|
+
* Port of the control-plane half of `packages/proxy/src/wasm/registry.rs`
|
|
7
|
+
* (`ensure_up_to_date`, `load_descriptor`, `report_refusal`). The descriptors
|
|
8
|
+
* arrive with the workspace policy this proxy already fetches (`wasmRules` on
|
|
9
|
+
* `GET /api/v1/sop/rules`, or on the MCP daemon's cached
|
|
10
|
+
* `GET /api/v1/policy/resolve`), so they refresh when the policy does. Each
|
|
11
|
+
* binary is fetched by the SHA-256 its descriptor names, only when no loaded
|
|
12
|
+
* rule already has that hash, and must hash to it before it is compiled:
|
|
13
|
+
* whoever can answer for that hash could otherwise swap a governance rule for
|
|
14
|
+
* one that allows everything.
|
|
15
|
+
*
|
|
16
|
+
* A version that cannot load — binary missing, hash mismatch, or a module the
|
|
17
|
+
* worker refuses — is reported once per hash and reason, and the version of
|
|
18
|
+
* that rule already loaded, if any, keeps enforcing. A control plane that
|
|
19
|
+
* cannot be reached for a binary leaves the whole loaded set as it was, as
|
|
20
|
+
* `registry.rs` does when its fetch fails.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import type { WasmRuleDescriptor, WasmRuleMode } from '@intutic/shared-types';
|
|
25
|
+
import type { WasmRuleRefusalDetail } from '../emitter.js';
|
|
26
|
+
import { type CompileBridge, type CompileFailureReason } from './loader.js';
|
|
27
|
+
/**
|
|
28
|
+
* Minimum time between attempts after a sync that could not reach the control
|
|
29
|
+
* plane or refused a version — the Rust proxy's 5-second rescan, so a binary
|
|
30
|
+
* published a moment after its descriptor is picked up as quickly there.
|
|
31
|
+
*/
|
|
32
|
+
export declare const CLOUD_RETRY_MS = 5000;
|
|
33
|
+
/** A control-plane rule loaded into the worker. */
|
|
34
|
+
export interface CloudRuleMeta {
|
|
35
|
+
/** The control plane's rule id (`wasm_…`), reported as is, like the Rust proxy does. */
|
|
36
|
+
ruleId: string;
|
|
37
|
+
name: string;
|
|
38
|
+
sha256: string;
|
|
39
|
+
priority: number;
|
|
40
|
+
mode: WasmRuleMode;
|
|
41
|
+
readsReferencedFiles: boolean;
|
|
42
|
+
rego: boolean;
|
|
43
|
+
/** Kept so a worker respawn can recompile without fetching again. */
|
|
44
|
+
bytes: Uint8Array;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Why a control-plane rule version was not loaded (`registry.rs`'s `Refusal`).
|
|
48
|
+
* `kind` is the reason the control plane files the incident under
|
|
49
|
+
* (`RULE_LOAD_FAILURE_REASONS`): a module the worker refuses carries the
|
|
50
|
+
* worker's own reason for it.
|
|
51
|
+
*/
|
|
52
|
+
export type CloudRuleRefusal = {
|
|
53
|
+
kind: 'missing';
|
|
54
|
+
} | {
|
|
55
|
+
kind: 'hash_mismatch';
|
|
56
|
+
actual: string;
|
|
57
|
+
} | {
|
|
58
|
+
kind: CompileFailureReason;
|
|
59
|
+
error: string;
|
|
60
|
+
};
|
|
61
|
+
/** One refused version, reported once per hash and reason. */
|
|
62
|
+
export interface CloudRuleRefusalReport {
|
|
63
|
+
descriptor: WasmRuleDescriptor;
|
|
64
|
+
refusal: CloudRuleRefusal;
|
|
65
|
+
/** Whether an earlier version of the rule stays in force. */
|
|
66
|
+
hasPrevious: boolean;
|
|
67
|
+
/** The sentence the incident and the log line carry, in the Rust proxy's words. */
|
|
68
|
+
description: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The binary a hash names: its bytes, or `null` when the control plane has
|
|
72
|
+
* none. Throws when the control plane cannot be asked.
|
|
73
|
+
*/
|
|
74
|
+
export type FetchRuleBinary = (sha256: string) => Promise<Uint8Array | null>;
|
|
75
|
+
/** What the sync needs from the worker, implemented by `WasmRunner`. */
|
|
76
|
+
export interface CloudRuleBridge extends CompileBridge {
|
|
77
|
+
/** A rule's loaded version changed: whatever the previous version did no longer counts against it. */
|
|
78
|
+
replaced(ruleId: string): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Fetches binaries from the control plane's rule store by hash. A 404 is a
|
|
82
|
+
* binary the control plane does not have; any other failure means it could
|
|
83
|
+
* not be asked.
|
|
84
|
+
*/
|
|
85
|
+
export declare function fetchRuleBinaryFrom(controlPlaneUrl: string, apiKey: string): FetchRuleBinary;
|
|
86
|
+
/** A refusal as the `wasm_rule_refused` event carries it. */
|
|
87
|
+
export declare function refusalDetail(report: CloudRuleRefusalReport): WasmRuleRefusalDetail;
|
|
88
|
+
/** Whether `bytes` are the binary `sha256` names; case is not significant in hex. */
|
|
89
|
+
export declare function binaryMatches(bytes: Uint8Array, sha256: string): {
|
|
90
|
+
matches: boolean;
|
|
91
|
+
actual: string;
|
|
92
|
+
};
|
|
93
|
+
export declare function describeRefusal(descriptor: WasmRuleDescriptor, refusal: CloudRuleRefusal, hasPrevious: boolean): string;
|
|
94
|
+
export declare class CloudRuleSet {
|
|
95
|
+
private readonly fetchBinary;
|
|
96
|
+
private readonly report;
|
|
97
|
+
private rules;
|
|
98
|
+
/** The descriptor list last applied, serialized; `undefined` until one has been. */
|
|
99
|
+
private appliedKey;
|
|
100
|
+
/** The list of the last attempt, applied or not, and when it ran. */
|
|
101
|
+
private attemptedKey;
|
|
102
|
+
private attemptedAt;
|
|
103
|
+
/** Whether the applied list left a version unloaded, so it is retried. */
|
|
104
|
+
private incomplete;
|
|
105
|
+
private syncing;
|
|
106
|
+
private readonly refusalsReported;
|
|
107
|
+
constructor(fetchBinary: FetchRuleBinary, report: (report: CloudRuleRefusalReport) => void);
|
|
108
|
+
/** Whether a descriptor list has been applied, so the loaded set is the workspace's. */
|
|
109
|
+
isLoaded(): boolean;
|
|
110
|
+
/** The loaded rules, in descriptor order. */
|
|
111
|
+
getRules(): readonly CloudRuleMeta[];
|
|
112
|
+
/**
|
|
113
|
+
* Brings the loaded set in line with `descriptors`.
|
|
114
|
+
*
|
|
115
|
+
* A changed list is applied before this resolves, so the call that follows
|
|
116
|
+
* a policy refresh is judged by the new set. Retrying versions the applied
|
|
117
|
+
* list refused, at most every {@link CLOUD_RETRY_MS}, runs in the
|
|
118
|
+
* background: the loaded set is already the workspace's. A list that could
|
|
119
|
+
* not be applied is retried no sooner either, so an unreachable control
|
|
120
|
+
* plane costs a call one fetch timeout at most every few seconds rather
|
|
121
|
+
* than on every call.
|
|
122
|
+
*/
|
|
123
|
+
sync(descriptors: readonly WasmRuleDescriptor[], bridge: CloudRuleBridge): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Recompiles every loaded rule from its kept bytes — the worker that held
|
|
126
|
+
* them was replaced. Waits for a sync in flight, which may have compiled
|
|
127
|
+
* into the old worker.
|
|
128
|
+
*/
|
|
129
|
+
reload(bridge: CompileBridge): Promise<void>;
|
|
130
|
+
private run;
|
|
131
|
+
private apply;
|
|
132
|
+
/** A binary some loaded rule already has: compiled again only when it is new to this rule id. */
|
|
133
|
+
private reuse;
|
|
134
|
+
/** `load_descriptor`: the hash, then the same load checks as a local rule. */
|
|
135
|
+
private load;
|
|
136
|
+
private reportOnce;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=cloudRules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudRules.d.ts","sourceRoot":"","sources":["../../src/wasm/cloudRules.ts"],"names":[],"mappings":"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"}
|