@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.
- package/README.md +54 -5
- package/dist/cjs/coverage-attestation.d.ts +27 -0
- package/dist/cjs/coverage-attestation.d.ts.map +1 -0
- package/dist/cjs/coverage-attestation.js +146 -0
- package/dist/cjs/coverage-attestation.js.map +1 -0
- package/dist/cjs/execution-grant.d.ts +41 -0
- package/dist/cjs/execution-grant.d.ts.map +1 -0
- package/dist/cjs/execution-grant.js +66 -0
- package/dist/cjs/execution-grant.js.map +1 -0
- package/dist/cjs/guard.d.ts.map +1 -1
- package/dist/cjs/guard.js +91 -37
- package/dist/cjs/guard.js.map +1 -1
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +13 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/policy.d.ts +1 -1
- package/dist/cjs/policy.d.ts.map +1 -1
- package/dist/cjs/policy.js +2 -2
- package/dist/cjs/policy.js.map +1 -1
- package/dist/cjs/tool-registry.d.ts +6 -5
- package/dist/cjs/tool-registry.d.ts.map +1 -1
- package/dist/cjs/tool-registry.js +7 -6
- package/dist/cjs/tool-registry.js.map +1 -1
- package/dist/cjs/types.d.ts +22 -2
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/with-coderifts.d.ts +6 -0
- package/dist/cjs/with-coderifts.d.ts.map +1 -1
- package/dist/cjs/with-coderifts.js +3 -0
- package/dist/cjs/with-coderifts.js.map +1 -1
- package/dist/esm/coverage-attestation.d.ts +27 -0
- package/dist/esm/coverage-attestation.d.ts.map +1 -0
- package/dist/esm/coverage-attestation.js +141 -0
- package/dist/esm/coverage-attestation.js.map +1 -0
- package/dist/esm/execution-grant.d.ts +41 -0
- package/dist/esm/execution-grant.d.ts.map +1 -0
- package/dist/esm/execution-grant.js +59 -0
- package/dist/esm/execution-grant.js.map +1 -0
- package/dist/esm/guard.d.ts.map +1 -1
- package/dist/esm/guard.js +91 -37
- package/dist/esm/guard.js.map +1 -1
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/policy.d.ts +1 -1
- package/dist/esm/policy.d.ts.map +1 -1
- package/dist/esm/policy.js +2 -2
- package/dist/esm/policy.js.map +1 -1
- package/dist/esm/tool-registry.d.ts +6 -5
- package/dist/esm/tool-registry.d.ts.map +1 -1
- package/dist/esm/tool-registry.js +7 -6
- package/dist/esm/tool-registry.js.map +1 -1
- package/dist/esm/types.d.ts +22 -2
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/with-coderifts.d.ts +6 -0
- package/dist/esm/with-coderifts.d.ts.map +1 -1
- package/dist/esm/with-coderifts.js +3 -0
- package/dist/esm/with-coderifts.js.map +1 -1
- 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 (
|
|
177
|
+
### Guarding the whole tool surface (registry scope)
|
|
178
178
|
|
|
179
|
-
`guardToolCall` guards one call.
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
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"}
|
package/dist/cjs/guard.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|