@intutic/gate 1.10.1
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/LICENSE +21 -0
- package/README.md +261 -0
- package/dist/actions.d.ts +86 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +239 -0
- package/dist/actions.js.map +1 -0
- package/dist/client.d.ts +94 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +207 -0
- package/dist/client.js.map +1 -0
- package/dist/dsh.d.ts +162 -0
- package/dist/dsh.d.ts.map +1 -0
- package/dist/dsh.js +189 -0
- package/dist/dsh.js.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +53 -0
- package/dist/errors.js.map +1 -0
- package/dist/eve.d.ts +425 -0
- package/dist/eve.d.ts.map +1 -0
- package/dist/eve.js +378 -0
- package/dist/eve.js.map +1 -0
- package/dist/gate.d.ts +113 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +274 -0
- package/dist/gate.js.map +1 -0
- package/dist/harness.d.ts +482 -0
- package/dist/harness.d.ts.map +1 -0
- package/dist/harness.js +504 -0
- package/dist/harness.js.map +1 -0
- package/dist/headers.d.ts +26 -0
- package/dist/headers.d.ts.map +1 -0
- package/dist/headers.js +30 -0
- package/dist/headers.js.map +1 -0
- package/dist/imagecheck.d.ts +93 -0
- package/dist/imagecheck.d.ts.map +1 -0
- package/dist/imagecheck.js +286 -0
- package/dist/imagecheck.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/managedAgents.d.ts +375 -0
- package/dist/managedAgents.d.ts.map +1 -0
- package/dist/managedAgents.js +446 -0
- package/dist/managedAgents.js.map +1 -0
- package/dist/mastra.d.ts +175 -0
- package/dist/mastra.d.ts.map +1 -0
- package/dist/mastra.js +161 -0
- package/dist/mastra.js.map +1 -0
- package/dist/openai.d.ts +392 -0
- package/dist/openai.d.ts.map +1 -0
- package/dist/openai.js +658 -0
- package/dist/openai.js.map +1 -0
- package/dist/shlex.d.ts +16 -0
- package/dist/shlex.d.ts.map +1 -0
- package/dist/shlex.js +78 -0
- package/dist/shlex.js.map +1 -0
- package/dist/snapshot.d.ts +111 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +243 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/soprules.d.ts +88 -0
- package/dist/soprules.d.ts.map +1 -0
- package/dist/soprules.js +176 -0
- package/dist/soprules.js.map +1 -0
- package/dist/trueforge.d.ts +191 -0
- package/dist/trueforge.d.ts.map +1 -0
- package/dist/trueforge.js +184 -0
- package/dist/trueforge.js.map +1 -0
- package/dist/vercel.d.ts +174 -0
- package/dist/vercel.d.ts.map +1 -0
- package/dist/vercel.js +157 -0
- package/dist/vercel.js.map +1 -0
- package/dist/workflow.d.ts +209 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +254 -0
- package/dist/workflow.js.map +1 -0
- package/dist/wrapTools.d.ts +68 -0
- package/dist/wrapTools.d.ts.map +1 -0
- package/dist/wrapTools.js +95 -0
- package/dist/wrapTools.js.map +1 -0
- package/package.json +123 -0
package/dist/eve.js
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eve adapter: `intuticApproval()`, `intuticConnectionApproval()`,
|
|
3
|
+
* `intuticAuditHooks()`.
|
|
4
|
+
*
|
|
5
|
+
* `@intutic/gate/eve` — a framework-specific specialization of the same idea
|
|
6
|
+
* `wrapTools.ts` implements generically (see that file's module doc): wrap the
|
|
7
|
+
* framework's own veto point around this package's `Gate.guard()`.
|
|
8
|
+
*
|
|
9
|
+
* eve (npm `eve`, github.com/vercel/eve) is Vercel's filesystem-first
|
|
10
|
+
* framework for durable backend AI agents: an agent is a directory (`agent/`
|
|
11
|
+
* with `instructions.md`, `agent/tools/*.ts`, `agent/connections/*.ts`,
|
|
12
|
+
* `agent/hooks/*.ts`, ...) that eve builds by walking the tree. It is a
|
|
13
|
+
* pre-1.0 PREVIEW product (0.39.1 at the time of writing, very active) —
|
|
14
|
+
* see docs/TECH_DEBT.md TD-410 for the churn shield this adapter carries,
|
|
15
|
+
* the same posture the dsh integration established.
|
|
16
|
+
*
|
|
17
|
+
* ## The veto mechanism — CONFIRMED against a real install, not assumed
|
|
18
|
+
*
|
|
19
|
+
* `eve@0.39.1` is installed as a devDependency of this package and its
|
|
20
|
+
* shipped `.d.ts` files were read directly (not inferred from docs alone).
|
|
21
|
+
* eve's per-tool veto point is the `approval` property on a tool definition
|
|
22
|
+
* (`dist/src/public/definitions/tool.d.ts`), and the same `Approval` type is
|
|
23
|
+
* accepted per-connection by `defineMcpClientConnection` /
|
|
24
|
+
* `defineOpenAPIConnection` (`dist/src/public/definitions/connections/
|
|
25
|
+
* {mcp,openapi}.d.ts`), gating ALL of that connection's tools. There is NO
|
|
26
|
+
* agent-level default approval field (`agent.d.ts` carries zero approval
|
|
27
|
+
* fields — verified) — attaching a shared policy per tool/connection is
|
|
28
|
+
* eve's own documented multi-tenant pattern
|
|
29
|
+
* (`docs/patterns/multi-tenant-approvals.md`), and exactly the shape this
|
|
30
|
+
* adapter exports.
|
|
31
|
+
*
|
|
32
|
+
* The confirmed policy contract (`dist/src/public/definitions/approval.d.ts`):
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* export interface ApprovalContext<TInput = Record<string, unknown>> extends SessionContext {
|
|
36
|
+
* readonly approvedTools: ReadonlySet<string>
|
|
37
|
+
* readonly callId: string
|
|
38
|
+
* readonly toolInput?: ApprovalToolInput<TInput> // Readonly<TInput> | TInput; CAN be undefined
|
|
39
|
+
* readonly toolName: string
|
|
40
|
+
* }
|
|
41
|
+
* export type ApprovalStatus = undefined | boolean
|
|
42
|
+
* | 'not-applicable' | 'approved' | 'denied' | 'user-approval'
|
|
43
|
+
* | { readonly type: 'not-applicable'; readonly reason?: never }
|
|
44
|
+
* | { readonly type: 'approved'; readonly reason?: string }
|
|
45
|
+
* | { readonly type: 'denied'; readonly reason?: string }
|
|
46
|
+
* | { readonly type: 'user-approval'; readonly reason?: never }
|
|
47
|
+
* export type ApprovalPolicy<TInput = Record<string, unknown>> =
|
|
48
|
+
* (ctx: ApprovalContext<TInput>) => ApprovalStatus | Promise<ApprovalStatus>
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* These are AI SDK 7 approval statuses (eve is built on `ai` v7 — the same
|
|
52
|
+
* family `vercel.ts` documents). `'denied'` / `{ type: 'denied', reason }`
|
|
53
|
+
* vetoes the call before execution; `reason` reaches the model in place of a
|
|
54
|
+
* tool result. `'not-applicable'` (and `undefined`) means "continue without a
|
|
55
|
+
* prompt"; `'user-approval'` parks the run durably for a human. The boolean
|
|
56
|
+
* forms are back-compat for eve's earlier predicate shape: `true` is treated
|
|
57
|
+
* as `'user-approval'` and `false` as `'not-applicable'` (confirmed in
|
|
58
|
+
* `docs/tools/human-in-the-loop.md`) — this adapter never RETURNS booleans,
|
|
59
|
+
* but its structural {@link EveApprovalStatus} copy includes them so the type
|
|
60
|
+
* stays field-for-field faithful to the real union.
|
|
61
|
+
*
|
|
62
|
+
* ## Allow-shape: why `'not-applicable'` and not `'approved'`
|
|
63
|
+
*
|
|
64
|
+
* Unlike the Vercel AI SDK's `toolApproval` (a separate, whole-run config
|
|
65
|
+
* that coexists with per-tool mechanisms), eve's `approval` IS the tool's one
|
|
66
|
+
* approval policy — whatever this function returns is the whole decision for
|
|
67
|
+
* that call. On allow this adapter returns `'not-applicable'` by default:
|
|
68
|
+
* eve's own "no prompt needed, continue" value, matching the semantics of an
|
|
69
|
+
* omitted `approval` (`never()`). It deliberately does NOT return
|
|
70
|
+
* `'approved'`: that value asserts an affirmative approval decision this gate
|
|
71
|
+
* did not make (Intutic's allow is "no objection", not "signed off"), and its
|
|
72
|
+
* interaction with eve's `approvedTools` bookkeeping (`once()` keys off that
|
|
73
|
+
* set) is not something this adapter verified. Callers who want eve's human
|
|
74
|
+
* flow ON TOP of the governance gate set `{ onAllow: 'user-approval' }` —
|
|
75
|
+
* "governance has no objection; still ask a person" — or compose manually
|
|
76
|
+
* (see {@link intuticApproval}).
|
|
77
|
+
*
|
|
78
|
+
* ## Audit hooks — observe-only, and honestly scoped
|
|
79
|
+
*
|
|
80
|
+
* eve's hook surface (`agent/hooks/*.ts`, `dist/src/public/definitions/
|
|
81
|
+
* hook.d.ts`) exposes `approval.candidate` / `approval.settled` stream
|
|
82
|
+
* events. Handlers are OBSERVE-ONLY by eve's own contract ("fire after eve
|
|
83
|
+
* has accepted and durably recorded each event ... cannot inject model
|
|
84
|
+
* context") — {@link intuticAuditHooks} is telemetry, not enforcement; the
|
|
85
|
+
* enforcement surface is {@link intuticApproval}. LOAD-BEARING caveat,
|
|
86
|
+
* verified against `dist/src/protocol/message.d.ts`: these two events carry
|
|
87
|
+
* `requestId`/`responderPrincipalId`/`turnId`/`stepIndex` but NOT the tool
|
|
88
|
+
* name or input.
|
|
89
|
+
*
|
|
90
|
+
* TD-411 half 2, revisited: `intuticApproval()` and `intuticAuditHooks()` are
|
|
91
|
+
* both plain functions exported from this one module and cannot be assumed to
|
|
92
|
+
* run in the same process at settlement time — eve's own docs state a parked
|
|
93
|
+
* approval survives a process restart verbatim ("the process can restart and
|
|
94
|
+
* the parked turn survives", `docs/tools/human-in-the-loop.md`), so a
|
|
95
|
+
* `requestId -> toolName` map populated at approval-decision time and read
|
|
96
|
+
* back later inside the hook would silently degrade for exactly the durable,
|
|
97
|
+
* long-parked approvals this mechanism exists for — the worst kind of fix,
|
|
98
|
+
* correct in local testing and quietly wrong in the deployments that matter
|
|
99
|
+
* most. That map was NOT built.
|
|
100
|
+
*
|
|
101
|
+
* What WAS found and built instead needs no cross-call memory at all: eve
|
|
102
|
+
* ships a THIRD hookable event, `input.requested` (confirmed in the same
|
|
103
|
+
* `HookEventMap`, `dist/src/public/definitions/hook.d.ts`), fired once when a
|
|
104
|
+
* batch of human-input requests is created — including every `kind:
|
|
105
|
+
* 'tool-approval'` request `intuticApproval()`'s `'user-approval'` return
|
|
106
|
+
* value produces. Each request in that ONE event already carries
|
|
107
|
+
* `requestId` AND `action.toolName` TOGETHER (`InputRequest`,
|
|
108
|
+
* `dist/src/runtime/input/types.d.ts`'s `inputRequestSchema` — confirmed by
|
|
109
|
+
* the shipped zod schema, not just prose; corroborated by
|
|
110
|
+
* `docs/tools/human-in-the-loop.md`'s explicit statement that "`toolName` and
|
|
111
|
+
* `requestId` identify the action and request"). {@link intuticAuditHooks}
|
|
112
|
+
* now subscribes to it too: it emits a real, tool-identified `tool_flagged`
|
|
113
|
+
* event at REQUEST time (closing the "no tool identity" gap unconditionally,
|
|
114
|
+
* with no process-boundary risk — the whole payload arrives in one event),
|
|
115
|
+
* and best-effort caches `requestId -> toolName` in memory so the LATER
|
|
116
|
+
* `approval.candidate`/`approval.settled` events attribute to the real tool
|
|
117
|
+
* name too WHEN this cache is still warm (same-process, or a short-lived
|
|
118
|
+
* pause). When it is not — a genuinely long-parked, cross-restart approval —
|
|
119
|
+
* settlement still falls back to the synthetic {@link EVE_APPROVAL_TOOL_NAME},
|
|
120
|
+
* exactly the pre-existing behaviour, never worse. See TD-411 for the full
|
|
121
|
+
* reasoning and what a persistent (non-memory) correlation store would take
|
|
122
|
+
* to close that residual gap.
|
|
123
|
+
*
|
|
124
|
+
* ## LLM egress — documented honestly, not oversold
|
|
125
|
+
*
|
|
126
|
+
* eve routes models through the Vercel AI Gateway by default (a gateway model
|
|
127
|
+
* id string in `agent.ts`'s `defineAgent({ model })`, `AI_GATEWAY_API_KEY` /
|
|
128
|
+
* `VERCEL_OIDC_TOKEN` credentials — confirmed in `docs/agent-config.md` and
|
|
129
|
+
* `docs/getting-started.mdx`). The AI Gateway wire protocol is NOT something
|
|
130
|
+
* the Intutic proxy parses, so gateway-routed egress is ungoverned by the
|
|
131
|
+
* proxy — full stop, and TD-412 tracks it. The governable path is eve's
|
|
132
|
+
* other documented option: passing a provider-authored `LanguageModel`
|
|
133
|
+
* (`createOpenAI(...)` etc.) to `defineAgent({ model })`, where the
|
|
134
|
+
* `withIntuticProxy()` helper — implemented once in `vercel.ts` and
|
|
135
|
+
* re-exported here — applies exactly as it does for the plain Vercel AI SDK.
|
|
136
|
+
* As with that framework, there is no env-var base-URL override: routing is
|
|
137
|
+
* in-code, per provider-construction call site.
|
|
138
|
+
*
|
|
139
|
+
* @module
|
|
140
|
+
*/
|
|
141
|
+
import { active as activeGate } from './gate.js';
|
|
142
|
+
import { GateClient } from './client.js';
|
|
143
|
+
import { IntuticGateRefusal } from './errors.js';
|
|
144
|
+
// One routing story, one implementation: eve's direct-provider path is the
|
|
145
|
+
// Vercel AI SDK's (eve is built on `ai` v7), so the helper is re-exported
|
|
146
|
+
// rather than duplicated. See vercel.ts for the full module doc.
|
|
147
|
+
export { intuticProxyUrl, withIntuticProxy } from './vercel.js';
|
|
148
|
+
/** Synthetic tool name used by {@link intuticAuditHooks} — eve's
|
|
149
|
+
* `approval.candidate`/`approval.settled` events do not carry the real tool
|
|
150
|
+
* name (verified against `dist/src/protocol/message.d.ts`; see module doc). */
|
|
151
|
+
export const EVE_APPROVAL_TOOL_NAME = 'eve:approval';
|
|
152
|
+
/**
|
|
153
|
+
* Render an eve `toolInput` as the `tool_input` object {@link Gate.guard}
|
|
154
|
+
* evaluates.
|
|
155
|
+
*
|
|
156
|
+
* Mirrors dsh.ts's `renderDshToolInput` (same reasoning as its own mirror of
|
|
157
|
+
* `wrapTools.ts`'s non-exported `renderToolInput`): a plain object passes
|
|
158
|
+
* through as-is; `undefined` (which eve documents as possible — "toolInput
|
|
159
|
+
* can be undefined, so guard the access") becomes `{}`; any other non-object
|
|
160
|
+
* value falls back to `{ args: [...] }` so the gate still has something to
|
|
161
|
+
* evaluate.
|
|
162
|
+
*/
|
|
163
|
+
function renderEveToolInput(input) {
|
|
164
|
+
if (input === undefined)
|
|
165
|
+
return {};
|
|
166
|
+
if (input !== null && typeof input === 'object' && !Array.isArray(input)) {
|
|
167
|
+
return input;
|
|
168
|
+
}
|
|
169
|
+
return { args: [input] };
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Builds an approval policy matching eve's `ApprovalPolicy` signature, for
|
|
173
|
+
* direct use as a tool definition's `approval` field:
|
|
174
|
+
*
|
|
175
|
+
* ```ts
|
|
176
|
+
* // agent/tools/refund_charge.ts
|
|
177
|
+
* import { defineTool } from 'eve/tools'
|
|
178
|
+
* import { z } from 'zod'
|
|
179
|
+
* import { intuticApproval } from '@intutic/gate/eve'
|
|
180
|
+
*
|
|
181
|
+
* export default defineTool({
|
|
182
|
+
* description: 'Refund a charge.',
|
|
183
|
+
* inputSchema: z.object({ chargeId: z.string(), amount: z.number() }),
|
|
184
|
+
* approval: intuticApproval(),
|
|
185
|
+
* async execute(input) {
|
|
186
|
+
* return refund(input)
|
|
187
|
+
* },
|
|
188
|
+
* })
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* (Install the gate once, process-wide, e.g. in `agent.ts`:
|
|
192
|
+
* `install(new Gate({ workspaceId: process.env.INTUTIC_WORKSPACE_ID }))`.)
|
|
193
|
+
*
|
|
194
|
+
* Resolves to `'not-applicable'` on allow (or `opts.onAllow` — see
|
|
195
|
+
* {@link IntuticApprovalOptions.onAllow}) and to `{ type: 'denied', reason }`
|
|
196
|
+
* on refusal — `reason` is the `[Intutic Governance] BLOCKED: ...` message,
|
|
197
|
+
* handed back to the model in place of a tool result; the tool's `execute`
|
|
198
|
+
* never runs.
|
|
199
|
+
*
|
|
200
|
+
* Requires a `Gate` — either passed via `{ gate }` here, or installed
|
|
201
|
+
* process-wide with `install(new Gate(...))`. A call with neither throws,
|
|
202
|
+
* refusing to run the tool unguarded rather than silently skipping
|
|
203
|
+
* enforcement — same posture as `wrapTool`/`intuticHooks`/
|
|
204
|
+
* `intuticToolApproval`. A non-refusal crash inside the gate is re-thrown
|
|
205
|
+
* rather than mapped to a denial — eve's own approval docs direct policies to
|
|
206
|
+
* "throw or deny, never silently allow", and a thrown policy fails the turn
|
|
207
|
+
* (fail closed), matching vercel.ts's posture for the same status family.
|
|
208
|
+
*/
|
|
209
|
+
export function intuticApproval(opts = {}) {
|
|
210
|
+
return async (ctx) => {
|
|
211
|
+
const g = opts.gate ?? activeGate();
|
|
212
|
+
if (g === null) {
|
|
213
|
+
throw new Error('No gate configured: call install(new Gate(...)) from @intutic/gate, or pass ' +
|
|
214
|
+
'{ gate } to intuticApproval(). Refusing to run the tool unguarded.');
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
await g.guard(ctx.toolName, renderEveToolInput(ctx.toolInput));
|
|
218
|
+
return opts.onAllow ?? 'not-applicable';
|
|
219
|
+
}
|
|
220
|
+
catch (exc) {
|
|
221
|
+
if (exc instanceof IntuticGateRefusal) {
|
|
222
|
+
return { type: 'denied', reason: exc.message };
|
|
223
|
+
}
|
|
224
|
+
throw exc;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The same policy, shaped for a CONNECTION's `approval` field — eve's MCP and
|
|
230
|
+
* OpenAPI connections accept one `approval` gating ALL of that connection's
|
|
231
|
+
* tools (`defineMcpClientConnection`/`defineOpenAPIConnection`, confirmed at
|
|
232
|
+
* `dist/src/public/definitions/connections/{mcp,openapi}.d.ts` — an omitted
|
|
233
|
+
* `approval` means every connection tool executes without approval):
|
|
234
|
+
*
|
|
235
|
+
* ```ts
|
|
236
|
+
* // agent/connections/support.ts
|
|
237
|
+
* import { defineMcpClientConnection } from 'eve/connections'
|
|
238
|
+
* import { intuticConnectionApproval } from '@intutic/gate/eve'
|
|
239
|
+
*
|
|
240
|
+
* export default defineMcpClientConnection({
|
|
241
|
+
* url: 'https://support.example.com/mcp',
|
|
242
|
+
* description: 'Support tickets.',
|
|
243
|
+
* approval: intuticConnectionApproval(),
|
|
244
|
+
* })
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* Implemented AS {@link intuticApproval} (one enforcement path, not two) —
|
|
248
|
+
* the separate export exists because the surface differs in one way worth
|
|
249
|
+
* knowing: `ctx.toolName` for a connection tool is the QUALIFIED name
|
|
250
|
+
* (`support__add_internal_note`, connection slug + `__` + remote tool name —
|
|
251
|
+
* eve's own convention, per `docs/patterns/multi-tenant-approvals.md`), and
|
|
252
|
+
* that qualified name is what `Gate.guard()` evaluates and what SOP rules /
|
|
253
|
+
* snapshot `tool:` subjects must match. This adapter deliberately does not
|
|
254
|
+
* strip the prefix: the qualified name is the call's real identity inside
|
|
255
|
+
* this eve app, and un-prefixing would let two connections' same-named remote
|
|
256
|
+
* tools collapse into one rule target.
|
|
257
|
+
*/
|
|
258
|
+
export function intuticConnectionApproval(opts = {}) {
|
|
259
|
+
return intuticApproval(opts);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Observe-only audit emitter for eve's human-approval lifecycle, shaped for
|
|
263
|
+
* `agent/hooks/`:
|
|
264
|
+
*
|
|
265
|
+
* ```ts
|
|
266
|
+
* // agent/hooks/intutic-audit.ts
|
|
267
|
+
* import { defineHook } from 'eve/hooks'
|
|
268
|
+
* import { intuticAuditHooks } from '@intutic/gate/eve'
|
|
269
|
+
*
|
|
270
|
+
* export default defineHook(intuticAuditHooks())
|
|
271
|
+
* ```
|
|
272
|
+
*
|
|
273
|
+
* Maps eve's approval stream events onto Intutic's gate event vocabulary
|
|
274
|
+
* (the same `tool_allowed`/`tool_blocked`/`tool_flagged` names `gate.ts`
|
|
275
|
+
* emits, so the dashboard renders both sources on one timeline):
|
|
276
|
+
*
|
|
277
|
+
* - `input.requested`, one `kind: 'tool-approval'` request → `tool_flagged`,
|
|
278
|
+
* under the REAL tool name (`request.action.toolName`) — a genuinely new
|
|
279
|
+
* signal this adapter did not emit before: a call is now pending human
|
|
280
|
+
* approval. See the module doc (TD-411) for why this event, not a
|
|
281
|
+
* process-memory map, is what closes "no tool identity" here.
|
|
282
|
+
* - `approval.settled` `outcome: 'approved'` → `tool_allowed` — a human
|
|
283
|
+
* explicitly approved the parked call.
|
|
284
|
+
* - `approval.settled` `outcome: 'cancelled'` → `tool_blocked` — the request
|
|
285
|
+
* was settled without approval; the call never ran. This is a HUMAN veto
|
|
286
|
+
* recorded for audit, not an Intutic-gate refusal (the reason string says
|
|
287
|
+
* so), and like every `tool_blocked` it creates an incident row.
|
|
288
|
+
* - `approval.candidate` non-`'pending'` outcomes (`rejected`/`failed`/
|
|
289
|
+
* `timed-out`/`stale`) → `tool_flagged` — a responder's attempt to answer
|
|
290
|
+
* went somewhere worth an operator's attention. `'pending'` (a candidate
|
|
291
|
+
* simply being created) is routine lifecycle and deliberately NOT emitted.
|
|
292
|
+
*
|
|
293
|
+
* `approval.candidate`/`approval.settled` attribute to the REAL tool name
|
|
294
|
+
* when this instance's in-memory `requestId -> toolName` cache (populated
|
|
295
|
+
* by `input.requested`) is still warm, and fall back to the synthetic
|
|
296
|
+
* {@link EVE_APPROVAL_TOOL_NAME} otherwise — see the module doc for why that
|
|
297
|
+
* fallback exists and is not itself a bug.
|
|
298
|
+
*
|
|
299
|
+
* These hooks are TELEMETRY, not enforcement: eve runs hook handlers after
|
|
300
|
+
* events are durably recorded, and they cannot veto anything (eve's own
|
|
301
|
+
* "observe-only" hook contract). The enforcement surface is
|
|
302
|
+
* {@link intuticApproval}. Handlers never throw — a telemetry failure must
|
|
303
|
+
* not break the run (`GateClient.emit`'s own never-throws contract).
|
|
304
|
+
*/
|
|
305
|
+
export function intuticAuditHooks(opts = {}) {
|
|
306
|
+
const perSession = new Map();
|
|
307
|
+
// Best-effort, same-process-only. Populated by `input.requested` (which
|
|
308
|
+
// carries requestId and toolName together already — no correlation is
|
|
309
|
+
// needed to populate it) and consulted by `approval.candidate`/
|
|
310
|
+
// `approval.settled` (which do not carry toolName at all). Evicted on
|
|
311
|
+
// `approval.settled` — the terminal event for a requestId, after which it
|
|
312
|
+
// is never looked up again. A process that restarts between request and
|
|
313
|
+
// settlement (eve's own docs say this is expected and safe for eve itself
|
|
314
|
+
// — "the process can restart and the parked turn survives") simply finds
|
|
315
|
+
// this map empty and falls back to EVE_APPROVAL_TOOL_NAME, exactly this
|
|
316
|
+
// function's behaviour before this cache existed. See TD-411.
|
|
317
|
+
const requestIdToToolName = new Map();
|
|
318
|
+
function clientFor(sessionId) {
|
|
319
|
+
if (opts.client !== undefined)
|
|
320
|
+
return opts.client;
|
|
321
|
+
let client = perSession.get(sessionId);
|
|
322
|
+
if (client === undefined) {
|
|
323
|
+
try {
|
|
324
|
+
client = GateClient.fromEnv({ harness: 'eve', sessionId });
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
// fromEnv only throws on a missing session id, which we always
|
|
328
|
+
// supply — but a telemetry hook must never take the run down over a
|
|
329
|
+
// client it could not build.
|
|
330
|
+
client = null;
|
|
331
|
+
}
|
|
332
|
+
perSession.set(sessionId, client);
|
|
333
|
+
}
|
|
334
|
+
return client;
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
events: {
|
|
338
|
+
'input.requested': async (event, ctx) => {
|
|
339
|
+
const client = clientFor(ctx.session.id);
|
|
340
|
+
for (const request of event.data.requests) {
|
|
341
|
+
if (request.kind !== 'tool-approval' || request.action === undefined)
|
|
342
|
+
continue;
|
|
343
|
+
requestIdToToolName.set(request.requestId, request.action.toolName);
|
|
344
|
+
if (client === null)
|
|
345
|
+
continue;
|
|
346
|
+
await client.emit('tool_flagged', request.action.toolName, `eve requested human approval before running this tool (request ${request.requestId})`, request.action.input);
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
'approval.candidate': async (event, ctx) => {
|
|
350
|
+
if (event.data.outcome === 'pending')
|
|
351
|
+
return;
|
|
352
|
+
const client = clientFor(ctx.session.id);
|
|
353
|
+
if (client === null)
|
|
354
|
+
return;
|
|
355
|
+
const toolName = requestIdToToolName.get(event.data.requestId) ?? EVE_APPROVAL_TOOL_NAME;
|
|
356
|
+
const suffix = event.data.reason ? `: ${event.data.reason}` : '';
|
|
357
|
+
await client.emit('tool_flagged', toolName, `eve approval candidate ${event.data.outcome} (request ${event.data.requestId}, ` +
|
|
358
|
+
`responder ${event.data.responderPrincipalId})${suffix}`, event.data);
|
|
359
|
+
},
|
|
360
|
+
'approval.settled': async (event, ctx) => {
|
|
361
|
+
const client = clientFor(ctx.session.id);
|
|
362
|
+
const toolName = requestIdToToolName.get(event.data.requestId) ?? EVE_APPROVAL_TOOL_NAME;
|
|
363
|
+
requestIdToToolName.delete(event.data.requestId);
|
|
364
|
+
if (client === null)
|
|
365
|
+
return;
|
|
366
|
+
if (event.data.outcome === 'approved') {
|
|
367
|
+
await client.emit('tool_allowed', toolName, `eve approval settled: approved by ${event.data.responderPrincipalId} ` +
|
|
368
|
+
`(request ${event.data.requestId})`, event.data);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
await client.emit('tool_blocked', toolName, `eve approval settled: cancelled — the parked tool call never ran ` +
|
|
372
|
+
`(request ${event.data.requestId}, responder ${event.data.responderPrincipalId}). ` +
|
|
373
|
+
`Human veto recorded by the observe-only audit hook, not an Intutic gate refusal.`, event.data);
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=eve.js.map
|
package/dist/eve.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eve.js","sourceRoot":"","sources":["../src/eve.ts"],"names":[],"mappings":"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"}
|
package/dist/gate.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The enforcement point.
|
|
3
|
+
*
|
|
4
|
+
* Port of `packages/intutic-clawde/intutic_clawde/gate/gate.py`.
|
|
5
|
+
*
|
|
6
|
+
* Intutic ships PreToolUse hooks for the harnesses it has a native adapter
|
|
7
|
+
* for; frameworks outside that list (Mastra, the Vercel AI SDK, LangChain.js,
|
|
8
|
+
* a hand-rolled loop) have no adapter, and the sync-daemon writes no
|
|
9
|
+
* PreToolUse hook for them. This package is that enforcement point: the
|
|
10
|
+
* missing adapter, written against Intutic's own published gate contract.
|
|
11
|
+
*
|
|
12
|
+
* Four tiers, in order — identical precedence to the Python SDK:
|
|
13
|
+
*
|
|
14
|
+
* A1 policy snapshot port of intuticGate() fails CLOSED
|
|
15
|
+
* A3 SOP rules authored in the product fails OPEN (A2 covers it)
|
|
16
|
+
* A2 image integrity local check fails CLOSED
|
|
17
|
+
* B POST /hook-gate control-plane check fail posture set by GateClient
|
|
18
|
+
*
|
|
19
|
+
* A1 and A2 are load-bearing and local. Tier B contributes the DLP regexes
|
|
20
|
+
* and workspace policy from the control plane; whether an unreachable control
|
|
21
|
+
* plane blocks is the client's `failClosed` setting (default true).
|
|
22
|
+
*
|
|
23
|
+
* Tier A3 applies rules written in the SOP register rather than in code. It
|
|
24
|
+
* runs BEFORE A2 so that a block, when both would fire, is attributed to the
|
|
25
|
+
* authored policy rather than to the hardcoded one. It fails open because A2
|
|
26
|
+
* covers the identical case and fails closed: A3 moves where the policy is
|
|
27
|
+
* *written*, and is not what makes the run safe. See soprules.ts.
|
|
28
|
+
*
|
|
29
|
+
* ## Naming note for callers porting from other Intutic SDKs
|
|
30
|
+
*
|
|
31
|
+
* This is NOT the "static floor" tier the compiled shell/JS gate emitters
|
|
32
|
+
* carry (`staticFloorPatterns()` in
|
|
33
|
+
* `services/sync-daemon/src/harness/protectedPaths.ts`, concatenated ahead of
|
|
34
|
+
* the snapshot's own rules in `gateBody.ts`'s `intuticGate()`). Like the
|
|
35
|
+
* Python SDK it ports, this package's Tier A1 reads ONLY
|
|
36
|
+
* `~/.intutic/hooks/policy-snapshot.rules` — the compiled-in bypass/secret/
|
|
37
|
+
* skill-surface patterns never reach that file (only SOP-authored rules, the
|
|
38
|
+
* destructive-command tier, and the tier-promoted skill-surface rules do, via
|
|
39
|
+
* `buildSnapshotRules` in `services/sync-daemon/src/lib/policySnapshot.ts`).
|
|
40
|
+
* A workspace relying on this SDK for governance therefore gets a strict
|
|
41
|
+
* SUBSET of what a shipped shell/JS harness gate enforces. That gap already
|
|
42
|
+
* exists in the Python SDK this package ports; it is not introduced here. See
|
|
43
|
+
* `src/__tests__/fidelity.test.ts` for the parts of the shipped contract this
|
|
44
|
+
* package's Tier A1 DOES reproduce exactly (the destructive-command and
|
|
45
|
+
* skill-surface pattern tables, as they would arrive via a real snapshot).
|
|
46
|
+
*/
|
|
47
|
+
import { GateClient } from './client.js';
|
|
48
|
+
import * as imagecheck from './imagecheck.js';
|
|
49
|
+
import * as snapshot from './snapshot.js';
|
|
50
|
+
import * as soprules from './soprules.js';
|
|
51
|
+
/** Tools that cannot change anything. They still get the local snapshot check
|
|
52
|
+
* (Tier A1), but skip the remote gate call (Tier B). */
|
|
53
|
+
export declare const READ_ONLY_TOOLS: ReadonlySet<string>;
|
|
54
|
+
export interface GateConfig {
|
|
55
|
+
repoRoot?: string;
|
|
56
|
+
workspaceId?: string;
|
|
57
|
+
allowlistPath?: string;
|
|
58
|
+
enforce?: boolean;
|
|
59
|
+
useHookGate?: boolean;
|
|
60
|
+
useSopRules?: boolean;
|
|
61
|
+
}
|
|
62
|
+
interface ResolvedConfig {
|
|
63
|
+
repoRoot: string;
|
|
64
|
+
workspaceId: string;
|
|
65
|
+
allowlistPath: string;
|
|
66
|
+
enforce: boolean;
|
|
67
|
+
useHookGate: boolean;
|
|
68
|
+
useSopRules: boolean;
|
|
69
|
+
}
|
|
70
|
+
export type ToolInput = Record<string, unknown>;
|
|
71
|
+
export declare class Gate {
|
|
72
|
+
readonly cfg: ResolvedConfig;
|
|
73
|
+
readonly client: GateClient | null;
|
|
74
|
+
private _snapshot;
|
|
75
|
+
private _snapshotReported;
|
|
76
|
+
private _policy;
|
|
77
|
+
/** `null` = not fetched yet. A failed fetch caches `[]` so one unreachable
|
|
78
|
+
* control plane does not add a timeout to every subsequent tool call. */
|
|
79
|
+
private _sopRules;
|
|
80
|
+
constructor(cfg?: GateConfig, client?: GateClient | null);
|
|
81
|
+
private allowlistAbs;
|
|
82
|
+
getSnapshot(): snapshot.Snapshot;
|
|
83
|
+
/**
|
|
84
|
+
* Load the image allowlist.
|
|
85
|
+
*
|
|
86
|
+
* A missing or malformed allowlist is NOT treated as "allow everything".
|
|
87
|
+
* An empty policy with `require_digest` still refuses every unpinned
|
|
88
|
+
* image, which is the safe direction; a policy we cannot read at all
|
|
89
|
+
* throws, and the caller turns that into a block.
|
|
90
|
+
*/
|
|
91
|
+
getPolicy(): imagecheck.ImagePolicy;
|
|
92
|
+
/**
|
|
93
|
+
* Active SOP rules, fetched once per process.
|
|
94
|
+
*
|
|
95
|
+
* Deliberately not refreshed on a timer: a rule set that changes mid-run
|
|
96
|
+
* makes a verdict depend on when the fetch landed. Construct a new `Gate`
|
|
97
|
+
* (or clear the cache) to refresh.
|
|
98
|
+
*/
|
|
99
|
+
getSopRules(): Promise<soprules.SopRule[]>;
|
|
100
|
+
private emit;
|
|
101
|
+
/**
|
|
102
|
+
* Report snapshot condition exactly once per process — otherwise these
|
|
103
|
+
* states are computed and never read, and an operator cannot distinguish
|
|
104
|
+
* "snapshot missing on 400 machines" from "snapshot healthy".
|
|
105
|
+
*/
|
|
106
|
+
private reportSnapshotHealthOnce;
|
|
107
|
+
/** Throws {@link IntuticGateRefusal} if this call must not run. Resolves to allow. */
|
|
108
|
+
guard(toolName: string, toolInput: ToolInput): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
export declare function install(gate: Gate | null): void;
|
|
111
|
+
export declare function active(): Gate | null;
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAKH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC;yDACyD;AACzD,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAM9C,CAAA;AAEF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,OAAO,CAAA;CACrB;AAaD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAE/C,qBAAa,IAAI;IACf,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IAClC,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,OAAO,CAAsC;IACrD;8EAC0E;IAC1E,OAAO,CAAC,SAAS,CAAkC;gBAEvC,GAAG,GAAE,UAAe,EAAE,MAAM,GAAE,UAAU,GAAG,IAAW;IAKlE,OAAO,CAAC,YAAY;IAOpB,WAAW,IAAI,QAAQ,CAAC,QAAQ;IAOhC;;;;;;;OAOG;IACH,SAAS,IAAI,UAAU,CAAC,WAAW;IAwBnC;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAwBlC,IAAI;IAalB;;;;OAIG;YACW,wBAAwB;IAWtC,sFAAsF;IAChF,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAqGnE;AA0BD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAE/C;AAED,wBAAgB,MAAM,IAAI,IAAI,GAAG,IAAI,CAEpC"}
|