@coderifts/agent-guard 9.5.0 → 9.7.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.
Files changed (60) hide show
  1. package/README.md +54 -5
  2. package/dist/cjs/coverage-attestation.d.ts +27 -0
  3. package/dist/cjs/coverage-attestation.d.ts.map +1 -0
  4. package/dist/cjs/coverage-attestation.js +146 -0
  5. package/dist/cjs/coverage-attestation.js.map +1 -0
  6. package/dist/cjs/execution-grant.d.ts +41 -0
  7. package/dist/cjs/execution-grant.d.ts.map +1 -0
  8. package/dist/cjs/execution-grant.js +66 -0
  9. package/dist/cjs/execution-grant.js.map +1 -0
  10. package/dist/cjs/guard.d.ts.map +1 -1
  11. package/dist/cjs/guard.js +91 -37
  12. package/dist/cjs/guard.js.map +1 -1
  13. package/dist/cjs/index.d.ts +4 -0
  14. package/dist/cjs/index.d.ts.map +1 -1
  15. package/dist/cjs/index.js +13 -3
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/policy.d.ts +1 -1
  18. package/dist/cjs/policy.d.ts.map +1 -1
  19. package/dist/cjs/policy.js +2 -2
  20. package/dist/cjs/policy.js.map +1 -1
  21. package/dist/cjs/tool-registry.d.ts +6 -5
  22. package/dist/cjs/tool-registry.d.ts.map +1 -1
  23. package/dist/cjs/tool-registry.js +7 -6
  24. package/dist/cjs/tool-registry.js.map +1 -1
  25. package/dist/cjs/types.d.ts +22 -2
  26. package/dist/cjs/types.d.ts.map +1 -1
  27. package/dist/cjs/with-coderifts.d.ts +6 -0
  28. package/dist/cjs/with-coderifts.d.ts.map +1 -1
  29. package/dist/cjs/with-coderifts.js +3 -0
  30. package/dist/cjs/with-coderifts.js.map +1 -1
  31. package/dist/esm/coverage-attestation.d.ts +27 -0
  32. package/dist/esm/coverage-attestation.d.ts.map +1 -0
  33. package/dist/esm/coverage-attestation.js +141 -0
  34. package/dist/esm/coverage-attestation.js.map +1 -0
  35. package/dist/esm/execution-grant.d.ts +41 -0
  36. package/dist/esm/execution-grant.d.ts.map +1 -0
  37. package/dist/esm/execution-grant.js +59 -0
  38. package/dist/esm/execution-grant.js.map +1 -0
  39. package/dist/esm/guard.d.ts.map +1 -1
  40. package/dist/esm/guard.js +91 -37
  41. package/dist/esm/guard.js.map +1 -1
  42. package/dist/esm/index.d.ts +4 -0
  43. package/dist/esm/index.d.ts.map +1 -1
  44. package/dist/esm/index.js +2 -0
  45. package/dist/esm/index.js.map +1 -1
  46. package/dist/esm/policy.d.ts +1 -1
  47. package/dist/esm/policy.d.ts.map +1 -1
  48. package/dist/esm/policy.js +2 -2
  49. package/dist/esm/policy.js.map +1 -1
  50. package/dist/esm/tool-registry.d.ts +6 -5
  51. package/dist/esm/tool-registry.d.ts.map +1 -1
  52. package/dist/esm/tool-registry.js +7 -6
  53. package/dist/esm/tool-registry.js.map +1 -1
  54. package/dist/esm/types.d.ts +22 -2
  55. package/dist/esm/types.d.ts.map +1 -1
  56. package/dist/esm/with-coderifts.d.ts +6 -0
  57. package/dist/esm/with-coderifts.d.ts.map +1 -1
  58. package/dist/esm/with-coderifts.js +3 -0
  59. package/dist/esm/with-coderifts.js.map +1 -1
  60. package/package.json +1 -1
