@intutic/gate 3.0.1 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -53,8 +53,11 @@ plane's hook gate cannot be reached, answers non-2xx, or answers
|
|
|
53
53
|
group policy, the MCP server registry, image provenance, promoted findings)
|
|
54
54
|
could not complete, there is no verdict, and the call is refused with
|
|
55
55
|
`HOOK_GATE`. Pass `failClosed: false` to let calls through during such an
|
|
56
|
-
outage. A request the hook gate cannot read (HTTP 400, `INVALID_REQUEST`)
|
|
57
|
-
|
|
56
|
+
outage. A request the hook gate cannot read (HTTP 400, `INVALID_REQUEST`),
|
|
57
|
+
and a key that lacks the scope the hook gate needs (HTTP 403,
|
|
58
|
+
`INSUFFICIENT_SCOPE`), are refused whatever `failClosed` says. So is a call a
|
|
59
|
+
`plan_approval:` SOP gates when the session's plan cannot be read: rule
|
|
60
|
+
failures always fail closed. intutic-clawde's `GateClient` behaves the
|
|
58
61
|
same way, held to it by `packages/shared-types/fixtures/hook-gate-response-vectors.json`.
|
|
59
62
|
|
|
60
63
|
Each hook-gate answer names its decision (`decisionId`). The gate reports the
|
|
@@ -79,14 +82,19 @@ without a word. Both SDKs run
|
|
|
79
82
|
|
|
80
83
|
| Export | From | What it is |
|
|
81
84
|
|---|---|---|
|
|
82
|
-
| `Gate`, `GateConfig` | `gate.ts` | The
|
|
85
|
+
| `Gate`, `GateConfig` | `gate.ts` | The eight-tier evaluator (A0, A1, R, M, A3, A2, D, B). `new Gate(cfg, client?)`, `await gate.guard(toolName, toolInput)`. |
|
|
86
|
+
| `Gate.recordOutcome(toolName, toolInput, outcome?)`, `ToolOutcome`, `toolOutcomeOf(result)` | `gate.ts`, `wrapTools.ts` | Records how a call that ran went (`{ exitCode, isError, output }`), per session, for Tier R. `toolOutcomeOf` reads one from a tool's return value. |
|
|
87
|
+
| `READ_ONLY_TOOLS` | `gate.ts` | Tool names that cannot change anything: they get the snapshot check but skip the SOP rules (A3) and the hook gate (B). |
|
|
88
|
+
| `CAN_EVALUATE_RULE_RECORDS`, `PLAN_CACHE_MS` | `gate.ts` | Whether this gate evaluates the snapshot's `@rule` records (Tier R; `true`), and how long it keeps a session's plan before reading it again (30,000 ms). |
|
|
83
89
|
| `install(gate)`, `active()` | `gate.ts` | Process-wide default gate, so wrapped tools don't need the instance threaded through every call site. |
|
|
84
|
-
| `IntuticGateRefusal`, `GateError`, `GateConnectionError` | `errors.ts` | Thrown on refusal. `.reason`, `.code` (a `GateRefusalCode`, listed in `GATE_REFUSAL_CODES`), `.incidentId` carry the structured verdict; `.message` carries the `[Intutic Governance] BLOCKED: ...` text. |
|
|
90
|
+
| `IntuticGateRefusal`, `GateError`, `GateConnectionError` | `errors.ts` | Thrown on refusal. `.reason`, `.code` (a `GateRefusalCode`, listed in `GATE_REFUSAL_CODES`), `.incidentId` carry the structured verdict; `.scope` (paths, tools, step, detector, rule) and `.evidence` say what the refusal concerns, so a retry can stay out of it (undefined when it names none, and in an OPAQUE workspace); `.message` carries the `[Intutic Governance] BLOCKED: ...` text. |
|
|
91
|
+
| `IntuticGateEscalation` | `errors.ts` | The `IntuticGateRefusal` (`code` `DECIDE_ESCALATED`) thrown when a decide rule could not decide the call; `.ruleId` names the rule. A caller that can ask its user asks with `.reason` and runs the call only on a yes. |
|
|
85
92
|
| `IntuticGateHold` | `errors.ts` | The `IntuticGateRefusal` a hold rule throws (`code` `HELD`) after recording the hold for approval; `.holdId` names it. See `hold.ts`. |
|
|
86
93
|
| `GateClient` | `client.ts` | Control-plane client (`hookGate`, `emit`, `localOnly`, `GateClient.fromEnv(...)`). |
|
|
87
94
|
| `wrapTool(fn \| tool, opts?)`, `wrapTools(list \| record, gate?)` | `wrapTools.ts` | Generic wrapping for a plain async function or an `{ execute, ... }`-shaped tool object. **This is the integration point for any JS framework without a dedicated adapter — LangChain.js included.** |
|
|
88
95
|
| `intuticHeaders(opts?)` | `headers.ts` | Headers for a proxy-pointed HTTP/OpenAI-compatible client (`x-session-id`, `x-workspace-id`, `x-intutic-harness`). |
|
|
89
|
-
| `loadSnapshot`, `evaluate`, `Snapshot`, `guardDisabledFromEnv` | `snapshot.ts` | Tier A1: reads `~/.intutic/hooks/policy-snapshot.rules` (or the file `INTUTIC_SNAPSHOT_RULES` names). |
|
|
96
|
+
| `loadSnapshot`, `evaluate`, `Snapshot`, `guardDisabledFromEnv` | `snapshot.ts` | Tier A1: reads `~/.intutic/hooks/policy-snapshot.rules` (or the file `INTUTIC_SNAPSHOT_RULES` names). `evaluate` returns the deciding match, with the shadow and warn matches it passed in `advisories`. |
|
|
97
|
+
| `decide(state, questions, opts?)`, `DecideEngineError` | `decideApi.ts`, `decideEngine.ts` | Asks the self-hosted decide engine a few narrow questions about any text, outside a gate; throws `DecideEngineError` when the engine is not configured, its host is refused, or it cannot answer in time. See [Decide rules](https://docs.intutic.ai/guide/decide#in-your-own-agent-decide). |
|
|
90
98
|
| `parseRules`, `firstMatch`, `fetchRules`, `fetchRegister`, `parseRegister`, `SopRule`, `SopRegister` | `soprules.ts` | Tier A3: SOP-authored `WHERE`-clause rules, and the register they come in (rules plus the workspace's intervention mode). |
|
|
91
99
|
| `checkCommand`, `checkImages`, `checkWrittenManifest`, `ImageVerdict` | `imagecheck.ts` | Tier A2: container-image provenance on deploy commands. |
|
|
92
100
|
| `McpRegistryRecord`, `McpAllowlistRecord` | `mcpRegistryRecord.ts` | Tier M: the snapshot's MCP server registry and allowlist (`Snapshot.mcpRegistry`, `Snapshot.mcpAllowlist`), decided as the hook gates and the MCP proxy decide them; a byte-identical copy of `@intutic/shared-types`' module. |
|
|
@@ -103,14 +111,23 @@ dropped, the SSO group policy still refuses, and every MCP call is refused with
|
|
|
103
111
|
`POLICY_SNAPSHOT_UNVERIFIED`. A hand-written snapshot for a test needs the line
|
|
104
112
|
too.
|
|
105
113
|
|
|
114
|
+
A SOP's `requires_before: action:run_tests[ok] -> …` is met only by a passing
|
|
115
|
+
test run this gate recorded for the session, with no file changed since.
|
|
116
|
+
`wrapTool` and `wrapTools` record every call they run. A caller that calls
|
|
117
|
+
`gate.guard()` itself must call `gate.recordOutcome(toolName, toolInput,
|
|
118
|
+
outcome)` after each call it runs, or the prerequisite is never met and the
|
|
119
|
+
gated tool is refused with `PREREQUISITE_UNMET`. With no session id
|
|
120
|
+
(`GateClient.sessionId`) nothing is recorded.
|
|
121
|
+
|
|
106
122
|
Full reference: [Gate SDK](https://docs.intutic.ai/reference/gate-sdk). Every export, with its signature and defaults: [API reference](https://docs.intutic.ai/reference/sdk/gate/).
|
|
107
123
|
|
|
108
124
|
### A note for sibling adapter phases
|
|
109
125
|
|
|
110
126
|
`Gate.guard()` is **async** (`Promise<void>`), unlike the Python SDK's
|
|
111
127
|
synchronous `Gate.guard()` — the network-backed tiers (SOP-rule fetch,
|
|
112
|
-
`POST /hook-gate`) use `fetch` here rather than Python's blocking
|
|
113
|
-
`urllib.request
|
|
128
|
+
`POST /hook-gate`) use `fetch` here rather than Python's blocking calls
|
|
129
|
+
(`urllib.request` for the SOP rules, `requests` for the hook gate). Every
|
|
130
|
+
adapter built on this package must `await` it.
|
|
114
131
|
|
|
115
132
|
### What Tier A1 does and does not cover
|
|
116
133
|
|
|
@@ -123,7 +140,10 @@ tables) the way the shipped shell/JS gate emitters do (`INTUTIC_FLOOR`,
|
|
|
123
140
|
concatenated ahead of the snapshot's own rules in `gateBody.ts`'s
|
|
124
141
|
`intuticGate()`). Only what actually flows through the `.rules` file —
|
|
125
142
|
SOP-authored rules, the destructive-command tier, and the tier-promoted
|
|
126
|
-
skill-surface rules — is enforced by Tier A1 here.
|
|
143
|
+
skill-surface rules — is enforced by Tier A1 here. The same file also carries
|
|
144
|
+
the `@rule` and `@decide` records that Tiers R and D evaluate, each with a
|
|
145
|
+
fallback line that refuses its tools in a gate that cannot evaluate the
|
|
146
|
+
record; this gate skips a fallback line only when its record decoded. This gap already exists in
|
|
127
147
|
`intutic_clawde`; it is preserved, not introduced, by this port. See
|
|
128
148
|
`src/__tests__/fidelity.test.ts` for exactly which parts of the shipped
|
|
129
149
|
contract Tier A1 DOES reproduce, verified against the real pattern tables.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intutic/gate",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Intutic pre-execution tool gate for JS/TS agent frameworks without a shipped Intutic harness (Mastra, the Vercel AI SDK, LangChain.js, dsh, and hand-rolled agent loops)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"vitest": "^4",
|
|
113
113
|
"workflow": "^5.0.1",
|
|
114
114
|
"zod": "^4.2.0",
|
|
115
|
-
"@intutic/shared-types": "3.0.
|
|
115
|
+
"@intutic/shared-types": "3.0.3"
|
|
116
116
|
},
|
|
117
117
|
"engines": {
|
|
118
118
|
"node": ">=18"
|