@permission-protocol/mcp-guard 0.1.0 → 0.2.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/CHANGELOG.md +45 -0
- package/LICENSE +21 -0
- package/README.md +101 -59
- package/SECURITY.md +40 -0
- package/dist/src/approval-server.d.ts +69 -3
- package/dist/src/approval-server.js +345 -86
- package/dist/src/approval-server.js.map +1 -1
- package/dist/src/approval-ui.d.ts +5 -0
- package/dist/src/approval-ui.js +120 -81
- package/dist/src/approval-ui.js.map +1 -1
- package/dist/src/classify.d.ts +29 -0
- package/dist/src/classify.js +107 -0
- package/dist/src/classify.js.map +1 -0
- package/dist/src/cli.js +49 -12
- package/dist/src/cli.js.map +1 -1
- package/dist/src/config.d.ts +21 -1
- package/dist/src/config.js +92 -5
- package/dist/src/config.js.map +1 -1
- package/dist/src/enforcement/index.d.ts +12 -0
- package/dist/src/enforcement/index.js +53 -0
- package/dist/src/enforcement/index.js.map +1 -0
- package/dist/src/enforcement/policy.d.ts +29 -0
- package/dist/src/enforcement/policy.js +60 -0
- package/dist/src/enforcement/policy.js.map +1 -0
- package/dist/src/enforcement/types.d.ts +19 -0
- package/dist/src/enforcement/types.js +3 -0
- package/dist/src/enforcement/types.js.map +1 -0
- package/dist/src/enforcement/verifier.d.ts +4 -0
- package/dist/src/enforcement/verifier.js +110 -0
- package/dist/src/enforcement/verifier.js.map +1 -0
- package/dist/src/engine.d.ts +11 -2
- package/dist/src/engine.js +20 -14
- package/dist/src/engine.js.map +1 -1
- package/dist/src/frame.d.ts +67 -0
- package/dist/src/frame.js +113 -0
- package/dist/src/frame.js.map +1 -0
- package/dist/src/pending.d.ts +108 -12
- package/dist/src/pending.js +174 -24
- package/dist/src/pending.js.map +1 -1
- package/dist/src/proxy.d.ts +29 -2
- package/dist/src/proxy.js +274 -105
- package/dist/src/proxy.js.map +1 -1
- package/dist/src/receipt-verify.d.ts +36 -0
- package/dist/src/receipt-verify.js +88 -0
- package/dist/src/receipt-verify.js.map +1 -0
- package/dist/src/receipt.d.ts +81 -7
- package/dist/src/receipt.js +100 -17
- package/dist/src/receipt.js.map +1 -1
- package/dist/src/signer.d.ts +38 -0
- package/dist/src/signer.js +112 -0
- package/dist/src/signer.js.map +1 -0
- package/dist/src/verify-cli.d.ts +1 -0
- package/dist/src/verify-cli.js +133 -0
- package/dist/src/verify-cli.js.map +1 -0
- package/dist/src/verify-core.d.ts +22 -0
- package/dist/src/verify-core.js +50 -0
- package/dist/src/verify-core.js.map +1 -0
- package/dist/src/webhook.d.ts +35 -0
- package/dist/src/webhook.js +57 -0
- package/dist/src/webhook.js.map +1 -0
- package/example/test.sh +5 -7
- package/package.json +33 -7
- package/templates/github-actions/receipt-gate.yml +64 -0
- package/assets/demo.gif +0 -0
- package/demo/_demo-scenario.sh +0 -43
- package/dist/src/tests/config.test.d.ts +0 -1
- package/dist/src/tests/config.test.js +0 -63
- package/dist/src/tests/config.test.js.map +0 -1
- package/dist/src/tests/engine.test.d.ts +0 -1
- package/dist/src/tests/engine.test.js +0 -46
- package/dist/src/tests/engine.test.js.map +0 -1
- package/dist/src/tests/receipt.test.d.ts +0 -1
- package/dist/src/tests/receipt.test.js +0 -44
- package/dist/src/tests/receipt.test.js.map +0 -1
- package/docs/index.html +0 -771
- package/permission-protocol-mcp-guard-0.1.0.tgz +0 -0
- package/src/approval-server.ts +0 -136
- package/src/approval-ui.ts +0 -154
- package/src/cli.ts +0 -84
- package/src/config.ts +0 -68
- package/src/engine.ts +0 -31
- package/src/pending.ts +0 -65
- package/src/proxy.ts +0 -173
- package/src/receipt.ts +0 -52
- package/src/tests/config.test.ts +0 -61
- package/src/tests/engine.test.ts +0 -47
- package/src/tests/receipt.test.ts +0 -44
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Inbound JSON-RPC framing for the stdio proxy.
|
|
4
|
+
*
|
|
5
|
+
* The guard only ever forwards a message it parsed and evaluated, re-serialized from
|
|
6
|
+
* the parsed object, so the server cannot read a line differently than the guard did.
|
|
7
|
+
* Anything that is not a single well-formed JSON-RPC 2.0 object is answered with an
|
|
8
|
+
* error and never forwarded. MCP does not use JSON-RPC batching, so arrays are refused.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.PASSTHROUGH_METHODS = exports.RELEASE_FAILED = exports.EXPIRED = exports.DENIED = exports.HELD = exports.BLOCKED = exports.INVALID_PARAMS = exports.METHOD_NOT_FOUND = exports.INVALID_REQUEST = exports.PARSE_ERROR = void 0;
|
|
12
|
+
exports.isPassthrough = isPassthrough;
|
|
13
|
+
exports.parseFrame = parseFrame;
|
|
14
|
+
exports.errorLine = errorLine;
|
|
15
|
+
exports.toolCallTarget = toolCallTarget;
|
|
16
|
+
exports.stripAgentMetadata = stripAgentMetadata;
|
|
17
|
+
exports.PARSE_ERROR = -32700;
|
|
18
|
+
exports.INVALID_REQUEST = -32600;
|
|
19
|
+
exports.METHOD_NOT_FOUND = -32601;
|
|
20
|
+
exports.INVALID_PARAMS = -32602;
|
|
21
|
+
exports.BLOCKED = -32001;
|
|
22
|
+
exports.HELD = -32002;
|
|
23
|
+
exports.DENIED = -32003;
|
|
24
|
+
exports.EXPIRED = -32004;
|
|
25
|
+
exports.RELEASE_FAILED = -32005;
|
|
26
|
+
/**
|
|
27
|
+
* Methods that carry no action or data access of their own. Everything else — tools/call,
|
|
28
|
+
* resources/read, prompts/get, resources/subscribe and any method the guard does not
|
|
29
|
+
* know — goes through the policy.
|
|
30
|
+
*/
|
|
31
|
+
exports.PASSTHROUGH_METHODS = new Set([
|
|
32
|
+
'initialize',
|
|
33
|
+
'ping',
|
|
34
|
+
'tools/list',
|
|
35
|
+
'resources/list',
|
|
36
|
+
'resources/templates/list',
|
|
37
|
+
'resources/unsubscribe',
|
|
38
|
+
'prompts/list',
|
|
39
|
+
'logging/setLevel',
|
|
40
|
+
'completion/complete',
|
|
41
|
+
]);
|
|
42
|
+
function isPassthrough(method) {
|
|
43
|
+
return exports.PASSTHROUGH_METHODS.has(method) || method.startsWith('notifications/');
|
|
44
|
+
}
|
|
45
|
+
function isPlainObject(v) {
|
|
46
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
47
|
+
}
|
|
48
|
+
function validId(v) {
|
|
49
|
+
return v === null || typeof v === 'string' || (typeof v === 'number' && Number.isFinite(v));
|
|
50
|
+
}
|
|
51
|
+
function parseFrame(line) {
|
|
52
|
+
let parsed;
|
|
53
|
+
try {
|
|
54
|
+
parsed = JSON.parse(line);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return { kind: 'invalid', id: null, code: exports.PARSE_ERROR, message: 'Parse error' };
|
|
58
|
+
}
|
|
59
|
+
if (Array.isArray(parsed)) {
|
|
60
|
+
return { kind: 'invalid', id: null, code: exports.INVALID_REQUEST, message: 'Batch requests are not supported' };
|
|
61
|
+
}
|
|
62
|
+
if (!isPlainObject(parsed)) {
|
|
63
|
+
return { kind: 'invalid', id: null, code: exports.INVALID_REQUEST, message: 'Invalid Request' };
|
|
64
|
+
}
|
|
65
|
+
const id = validId(parsed.id) ? parsed.id : null;
|
|
66
|
+
const invalid = (message) => ({ kind: 'invalid', id, code: exports.INVALID_REQUEST, message });
|
|
67
|
+
if (parsed.jsonrpc !== '2.0')
|
|
68
|
+
return invalid('Invalid Request: jsonrpc must be "2.0"');
|
|
69
|
+
if ('id' in parsed && !validId(parsed.id))
|
|
70
|
+
return invalid('Invalid Request: bad id');
|
|
71
|
+
const msg = parsed;
|
|
72
|
+
if ('method' in parsed) {
|
|
73
|
+
if (typeof parsed.method !== 'string' || !parsed.method)
|
|
74
|
+
return invalid('Invalid Request: method must be a string');
|
|
75
|
+
if ('params' in parsed && !isPlainObject(parsed.params) && !Array.isArray(parsed.params)) {
|
|
76
|
+
return invalid('Invalid Request: params must be an object or array');
|
|
77
|
+
}
|
|
78
|
+
if ('id' in parsed)
|
|
79
|
+
return { kind: 'request', msg: msg };
|
|
80
|
+
return { kind: 'notification', msg: msg };
|
|
81
|
+
}
|
|
82
|
+
if ('id' in parsed && ('result' in parsed || 'error' in parsed))
|
|
83
|
+
return { kind: 'response', msg };
|
|
84
|
+
return invalid('Invalid Request');
|
|
85
|
+
}
|
|
86
|
+
function errorLine(id, code, message) {
|
|
87
|
+
return JSON.stringify({ jsonrpc: '2.0', id, error: { code, message } });
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The tools/call target and arguments, validated. Returns an error message when the
|
|
91
|
+
* params are malformed (the call is then refused, never forwarded).
|
|
92
|
+
*/
|
|
93
|
+
function toolCallTarget(params) {
|
|
94
|
+
if (!isPlainObject(params))
|
|
95
|
+
return { error: 'Invalid params: tools/call requires an object' };
|
|
96
|
+
if (typeof params.name !== 'string' || !params.name)
|
|
97
|
+
return { error: 'Invalid params: tool name must be a string' };
|
|
98
|
+
if (params.arguments !== undefined && !isPlainObject(params.arguments)) {
|
|
99
|
+
return { error: 'Invalid params: arguments must be an object' };
|
|
100
|
+
}
|
|
101
|
+
return { name: params.name, args: params.arguments };
|
|
102
|
+
}
|
|
103
|
+
/** A copy of the message with Permission Deck agent metadata (`_pp`) removed from tool arguments. */
|
|
104
|
+
function stripAgentMetadata(msg) {
|
|
105
|
+
const params = msg.params;
|
|
106
|
+
if (msg.method !== 'tools/call' || !isPlainObject(params) || !isPlainObject(params.arguments))
|
|
107
|
+
return msg;
|
|
108
|
+
if (!('_pp' in params.arguments))
|
|
109
|
+
return msg;
|
|
110
|
+
const { _pp, ...rest } = params.arguments;
|
|
111
|
+
return { ...msg, params: { ...params, arguments: rest } };
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/frame.ts"],"names":[],"mappings":"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"}
|
package/dist/src/pending.d.ts
CHANGED
|
@@ -1,20 +1,116 @@
|
|
|
1
|
+
import type { Lane } from './engine.js';
|
|
2
|
+
import type { Reversibility } from './config.js';
|
|
3
|
+
import type { JsonRpcId } from './frame.js';
|
|
4
|
+
/**
|
|
5
|
+
* The approval queue and its decision state machine.
|
|
6
|
+
*
|
|
7
|
+
* Every status change goes through `transition()`, driven by one table: an item starts
|
|
8
|
+
* `pending` and moves exactly once to a final state. Final states never change, so a
|
|
9
|
+
* denied item can never be approved, and an approval racing a countdown releases once.
|
|
10
|
+
*
|
|
11
|
+
* Item kinds:
|
|
12
|
+
* - held: a request the proxy is holding; approve/auto-release forwards it.
|
|
13
|
+
* - acted: a Verify-lane action that already ran under a standing rule; it can only
|
|
14
|
+
* be acknowledged (it cannot be denied or undone after the fact).
|
|
15
|
+
* - external: a decision with no MCP request behind it (GitHub webhook); approve
|
|
16
|
+
* issues a scoped receipt.
|
|
17
|
+
*/
|
|
18
|
+
export type PendingStatus = 'pending' | 'approved' | 'denied' | 'auto_released' | 'expired' | 'acknowledged';
|
|
19
|
+
export type PendingKind = 'held' | 'acted' | 'external';
|
|
20
|
+
export type PendingEvent = 'approve' | 'deny' | 'auto_release' | 'expire' | 'acknowledge' | 'hold';
|
|
21
|
+
/** Resolved items kept for display before the oldest are dropped. */
|
|
22
|
+
export declare const MAX_RESOLVED = 200;
|
|
23
|
+
export interface PendingEnrichment {
|
|
24
|
+
lane: Lane;
|
|
25
|
+
reversibility: Reversibility;
|
|
26
|
+
countdown_seconds?: number;
|
|
27
|
+
confidence?: number;
|
|
28
|
+
summary: string;
|
|
29
|
+
args_preview: string;
|
|
30
|
+
}
|
|
1
31
|
export interface PendingAction {
|
|
2
32
|
id: string;
|
|
3
|
-
|
|
33
|
+
kind: PendingKind;
|
|
34
|
+
method: string;
|
|
4
35
|
tool_name: string;
|
|
5
|
-
tool_args:
|
|
36
|
+
tool_args: Record<string, unknown>;
|
|
6
37
|
agent_id: string;
|
|
7
|
-
rule_id: string;
|
|
8
|
-
status:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
/**
|
|
38
|
+
rule_id: string | null;
|
|
39
|
+
status: PendingStatus;
|
|
40
|
+
created_at: string;
|
|
41
|
+
resolved_at?: string;
|
|
42
|
+
/** ISO time after which a pending item expires; absent = no expiry. */
|
|
43
|
+
expires_at?: string;
|
|
44
|
+
/** The JSON-RPC line to forward on release (held items only). */
|
|
45
|
+
forwardLine: string;
|
|
46
|
+
jsonrpcId: JsonRpcId;
|
|
47
|
+
/** Deliver a response line to the waiting client (held items only). */
|
|
48
|
+
resolve: (responseLine: string) => void;
|
|
49
|
+
lane: Lane;
|
|
50
|
+
reversibility: Reversibility;
|
|
51
|
+
countdown_seconds?: number;
|
|
52
|
+
confidence?: number;
|
|
53
|
+
summary: string;
|
|
54
|
+
args_preview: string;
|
|
55
|
+
receipt_id?: string;
|
|
56
|
+
scope?: string;
|
|
57
|
+
scope_ref?: string;
|
|
58
|
+
scope_sha?: string;
|
|
59
|
+
/** epoch ms when the countdown auto-release fires; undefined = no countdown */
|
|
60
|
+
releaseAt?: number;
|
|
61
|
+
countdownTimer?: NodeJS.Timeout;
|
|
62
|
+
expiryTimer?: NodeJS.Timeout;
|
|
63
|
+
}
|
|
64
|
+
export type TransitionResult = {
|
|
65
|
+
ok: true;
|
|
66
|
+
action: PendingAction;
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
error: 'not_found' | 'final' | 'not_allowed';
|
|
70
|
+
action?: PendingAction;
|
|
71
|
+
};
|
|
72
|
+
export declare function setAutoReleaseHandler(handler: ((action: PendingAction) => void) | null): void;
|
|
73
|
+
export declare function setExpireHandler(handler: ((action: PendingAction) => void) | null): void;
|
|
74
|
+
/** The only place an item's status changes. */
|
|
75
|
+
export declare function transition(id: string, event: PendingEvent): TransitionResult;
|
|
76
|
+
interface BaseInput {
|
|
77
|
+
toolName: string;
|
|
78
|
+
toolArgs?: Record<string, unknown>;
|
|
79
|
+
agentId: string;
|
|
80
|
+
ruleId: string | null;
|
|
81
|
+
enrichment: PendingEnrichment;
|
|
82
|
+
method?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface HeldInput extends BaseInput {
|
|
85
|
+
/** The scope the release receipt will bind, shown to the approver. */
|
|
86
|
+
scope?: string;
|
|
87
|
+
scope_ref?: string;
|
|
88
|
+
scope_sha?: string;
|
|
89
|
+
forwardLine: string;
|
|
90
|
+
jsonrpcId: JsonRpcId;
|
|
14
91
|
resolve: (responseLine: string) => void;
|
|
92
|
+
ttlSeconds?: number;
|
|
93
|
+
}
|
|
94
|
+
/** Hold a request for a decision. Reversible holds with a countdown auto-release. */
|
|
95
|
+
export declare function addPending(input: HeldInput): PendingAction;
|
|
96
|
+
export interface ActedInput extends BaseInput {
|
|
97
|
+
receiptId?: string;
|
|
98
|
+
ttlSeconds?: number;
|
|
99
|
+
}
|
|
100
|
+
/** Surface an action that already ran under a standing rule, for acknowledgement. */
|
|
101
|
+
export declare function surfaceActed(input: ActedInput): PendingAction;
|
|
102
|
+
export interface ExternalInput extends BaseInput {
|
|
103
|
+
scope?: string;
|
|
104
|
+
scope_ref?: string;
|
|
105
|
+
scope_sha?: string;
|
|
15
106
|
}
|
|
16
|
-
|
|
107
|
+
/** Enqueue a decision from an external source (GitHub webhook). Never auto-releases or expires. */
|
|
108
|
+
export declare function addExternalDecision(input: ExternalInput): PendingAction;
|
|
17
109
|
export declare function getPending(): PendingAction[];
|
|
18
110
|
export declare function getAction(id: string): PendingAction | undefined;
|
|
19
|
-
export declare function
|
|
20
|
-
|
|
111
|
+
export declare function queueSize(): number;
|
|
112
|
+
/** Seconds remaining until auto-release, server-computed. undefined if no countdown. */
|
|
113
|
+
export declare function countdownRemaining(action: PendingAction): number | undefined;
|
|
114
|
+
/** Test/teardown helper: clear the queue and any live timers. */
|
|
115
|
+
export declare function _resetQueue(): void;
|
|
116
|
+
export {};
|
package/dist/src/pending.js
CHANGED
|
@@ -1,44 +1,194 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_RESOLVED = void 0;
|
|
4
|
+
exports.setAutoReleaseHandler = setAutoReleaseHandler;
|
|
5
|
+
exports.setExpireHandler = setExpireHandler;
|
|
6
|
+
exports.transition = transition;
|
|
3
7
|
exports.addPending = addPending;
|
|
8
|
+
exports.surfaceActed = surfaceActed;
|
|
9
|
+
exports.addExternalDecision = addExternalDecision;
|
|
4
10
|
exports.getPending = getPending;
|
|
5
11
|
exports.getAction = getAction;
|
|
6
|
-
exports.
|
|
7
|
-
exports.
|
|
8
|
-
|
|
12
|
+
exports.queueSize = queueSize;
|
|
13
|
+
exports.countdownRemaining = countdownRemaining;
|
|
14
|
+
exports._resetQueue = _resetQueue;
|
|
15
|
+
const node_crypto_1 = require("node:crypto");
|
|
16
|
+
const ALLOWED_EVENTS = {
|
|
17
|
+
held: new Set(['approve', 'deny', 'auto_release', 'expire', 'hold']),
|
|
18
|
+
acted: new Set(['acknowledge', 'expire']),
|
|
19
|
+
external: new Set(['approve', 'deny']),
|
|
20
|
+
};
|
|
21
|
+
const FINAL_STATUS = {
|
|
22
|
+
approve: 'approved',
|
|
23
|
+
deny: 'denied',
|
|
24
|
+
auto_release: 'auto_released',
|
|
25
|
+
expire: 'expired',
|
|
26
|
+
acknowledge: 'acknowledged',
|
|
27
|
+
};
|
|
28
|
+
/** Resolved items kept for display before the oldest are dropped. */
|
|
29
|
+
exports.MAX_RESOLVED = 200;
|
|
9
30
|
const queue = new Map();
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
/** Called after a countdown has moved an item to `auto_released`; the proxy releases it. */
|
|
32
|
+
let autoReleaseHandler = null;
|
|
33
|
+
function setAutoReleaseHandler(handler) {
|
|
34
|
+
autoReleaseHandler = handler;
|
|
35
|
+
}
|
|
36
|
+
/** Called after a TTL has moved an item to `expired`; the proxy answers the client. */
|
|
37
|
+
let expireHandler = null;
|
|
38
|
+
function setExpireHandler(handler) {
|
|
39
|
+
expireHandler = handler;
|
|
40
|
+
}
|
|
41
|
+
function clearTimers(action, which) {
|
|
42
|
+
if (action.countdownTimer)
|
|
43
|
+
clearTimeout(action.countdownTimer);
|
|
44
|
+
action.countdownTimer = undefined;
|
|
45
|
+
if (which === 'all') {
|
|
46
|
+
if (action.expiryTimer)
|
|
47
|
+
clearTimeout(action.expiryTimer);
|
|
48
|
+
action.expiryTimer = undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function prune() {
|
|
52
|
+
let resolved = 0;
|
|
53
|
+
for (const a of queue.values())
|
|
54
|
+
if (a.status !== 'pending')
|
|
55
|
+
resolved++;
|
|
56
|
+
if (resolved <= exports.MAX_RESOLVED)
|
|
57
|
+
return;
|
|
58
|
+
for (const [id, a] of queue) {
|
|
59
|
+
if (resolved <= exports.MAX_RESOLVED)
|
|
60
|
+
break;
|
|
61
|
+
if (a.status !== 'pending') {
|
|
62
|
+
queue.delete(id);
|
|
63
|
+
resolved--;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** The only place an item's status changes. */
|
|
68
|
+
function transition(id, event) {
|
|
69
|
+
const action = queue.get(id);
|
|
70
|
+
if (!action)
|
|
71
|
+
return { ok: false, error: 'not_found' };
|
|
72
|
+
if (action.status !== 'pending')
|
|
73
|
+
return { ok: false, error: 'final', action };
|
|
74
|
+
if (!ALLOWED_EVENTS[action.kind].has(event))
|
|
75
|
+
return { ok: false, error: 'not_allowed', action };
|
|
76
|
+
if ((event === 'auto_release' || event === 'hold') && action.releaseAt === undefined) {
|
|
77
|
+
return { ok: false, error: 'not_allowed', action };
|
|
78
|
+
}
|
|
79
|
+
if (event === 'hold') {
|
|
80
|
+
clearTimers(action, 'countdown');
|
|
81
|
+
action.releaseAt = undefined;
|
|
82
|
+
return { ok: true, action };
|
|
83
|
+
}
|
|
84
|
+
clearTimers(action, 'all');
|
|
85
|
+
action.releaseAt = undefined;
|
|
86
|
+
action.status = FINAL_STATUS[event];
|
|
87
|
+
action.resolved_at = new Date().toISOString();
|
|
88
|
+
prune();
|
|
89
|
+
return { ok: true, action };
|
|
90
|
+
}
|
|
91
|
+
function startExpiry(action, ttlSeconds) {
|
|
92
|
+
if (!ttlSeconds || ttlSeconds <= 0)
|
|
93
|
+
return;
|
|
94
|
+
action.expires_at = new Date(Date.now() + ttlSeconds * 1000).toISOString();
|
|
95
|
+
action.expiryTimer = setTimeout(() => {
|
|
96
|
+
const r = transition(action.id, 'expire');
|
|
97
|
+
if (r.ok && expireHandler)
|
|
98
|
+
expireHandler(r.action);
|
|
99
|
+
}, ttlSeconds * 1000);
|
|
100
|
+
action.expiryTimer.unref?.();
|
|
101
|
+
}
|
|
102
|
+
function baseAction(kind, input) {
|
|
103
|
+
return {
|
|
104
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
105
|
+
kind,
|
|
106
|
+
method: input.method ?? 'tools/call',
|
|
107
|
+
tool_name: input.toolName,
|
|
108
|
+
tool_args: input.toolArgs ?? {},
|
|
109
|
+
agent_id: input.agentId,
|
|
110
|
+
rule_id: input.ruleId,
|
|
18
111
|
status: 'pending',
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
112
|
+
created_at: new Date().toISOString(),
|
|
113
|
+
forwardLine: '',
|
|
114
|
+
jsonrpcId: null,
|
|
115
|
+
resolve: () => { },
|
|
116
|
+
lane: input.enrichment.lane,
|
|
117
|
+
reversibility: input.enrichment.reversibility,
|
|
118
|
+
...(input.enrichment.confidence !== undefined ? { confidence: input.enrichment.confidence } : {}),
|
|
119
|
+
summary: input.enrichment.summary,
|
|
120
|
+
args_preview: input.enrichment.args_preview,
|
|
22
121
|
};
|
|
122
|
+
}
|
|
123
|
+
/** Hold a request for a decision. Reversible holds with a countdown auto-release. */
|
|
124
|
+
function addPending(input) {
|
|
125
|
+
const action = baseAction('held', input);
|
|
126
|
+
action.forwardLine = input.forwardLine;
|
|
127
|
+
action.jsonrpcId = input.jsonrpcId;
|
|
128
|
+
action.resolve = input.resolve;
|
|
129
|
+
if (input.scope)
|
|
130
|
+
action.scope = input.scope;
|
|
131
|
+
if (input.scope_ref)
|
|
132
|
+
action.scope_ref = input.scope_ref;
|
|
133
|
+
if (input.scope_sha)
|
|
134
|
+
action.scope_sha = input.scope_sha;
|
|
135
|
+
const countdown = input.enrichment.countdown_seconds;
|
|
136
|
+
if (countdown !== undefined)
|
|
137
|
+
action.countdown_seconds = countdown;
|
|
138
|
+
// Irreversible (or no countdown) NEVER auto-releases; it waits for a decision or expiry.
|
|
139
|
+
if (action.reversibility === 'reversible' && countdown !== undefined && countdown > 0) {
|
|
140
|
+
action.releaseAt = Date.now() + countdown * 1000;
|
|
141
|
+
action.countdownTimer = setTimeout(() => {
|
|
142
|
+
const r = transition(action.id, 'auto_release');
|
|
143
|
+
if (r.ok && autoReleaseHandler)
|
|
144
|
+
autoReleaseHandler(r.action);
|
|
145
|
+
}, countdown * 1000);
|
|
146
|
+
action.countdownTimer.unref?.();
|
|
147
|
+
}
|
|
148
|
+
startExpiry(action, input.ttlSeconds);
|
|
149
|
+
queue.set(action.id, action);
|
|
150
|
+
return action;
|
|
151
|
+
}
|
|
152
|
+
/** Surface an action that already ran under a standing rule, for acknowledgement. */
|
|
153
|
+
function surfaceActed(input) {
|
|
154
|
+
const action = baseAction('acted', input);
|
|
155
|
+
if (input.receiptId !== undefined)
|
|
156
|
+
action.receipt_id = input.receiptId;
|
|
157
|
+
startExpiry(action, input.ttlSeconds);
|
|
158
|
+
queue.set(action.id, action);
|
|
159
|
+
return action;
|
|
160
|
+
}
|
|
161
|
+
/** Enqueue a decision from an external source (GitHub webhook). Never auto-releases or expires. */
|
|
162
|
+
function addExternalDecision(input) {
|
|
163
|
+
const action = baseAction('external', input);
|
|
164
|
+
if (input.scope)
|
|
165
|
+
action.scope = input.scope;
|
|
166
|
+
if (input.scope_ref)
|
|
167
|
+
action.scope_ref = input.scope_ref;
|
|
168
|
+
if (input.scope_sha)
|
|
169
|
+
action.scope_sha = input.scope_sha;
|
|
23
170
|
queue.set(action.id, action);
|
|
24
171
|
return action;
|
|
25
172
|
}
|
|
26
173
|
function getPending() {
|
|
27
|
-
return Array.from(queue.values()).filter(a => a.status === 'pending');
|
|
174
|
+
return Array.from(queue.values()).filter((a) => a.status === 'pending');
|
|
28
175
|
}
|
|
29
176
|
function getAction(id) {
|
|
30
177
|
return queue.get(id);
|
|
31
178
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
179
|
+
function queueSize() {
|
|
180
|
+
return queue.size;
|
|
181
|
+
}
|
|
182
|
+
/** Seconds remaining until auto-release, server-computed. undefined if no countdown. */
|
|
183
|
+
function countdownRemaining(action) {
|
|
184
|
+
if (action.releaseAt === undefined || action.status !== 'pending')
|
|
35
185
|
return undefined;
|
|
36
|
-
action.
|
|
37
|
-
return action;
|
|
186
|
+
return Math.max(0, Math.ceil((action.releaseAt - Date.now()) / 1000));
|
|
38
187
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
188
|
+
/** Test/teardown helper: clear the queue and any live timers. */
|
|
189
|
+
function _resetQueue() {
|
|
190
|
+
for (const action of queue.values())
|
|
191
|
+
clearTimers(action, 'all');
|
|
192
|
+
queue.clear();
|
|
43
193
|
}
|
|
44
194
|
//# sourceMappingURL=pending.js.map
|
package/dist/src/pending.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/pending.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pending.js","sourceRoot":"","sources":["../../src/pending.ts"],"names":[],"mappings":"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"}
|
package/dist/src/proxy.d.ts
CHANGED
|
@@ -1,2 +1,29 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type Config, type Rule } from './config.js';
|
|
2
|
+
import { type Decision } from './engine.js';
|
|
3
|
+
import { type ScopeBinding } from './receipt.js';
|
|
4
|
+
import { type PendingEnrichment } from './pending.js';
|
|
5
|
+
/**
|
|
6
|
+
* Derive a one-line summary + the literal artifact preview from the tool name and args,
|
|
7
|
+
* so the console can render a human-readable card. For capped spends the amount shown is
|
|
8
|
+
* the argument the rule caps (`amountArg`), the same one the classifier read.
|
|
9
|
+
*/
|
|
10
|
+
export declare function derivePreview(toolName: string, toolArgs: Record<string, unknown> | undefined, amountArg?: string): {
|
|
11
|
+
summary: string;
|
|
12
|
+
args_preview: string;
|
|
13
|
+
};
|
|
14
|
+
/** Build the enrichment record for the queue from a classified Decision + args. */
|
|
15
|
+
export declare function buildEnrichment(decision: Decision, toolName: string, toolArgs: Record<string, unknown> | undefined, rule?: Rule | null): PendingEnrichment;
|
|
16
|
+
/**
|
|
17
|
+
* Derive a receipt scope binding from the tool + args, for the code/infra tools the
|
|
18
|
+
* offline receipt gate verifies:
|
|
19
|
+
* - merge_pr -> `github:merge`, ref `refs/pull/<n>/merge`
|
|
20
|
+
* - run_sql_migration -> `sql:migrate:<env>`
|
|
21
|
+
* - deploy -> `deploy:<env>`
|
|
22
|
+
* Other tools carry no scope.
|
|
23
|
+
*/
|
|
24
|
+
export declare function deriveScope(toolName: string, toolArgs: Record<string, unknown> | undefined): ScopeBinding | undefined;
|
|
25
|
+
export interface ProxyOptions {
|
|
26
|
+
approvalPort?: number;
|
|
27
|
+
operator?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function startProxy(config: Config, agentId: string, serverCommand: string[], opts?: ProxyOptions): void;
|