package/README.md CHANGED
@@ -174,17 +174,22 @@ When `withCodeRifts({ executorAttestation: { registry } })` is set and a CAS out
174
174
  > binder needed). A custom binder is still required only when the content lives under a different
175
175
  > argument name or must be resolved from `filesTouched`/`diff`.
176
176
 
177
- ### Guarding the whole tool surface (inescapability)
177
+ ### Guarding the whole tool surface (registry scope)
178
178
 
179
- `guardToolCall` guards one call. To make CodeRifts the **only** path a mutating tool can take, wrap
180
- your entire tool list with [`guardToolRegistry`](#) it returns the sole tool table the agent may
181
- see (every mutator wrapped, fail-closed at construction if any would remain raw):
179
+ `guardToolCall` guards one call. [`guardToolRegistry`](#) takes your whole tool list and returns a
180
+ table in which every mutator is wrapped, failing closed at construction if any would remain raw.
181
+ What that buys is a property of **the returned table**, not of the agent: register only this table,
182
+ and no mutator *in it* is reachable raw. Tools the host registers elsewhere are outside the guard —
183
+ see **The two scopes** below for how `registry_report` and `composition_assurance` answer those two
184
+ different questions.
182
185
 
183
186
  ```typescript
184
187
  import { guardToolRegistry } from '@coderifts/agent-guard';
185
188
 
186
189
  const { tools, coverage } = guardToolRegistry(rawTools, { guard: { client } });
187
- // register ONLY `tools` with your agent SDK; coverage === 'COMPLETE' ⇒ no mutator is reachable raw.
190
+ // register ONLY `tools`; coverage === 'COMPLETE' ⇒ no mutator IN THIS TABLE is reachable raw.
191
+ // That is table-truth, not a coverage claim about live traffic: for what was actually
192
+ // observed this run, read `composition_assurance.observed_class`.
188
193
  ```
189
194
 
190
195
  ### One-call orchestration with `withCodeRifts` (S1 + S2)
@@ -250,6 +255,41 @@ const { tools, registry_report, composition_assurance, receipt_thread } = withCo
250
255
  // register ONLY `tools`. Receipt carry-forward is default-on (`receipt_thread`).
251
256
  ```
252
257
 
258
+ ### Native execution grant (`executionGrant`, 9.6.0)
259
+
260
+ `withCodeRifts` 9.5.0 could not request a grant: its authorize sent four
261
+ fields and the factory received `decision_result`, so a top-level
262
+ `execution_grant` was dropped. The interim app-side wrap
263
+ (`withExecutionGrantClient` / `takeGrant()`) worked but was **last-authorize**
264
+ — overlapping tool calls could hand a tool the wrong grant.
265
+
266
+ 9.6.0 closes that natively. Default **OFF** (absent config is byte-identical
267
+ to 9.5.0). A host on 9.6.0 does **not** need `withExecutionGrantClient`.
268
+
269
+ ```typescript
270
+ const { tools } = withCodeRifts({
271
+ tools: rawTools, // execute(args, { execution_grant }) — 2nd arg is THIS call's grant
272
+ client,
273
+ operation: 'merge',
274
+ executionGrant: {
275
+ enabled: true,
276
+ // Optional. Return the ATOMIC nonce for THIS call (customer executor
277
+ // state-challenge). A throw fails the call closed
278
+ // (EXECUTION_GRANT_NONCE_UNRESOLVABLE) — never a grant-less proceed.
279
+ resolveStateNonce: async ({ artifactId, toolName, args }) =>
280
+ challengeNonceFor(artifactId),
281
+ },
282
+ });
283
+ ```
284
+
285
+ `guardToolCall` factory 3rd argument is the same `{ execution_grant }` object,
286
+ scoped to that invocation. Allow-class authorize that requested a grant and
287
+ does not receive one fails closed (`EXECUTION_GRANT_MISSING` /
288
+ `SIGNER_UNAVAILABLE`). After a grant was requested, `failPolicy: 'open'`
289
+ does not OPEN_PASSTHROUGH grant-less — the call fails closed with the
290
+ server's reason. The outcome records `{ requested, arrived }` only —
291
+ not the token. Not a verdict input; not a preimage field.
292
+
253
293
  Honesty (do not over-claim):
254
294
 
255
295
  - **Freshness** is ACTIVE only because STRICT sets `requireFreshness` **and** you supplied
@@ -927,6 +967,15 @@ Pass claim+lifecycle on `withCodeRifts({ …, onEvent, monitoringSinkWired: true
927
967
  - **Integrity failures never fail open** — a bad signature, schema-invalid response, detector/config
928
968
  error, or request-attributable rejection (413/422) always resolves closed + trips the breaker.
929
969
 
970
+ **The artifact is not the contract.** Every guarantee above keys off a change to a contract *file*.
971
+ An implementation edit under an unchanged spec changes the served behaviour and produces nothing for
972
+ this package to see: the detector does not trigger, no preflight fires, and a clean run means only
973
+ that the artifact did not move. A handler that starts returning `null` for a field the schema still
974
+ marks required, a response that quietly changes shape, an authorization check deleted behind a
975
+ byte-identical OpenAPI file — none of those are contract changes as far as this package is
976
+ concerned, and none of them are caught here. Governing the artifact is not the same as governing the
977
+ behaviour it describes, and this package does not diff served behaviour.
978
+
930
979
  ## Trigger detection
931
980
 
932
981
  `builtinDetector` (fail-safe, versioned) decides whether a tool call touches a contract artifact
@@ -0,0 +1,27 @@
1
+ import type { CoverageObserved } from './coverage-observed.js';
2
+ export declare const COVERAGE_ATTEST_VERSION = "cr.coverage.attest.v1";
3
+ export declare const COVERAGE_ATTEST_SIGNING_PREFIX = "crcovattest.v1";
4
+ export declare const COVERAGE_ATTEST_ENVELOPE_TAG = "cr.coverage.attest.v1";
5
+ export type CoverageAttestationSigner = (bytes: Uint8Array) => Uint8Array | Promise<Uint8Array>;
6
+ export type CoverageAttestationConfig = {
7
+ /** Customer-held coverage key id. Named on the token; resolved later against a registry. */
8
+ kid: string;
9
+ /** Host signs the UTF-8 signing-input bytes. Returns raw Ed25519 signature. Never a raw key. */
10
+ signer: CoverageAttestationSigner;
11
+ /** Scope label for the statement (e.g. a session id). Required — a statement needs a subject. */
12
+ sessionId: string;
13
+ };
14
+ export declare function coverageAttestSigningInput(body: Record<string, unknown>): string;
15
+ /**
16
+ * Issue a cr.coverage.attest.v1 token from a coverage snapshot. Returns undefined when config is
17
+ * absent, the snapshot is unusable, or the host signer throws — never an unsigned token.
18
+ */
19
+ export declare function tryIssueCoverageAttestation(args: {
20
+ config?: CoverageAttestationConfig | null;
21
+ coverage: CoverageObserved | null | undefined;
22
+ decisionId?: string | null;
23
+ receiptDigest?: string | null;
24
+ now?: string;
25
+ }): Promise<string | undefined>;
26
+ export declare function kidFromCoverageAttestation(token: string | undefined | null): string | null;
27
+ //# sourceMappingURL=coverage-attestation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage-attestation.d.ts","sourceRoot":"","sources":["../../src/coverage-attestation.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAC/D,eAAO,MAAM,4BAA4B,0BAA0B,CAAC;AAQpE,MAAM,MAAM,yBAAyB,GAAG,CACtC,KAAK,EAAE,UAAU,KACd,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,MAAM,yBAAyB,GAAG;IACtC,4FAA4F;IAC5F,GAAG,EAAE,MAAM,CAAC;IACZ,gGAAgG;IAChG,MAAM,EAAE,yBAAyB,CAAC;IAClC,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAUF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAchF;AAYD;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IACtD,MAAM,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC1C,QAAQ,EAAE,gBAAgB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4D9B;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK1F"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * cr.coverage.attest.v1 issuance (guard side).
3
+ *
4
+ * Wire/signing input MIRRORS app src/verdict-core/coverage-attestation.js. The guard SIGNS via a
5
+ * host-provided sign(bytes) callback — never a raw key in config. CodeRifts never holds the
6
+ * coverage private key. Custody model copied from tryIssueMonitoringAttestation, deliberately:
7
+ * one custody story for every host-signed artifact, not a second one per envelope.
8
+ *
9
+ * Observation-side only. Signer throw/empty → omit the token; never unsigned.
10
+ *
11
+ * ── THE PAYLOAD DECISION, and it is the point of this module ────────────────────────────────
12
+ * A signed statement must not assert more than the guard measured.
13
+ *
14
+ * The guard's own class vocabulary is WIDER than the envelope's, deliberately:
15
+ * guard UNKNOWN_OUTSIDE_SCOPE | INCOMPLETE_OBSERVED | COMPLETE_OBSERVED
16
+ * envelope UNKNOWN_OUTSIDE_SCOPE | INCOMPLETE_OBSERVED (no COMPLETE, by design)
17
+ *
18
+ * Half B absent (host never reported total dispatches): the guard knows governed_calls and
19
+ * nothing else. The token carries UNKNOWN_OUTSIDE_SCOPE and OMITS total_calls entirely. It does
20
+ * not default the total to governed_calls, and it does not send zero — absence is not zero, and a
21
+ * signed zero would be a lie with a signature on it.
22
+ *
23
+ * Guard COMPLETE_OBSERVED maps to envelope INCOMPLETE_OBSERVED. Not a downgrade for its own sake:
24
+ * the envelope's two classes encode "totals known" vs "totals unknown", and the app kernel rejects
25
+ * a COMPLETE payload as malformed rather than coercing it, because from inside the process the
26
+ * ABSENCE of an ungoverned call is unprovable. The numbers carry the finding — an empty
27
+ * ungoverned_tools tells the reader everything the host reported was governed, without a signed
28
+ * claim of completeness that we cannot back.
29
+ */
30
+ 'use strict';
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.COVERAGE_ATTEST_ENVELOPE_TAG = exports.COVERAGE_ATTEST_SIGNING_PREFIX = exports.COVERAGE_ATTEST_VERSION = void 0;
33
+ exports.coverageAttestSigningInput = coverageAttestSigningInput;
34
+ exports.tryIssueCoverageAttestation = tryIssueCoverageAttestation;
35
+ exports.kidFromCoverageAttestation = kidFromCoverageAttestation;
36
+ exports.COVERAGE_ATTEST_VERSION = 'cr.coverage.attest.v1';
37
+ exports.COVERAGE_ATTEST_SIGNING_PREFIX = 'crcovattest.v1';
38
+ exports.COVERAGE_ATTEST_ENVELOPE_TAG = 'cr.coverage.attest.v1';
39
+ /** Envelope classes. Intentionally two — there is no COMPLETE to emit. */
40
+ const ENVELOPE_CLASSES = ['INCOMPLETE_OBSERVED', 'UNKNOWN_OUTSIDE_SCOPE'];
41
+ /** NUL joins the tool-name list inside one pipe field, so a name can never forge a field. */
42
+ const NUL = '\x1f';
43
+ function scalar(v) {
44
+ return v == null ? '' : String(v);
45
+ }
46
+ function canonicalUngoverned(list) {
47
+ return Array.isArray(list) ? list.map((s) => String(s)).join(NUL) : '';
48
+ }
49
+ function coverageAttestSigningInput(body) {
50
+ const parts = [
51
+ exports.COVERAGE_ATTEST_SIGNING_PREFIX,
52
+ scalar(body.kid),
53
+ scalar(body.session_id),
54
+ scalar(body.observed_class),
55
+ body.governed_calls != null ? String(body.governed_calls) : '',
56
+ body.total_calls != null ? String(body.total_calls) : '',
57
+ canonicalUngoverned(body.ungoverned_tools),
58
+ scalar(body.decision_id),
59
+ scalar(body.receipt_digest),
60
+ scalar(body.observed_at),
61
+ ];
62
+ return parts.join('|');
63
+ }
64
+ function b64url(buf) {
65
+ return buf.toString('base64url');
66
+ }
67
+ /** True when the host reported Half B (total dispatches), so a total may be asserted. */
68
+ function hasHalfB(cov) {
69
+ return cov.class !== 'UNKNOWN_OUTSIDE_SCOPE'
70
+ && typeof cov.total_calls === 'number';
71
+ }
72
+ /**
73
+ * Issue a cr.coverage.attest.v1 token from a coverage snapshot. Returns undefined when config is
74
+ * absent, the snapshot is unusable, or the host signer throws — never an unsigned token.
75
+ */
76
+ async function tryIssueCoverageAttestation(args) {
77
+ const cfg = args.config;
78
+ if (!cfg || typeof cfg.kid !== 'string' || !cfg.kid || typeof cfg.signer !== 'function') {
79
+ return undefined;
80
+ }
81
+ if (typeof cfg.sessionId !== 'string' || cfg.sessionId.length === 0)
82
+ return undefined;
83
+ const cov = args.coverage;
84
+ if (!cov || typeof cov !== 'object')
85
+ return undefined;
86
+ if (typeof cov.governed_calls !== 'number' || !Number.isInteger(cov.governed_calls) || cov.governed_calls < 0) {
87
+ return undefined;
88
+ }
89
+ const halfB = hasHalfB(cov);
90
+ const observed_class = halfB ? 'INCOMPLETE_OBSERVED' : 'UNKNOWN_OUTSIDE_SCOPE';
91
+ if (!ENVELOPE_CLASSES.includes(observed_class))
92
+ return undefined;
93
+ const body = {
94
+ v: exports.COVERAGE_ATTEST_VERSION,
95
+ kid: cfg.kid,
96
+ session_id: cfg.sessionId,
97
+ observed_class,
98
+ governed_calls: cov.governed_calls,
99
+ observed_at: args.now || new Date().toISOString().replace(/\.\d{3}Z$/, 'Z'),
100
+ };
101
+ if (halfB) {
102
+ const withTotals = cov;
103
+ // A statement claiming more governed than dispatched is not a coverage statement — the app
104
+ // kernel rejects it as malformed, so refuse to mint it rather than emit a token that fails.
105
+ if (!Number.isInteger(withTotals.total_calls) || withTotals.total_calls < cov.governed_calls) {
106
+ return undefined;
107
+ }
108
+ body.total_calls = withTotals.total_calls;
109
+ body.ungoverned_tools = Array.isArray(withTotals.ungoverned_tools)
110
+ ? withTotals.ungoverned_tools.map((s) => String(s))
111
+ : [];
112
+ }
113
+ // else: total_calls and ungoverned_tools are OMITTED. Not zero. Not defaulted.
114
+ if (typeof args.decisionId === 'string' && args.decisionId)
115
+ body.decision_id = args.decisionId;
116
+ if (typeof args.receiptDigest === 'string' && args.receiptDigest)
117
+ body.receipt_digest = args.receiptDigest;
118
+ const input = Buffer.from(coverageAttestSigningInput(body), 'utf8');
119
+ let sig;
120
+ try {
121
+ sig = await cfg.signer(input);
122
+ }
123
+ catch {
124
+ return undefined;
125
+ }
126
+ if (sig == null)
127
+ return undefined;
128
+ const sigBuf = Buffer.isBuffer(sig) ? sig : Buffer.from(sig);
129
+ if (sigBuf.length === 0)
130
+ return undefined;
131
+ return [
132
+ exports.COVERAGE_ATTEST_ENVELOPE_TAG,
133
+ cfg.kid,
134
+ b64url(Buffer.from(JSON.stringify(body), 'utf8')),
135
+ b64url(sigBuf),
136
+ ].join('|');
137
+ }
138
+ function kidFromCoverageAttestation(token) {
139
+ if (typeof token !== 'string' || token.length === 0)
140
+ return null;
141
+ const parts = token.split('|');
142
+ if (parts.length !== 4 || parts[0] !== exports.COVERAGE_ATTEST_ENVELOPE_TAG)
143
+ return null;
144
+ return parts[1] || null;
145
+ }
146
+ //# sourceMappingURL=coverage-attestation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage-attestation.js","sourceRoot":"","sources":["../../src/coverage-attestation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Native execution-grant helpers (9.6.0).
3
+ *
4
+ * Grant request is per guardToolCall invocation (local vars). The token is not
5
+ * a verdict input and is not folded into any fingerprint preimage.
6
+ */
7
+ export type ExecutionGrantConfig = {
8
+ enabled: true;
9
+ resolveStateNonce?: (ctx: {
10
+ artifactId: string | null;
11
+ toolName: string;
12
+ args: unknown;
13
+ }) => string | Promise<string>;
14
+ };
15
+ export type ExecutionGrantObservation = {
16
+ requested: boolean;
17
+ arrived: boolean;
18
+ };
19
+ export type ExecutionGrantCallContext = {
20
+ execution_grant: string | null;
21
+ };
22
+ export declare function isExecutionGrantEnabled(config: {
23
+ executionGrant?: ExecutionGrantConfig;
24
+ } | null | undefined): boolean;
25
+ export declare function readExecutionGrantToken(response: unknown): string | null;
26
+ export declare function firstArtifactId(artifacts: unknown): string | null;
27
+ /** True when the thrown authorize error carries the named SIGNER_UNAVAILABLE code. */
28
+ export declare function isSignerUnavailableError(err: unknown): boolean;
29
+ export declare function resolveStateNonceForCall(config: {
30
+ executionGrant?: ExecutionGrantConfig;
31
+ }, call: {
32
+ toolName: string;
33
+ arguments?: unknown;
34
+ artifacts?: unknown;
35
+ }, artifacts: unknown): Promise<{
36
+ ok: true;
37
+ nonce?: string;
38
+ } | {
39
+ ok: false;
40
+ }>;
41
+ //# sourceMappingURL=execution-grant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-grant.d.ts","sourceRoot":"","sources":["../../src/execution-grant.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE;QACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,OAAO,CAAC;KACf,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAAE,cAAc,CAAC,EAAE,oBAAoB,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAErH;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIxE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CASjE;AAED,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAM9D;AAED,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE;IAAE,cAAc,CAAC,EAAE,oBAAoB,CAAA;CAAE,EACjD,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,EACpE,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,CAevD"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ /**
3
+ * Native execution-grant helpers (9.6.0).
4
+ *
5
+ * Grant request is per guardToolCall invocation (local vars). The token is not
6
+ * a verdict input and is not folded into any fingerprint preimage.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.isExecutionGrantEnabled = isExecutionGrantEnabled;
10
+ exports.readExecutionGrantToken = readExecutionGrantToken;
11
+ exports.firstArtifactId = firstArtifactId;
12
+ exports.isSignerUnavailableError = isSignerUnavailableError;
13
+ exports.resolveStateNonceForCall = resolveStateNonceForCall;
14
+ function isExecutionGrantEnabled(config) {
15
+ return !!(config && config.executionGrant && config.executionGrant.enabled === true);
16
+ }
17
+ function readExecutionGrantToken(response) {
18
+ if (!response || typeof response !== 'object')
19
+ return null;
20
+ const g = response.execution_grant;
21
+ return typeof g === 'string' && g.length > 0 ? g : null;
22
+ }
23
+ function firstArtifactId(artifacts) {
24
+ if (!Array.isArray(artifacts))
25
+ return null;
26
+ for (const a of artifacts) {
27
+ if (a && typeof a === 'object' && typeof a.id === 'string') {
28
+ const id = String(a.id).trim();
29
+ if (id)
30
+ return id;
31
+ }
32
+ }
33
+ return null;
34
+ }
35
+ /** True when the thrown authorize error carries the named SIGNER_UNAVAILABLE code. */
36
+ function isSignerUnavailableError(err) {
37
+ if (!err || typeof err !== 'object')
38
+ return false;
39
+ const e = err;
40
+ if (e.code === 'SIGNER_UNAVAILABLE')
41
+ return true;
42
+ if (e.body && e.body.code === 'SIGNER_UNAVAILABLE')
43
+ return true;
44
+ return false;
45
+ }
46
+ async function resolveStateNonceForCall(config, call, artifacts) {
47
+ const resolver = config.executionGrant && config.executionGrant.resolveStateNonce;
48
+ if (typeof resolver !== 'function')
49
+ return { ok: true };
50
+ try {
51
+ const raw = await resolver({
52
+ artifactId: firstArtifactId(artifacts) || firstArtifactId(call.artifacts),
53
+ toolName: call.toolName,
54
+ args: call.arguments,
55
+ });
56
+ if (raw == null || raw === '')
57
+ return { ok: true };
58
+ if (typeof raw !== 'string')
59
+ return { ok: false };
60
+ return { ok: true, nonce: raw };
61
+ }
62
+ catch {
63
+ return { ok: false };
64
+ }
65
+ }
66
+ //# sourceMappingURL=execution-grant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execution-grant.js","sourceRoot":"","sources":["../../src/execution-grant.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAoBH,0DAEC;AAED,0DAIC;AAED,0CASC;AAGD,4DAMC;AAED,4DAmBC;AAjDD,SAAgB,uBAAuB,CAAC,MAAoE;IAC1G,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;AACvF,CAAC;AAED,SAAgB,uBAAuB,CAAC,QAAiB;IACvD,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,CAAC,GAAI,QAA0C,CAAC,eAAe,CAAC;IACtE,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC;AAED,SAAgB,eAAe,CAAC,SAAkB;IAChD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAQ,CAAsB,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YACjF,MAAM,EAAE,GAAG,MAAM,CAAE,CAAoB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,IAAI,EAAE;gBAAE,OAAO,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sFAAsF;AACtF,SAAgB,wBAAwB,CAAC,GAAY;IACnD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,CAAC,GAAG,GAAoD,CAAC;IAC/D,IAAI,CAAC,CAAC,IAAI,KAAK,oBAAoB;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,oBAAoB;QAAE,OAAO,IAAI,CAAC;IAChE,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,KAAK,UAAU,wBAAwB,CAC5C,MAAiD,EACjD,IAAoE,EACpE,SAAkB;IAElB,MAAM,QAAQ,GAAG,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,iBAAiB,CAAC;IAClF,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC;YACzB,UAAU,EAAE,eAAe,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;YACzE,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,SAAS;SACrB,CAAC,CAAC;QACH,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,KAAK,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACnD,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,WAAW,EAAE,YAAY,EACT,kBAAkB,EAAE,cAAc,EAEnD,MAAM,YAAY,CAAC;AAYpB,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,2BAA2B,EACjC,MAAM,wBAAwB,CAAC;AA+ZhC;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,IAAI,EAAE,kBAAkB,EACxB,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,EACjC,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,oBAAoB,GAAG,2BAA2B,GAC/D,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CA+Y1B"}
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,WAAW,EAAE,YAAY,EACT,kBAAkB,EAAE,cAAc,EAEnD,MAAM,YAAY,CAAC;AAYpB,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,2BAA2B,EACjC,MAAM,wBAAwB,CAAC;AAgchC;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,IAAI,EAAE,kBAAkB,EACxB,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,EACjC,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,oBAAoB,GAAG,2BAA2B,GAC/D,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAqc1B"}