@coderifts/agent-guard 3.0.1 → 4.0.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 +46 -1
- package/dist/cjs/artifact-resolver.d.ts +8 -0
- package/dist/cjs/artifact-resolver.d.ts.map +1 -1
- package/dist/cjs/artifact-resolver.js +12 -1
- package/dist/cjs/artifact-resolver.js.map +1 -1
- package/dist/cjs/deploy-bind.d.ts +123 -0
- package/dist/cjs/deploy-bind.d.ts.map +1 -0
- package/dist/cjs/deploy-bind.js +112 -0
- package/dist/cjs/deploy-bind.js.map +1 -0
- package/dist/cjs/enforcement-gate.d.ts +13 -4
- package/dist/cjs/enforcement-gate.d.ts.map +1 -1
- package/dist/cjs/enforcement-gate.js +32 -7
- package/dist/cjs/enforcement-gate.js.map +1 -1
- package/dist/cjs/execution-proof.d.ts +132 -0
- package/dist/cjs/execution-proof.d.ts.map +1 -0
- package/dist/cjs/execution-proof.js +157 -0
- package/dist/cjs/execution-proof.js.map +1 -0
- package/dist/cjs/freshness.d.ts +244 -0
- package/dist/cjs/freshness.d.ts.map +1 -0
- package/dist/cjs/freshness.js +395 -0
- package/dist/cjs/freshness.js.map +1 -0
- package/dist/cjs/guard.d.ts +7 -1
- package/dist/cjs/guard.d.ts.map +1 -1
- package/dist/cjs/guard.js +114 -38
- package/dist/cjs/guard.js.map +1 -1
- package/dist/cjs/index.d.ts +10 -4
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +28 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/read-decision.d.ts +47 -0
- package/dist/cjs/read-decision.d.ts.map +1 -0
- package/dist/cjs/read-decision.js +161 -0
- package/dist/cjs/read-decision.js.map +1 -0
- package/dist/cjs/tool-registry.d.ts.map +1 -1
- package/dist/cjs/tool-registry.js +12 -1
- package/dist/cjs/tool-registry.js.map +1 -1
- package/dist/cjs/types.d.ts +28 -1
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/with-coderifts.d.ts +70 -8
- package/dist/cjs/with-coderifts.d.ts.map +1 -1
- package/dist/cjs/with-coderifts.js +177 -14
- package/dist/cjs/with-coderifts.js.map +1 -1
- package/dist/esm/artifact-resolver.d.ts +8 -0
- package/dist/esm/artifact-resolver.d.ts.map +1 -1
- package/dist/esm/artifact-resolver.js +11 -1
- package/dist/esm/artifact-resolver.js.map +1 -1
- package/dist/esm/deploy-bind.d.ts +123 -0
- package/dist/esm/deploy-bind.d.ts.map +1 -0
- package/dist/esm/deploy-bind.js +108 -0
- package/dist/esm/deploy-bind.js.map +1 -0
- package/dist/esm/enforcement-gate.d.ts +13 -4
- package/dist/esm/enforcement-gate.d.ts.map +1 -1
- package/dist/esm/enforcement-gate.js +32 -7
- package/dist/esm/enforcement-gate.js.map +1 -1
- package/dist/esm/execution-proof.d.ts +132 -0
- package/dist/esm/execution-proof.d.ts.map +1 -0
- package/dist/esm/execution-proof.js +151 -0
- package/dist/esm/execution-proof.js.map +1 -0
- package/dist/esm/freshness.d.ts +244 -0
- package/dist/esm/freshness.d.ts.map +1 -0
- package/dist/esm/freshness.js +384 -0
- package/dist/esm/freshness.js.map +1 -0
- package/dist/esm/guard.d.ts +7 -1
- package/dist/esm/guard.d.ts.map +1 -1
- package/dist/esm/guard.js +113 -37
- package/dist/esm/guard.js.map +1 -1
- package/dist/esm/index.d.ts +10 -4
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +10 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/read-decision.d.ts +47 -0
- package/dist/esm/read-decision.d.ts.map +1 -0
- package/dist/esm/read-decision.js +153 -0
- package/dist/esm/read-decision.js.map +1 -0
- package/dist/esm/tool-registry.d.ts.map +1 -1
- package/dist/esm/tool-registry.js +12 -1
- package/dist/esm/tool-registry.js.map +1 -1
- package/dist/esm/types.d.ts +28 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/with-coderifts.d.ts +70 -8
- package/dist/esm/with-coderifts.d.ts.map +1 -1
- package/dist/esm/with-coderifts.js +177 -14
- package/dist/esm/with-coderifts.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guard-produced execution proof block.
|
|
3
|
+
*
|
|
4
|
+
* Assembled ONLY from state the guard itself observed while handling a call. Callers cannot supply
|
|
5
|
+
* fields into this object: builders take GuardOutcome-internal facts, not a host "proof" option.
|
|
6
|
+
* The returned object is deeply frozen so post-return mutation of proof fields is rejected.
|
|
7
|
+
*
|
|
8
|
+
* What this block proves (when the corresponding fields are present):
|
|
9
|
+
* - preflight happened → preflighted + decision_id
|
|
10
|
+
* - receipt was fresh → receipt.status === 'VERIFIED_CURRENT' + expires_at
|
|
11
|
+
* - scope matched → binds_to.operation + currently_authorized
|
|
12
|
+
* - ran on the guarded path → execution.enforced === true (runtime-asserted only with
|
|
13
|
+
* receipt.verified + preflighted; same invariant the types encode)
|
|
14
|
+
* - artifact checked vs executed → change_fp is WHAT WAS CHECKED; execution_result_hash is NOT a
|
|
15
|
+
* general claim that the applied side effect matched that fp
|
|
16
|
+
*
|
|
17
|
+
* What this block must never claim: that the change is safe, that the host cannot bypass the
|
|
18
|
+
* package, or that an absent field means compliance. Those limits are explicit on every block.
|
|
19
|
+
*/
|
|
20
|
+
import type { GuardVerdict } from './types.js';
|
|
21
|
+
/** Machine-readable schema id for this block. */
|
|
22
|
+
export declare const EXECUTION_PROOF_SPEC: "guard-execution-proof.v1";
|
|
23
|
+
/**
|
|
24
|
+
* Hash of the factory return value — only when the value is already byte-stable.
|
|
25
|
+
*
|
|
26
|
+
* Not hashed (and the block says so) when:
|
|
27
|
+
* - the factory did not run / threw / produced no result
|
|
28
|
+
* - the result is an object, array, number, boolean, null, bigint, symbol, function — any of these
|
|
29
|
+
* would require a serialization choice (key order, undefined, non-JSON values) that reformats
|
|
30
|
+
* the value rather than hashing the bytes the factory returned
|
|
31
|
+
*
|
|
32
|
+
* A hash of a string/Buffer does NOT prove the contract artifacts applied match change_fp_checked.
|
|
33
|
+
* That gap is named on limits.
|
|
34
|
+
*/
|
|
35
|
+
export type ExecutionResultHash = {
|
|
36
|
+
status: 'hashed';
|
|
37
|
+
algorithm: 'sha256';
|
|
38
|
+
value: string;
|
|
39
|
+
} | {
|
|
40
|
+
status: 'not_hashed';
|
|
41
|
+
reason: 'not_executed' | 'execution_threw' | 'result_not_byte_stable' | 'result_type_unsupported';
|
|
42
|
+
};
|
|
43
|
+
export type GuardExecutionProof = {
|
|
44
|
+
proof_spec: typeof EXECUTION_PROOF_SPEC;
|
|
45
|
+
/** Observed: true iff this call completed a preflight round-trip that produced a decision envelope. */
|
|
46
|
+
preflighted: boolean;
|
|
47
|
+
/** Observed from the decision envelope when preflighted; null otherwise. */
|
|
48
|
+
decision_id: string | null;
|
|
49
|
+
receipt: {
|
|
50
|
+
/**
|
|
51
|
+
* Observed: true only when the guard's verify+bind step branded the envelope
|
|
52
|
+
* (requires valid signature, status VERIFIED_CURRENT, body hash + fp + scope match).
|
|
53
|
+
*/
|
|
54
|
+
verified: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Observed derivation: bind requires status === 'VERIFIED_CURRENT', so verified ⇒ this value.
|
|
57
|
+
* null when the receipt was not verified (or no receipt path).
|
|
58
|
+
*/
|
|
59
|
+
status: 'VERIFIED_CURRENT' | null;
|
|
60
|
+
/** Observed from the envelope when present; null when no envelope. */
|
|
61
|
+
expires_at: string | null;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Observed from the authenticated envelope fields when an envelope exists.
|
|
65
|
+
* change_fp is the fingerprint of WHAT WAS CHECKED (preflighted), not of what the factory applied.
|
|
66
|
+
* null when no envelope (SKIPPED / unavailable without envelope).
|
|
67
|
+
*/
|
|
68
|
+
binds_to: {
|
|
69
|
+
operation: string | null;
|
|
70
|
+
change_fp: string | null;
|
|
71
|
+
} | null;
|
|
72
|
+
/**
|
|
73
|
+
* Observed at verify time: true iff receipt.verified (VERIFIED_CURRENT + bind).
|
|
74
|
+
* false when an envelope/receipt was present but did not verify.
|
|
75
|
+
* null when there was no receipt path to evaluate (SKIPPED, no envelope).
|
|
76
|
+
*/
|
|
77
|
+
currently_authorized: boolean | null;
|
|
78
|
+
execution: {
|
|
79
|
+
attempted: boolean;
|
|
80
|
+
executed: boolean;
|
|
81
|
+
enforced: boolean;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Observed: kind of the guard verdict that produced this outcome.
|
|
85
|
+
* On a blocked call this is how the block is named (BLOCK / APPROVAL / UNAVAILABLE / …).
|
|
86
|
+
*/
|
|
87
|
+
verdict_kind: string;
|
|
88
|
+
execution_result_hash: ExecutionResultHash;
|
|
89
|
+
/**
|
|
90
|
+
* Explicit non-claims. Readers that treat missing fields as "ok" are wrong; these are always set.
|
|
91
|
+
*/
|
|
92
|
+
limits: {
|
|
93
|
+
does_not_claim_change_safe: true;
|
|
94
|
+
does_not_claim_host_cannot_bypass: true;
|
|
95
|
+
does_not_claim_absent_field_is_compliance: true;
|
|
96
|
+
change_fp_is_what_was_checked_not_what_executed: true;
|
|
97
|
+
calls_outside_guarded_path_invisible: true;
|
|
98
|
+
execution_result_hash_is_not_artifact_match_proof: true;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
export type ProofBuildInput = {
|
|
102
|
+
preflighted: boolean;
|
|
103
|
+
executionAttempted: boolean;
|
|
104
|
+
executed: boolean;
|
|
105
|
+
enforced: boolean;
|
|
106
|
+
verdict: GuardVerdict;
|
|
107
|
+
/** Present only when executed:true (factory returned). */
|
|
108
|
+
result?: unknown;
|
|
109
|
+
/** Present only when factory threw. */
|
|
110
|
+
error?: unknown;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Runtime twin of the type-level enforced⟺receiptVerified invariant.
|
|
114
|
+
* Throws if enforced:true is paired with anything other than receiptVerified+preflighted.
|
|
115
|
+
* The proof block is read by consumers that do not have our TypeScript brands.
|
|
116
|
+
*/
|
|
117
|
+
export declare function assertEnforcedReceiptInvariant(input: {
|
|
118
|
+
enforced: boolean;
|
|
119
|
+
preflighted: boolean;
|
|
120
|
+
receiptVerified: boolean;
|
|
121
|
+
}): void;
|
|
122
|
+
/**
|
|
123
|
+
* Honest byte hash of a factory return. Only string / Buffer / Uint8Array are hashed as raw bytes.
|
|
124
|
+
* Everything else is not_hashed with an explicit reason — never a JSON reformat hash.
|
|
125
|
+
*/
|
|
126
|
+
export declare function hashExecutionResult(result: unknown): ExecutionResultHash;
|
|
127
|
+
/**
|
|
128
|
+
* Build the proof block from guard-observed outcome facts only.
|
|
129
|
+
* Never accepts a caller-supplied proof object or partial field map.
|
|
130
|
+
*/
|
|
131
|
+
export declare function buildExecutionProof(input: ProofBuildInput): GuardExecutionProof;
|
|
132
|
+
//# sourceMappingURL=execution-proof.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-proof.d.ts","sourceRoot":"","sources":["../../src/execution-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,EAAG,0BAAmC,CAAC;AAExE;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxD;IACE,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EACF,cAAc,GACd,iBAAiB,GACjB,wBAAwB,GACxB,yBAAyB,CAAC;CAC/B,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,OAAO,oBAAoB,CAAC;IACxC,uGAAuG;IACvG,WAAW,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE;QACP;;;WAGG;QACH,QAAQ,EAAE,OAAO,CAAC;QAClB;;;WAGG;QACH,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;QAClC,sEAAsE;QACtE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC;IACF;;;;OAIG;IACH,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,IAAI,CAAC;IACT;;;;OAIG;IACH,oBAAoB,EAAE,OAAO,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE;QACT,SAAS,EAAE,OAAO,CAAC;QACnB,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,OAAO,CAAC;KACnB,CAAC;IACF;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,mBAAmB,CAAC;IAC3C;;OAEG;IACH,MAAM,EAAE;QACN,0BAA0B,EAAE,IAAI,CAAC;QACjC,iCAAiC,EAAE,IAAI,CAAC;QACxC,yCAAyC,EAAE,IAAI,CAAC;QAChD,+CAA+C,EAAE,IAAI,CAAC;QACtD,oCAAoC,EAAE,IAAI,CAAC;QAC3C,iDAAiD,EAAE,IAAI,CAAC;KACzD,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uCAAuC;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAWF;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,EAAE,OAAO,CAAC;CAC1B,GAAG,IAAI,CAQP;AA0BD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,GAAG,mBAAmB,CAuBxE;AAeD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,mBAAmB,CAsD/E"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Guard-produced execution proof block.
|
|
4
|
+
*
|
|
5
|
+
* Assembled ONLY from state the guard itself observed while handling a call. Callers cannot supply
|
|
6
|
+
* fields into this object: builders take GuardOutcome-internal facts, not a host "proof" option.
|
|
7
|
+
* The returned object is deeply frozen so post-return mutation of proof fields is rejected.
|
|
8
|
+
*
|
|
9
|
+
* What this block proves (when the corresponding fields are present):
|
|
10
|
+
* - preflight happened → preflighted + decision_id
|
|
11
|
+
* - receipt was fresh → receipt.status === 'VERIFIED_CURRENT' + expires_at
|
|
12
|
+
* - scope matched → binds_to.operation + currently_authorized
|
|
13
|
+
* - ran on the guarded path → execution.enforced === true (runtime-asserted only with
|
|
14
|
+
* receipt.verified + preflighted; same invariant the types encode)
|
|
15
|
+
* - artifact checked vs executed → change_fp is WHAT WAS CHECKED; execution_result_hash is NOT a
|
|
16
|
+
* general claim that the applied side effect matched that fp
|
|
17
|
+
*
|
|
18
|
+
* What this block must never claim: that the change is safe, that the host cannot bypass the
|
|
19
|
+
* package, or that an absent field means compliance. Those limits are explicit on every block.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.EXECUTION_PROOF_SPEC = void 0;
|
|
23
|
+
exports.assertEnforcedReceiptInvariant = assertEnforcedReceiptInvariant;
|
|
24
|
+
exports.hashExecutionResult = hashExecutionResult;
|
|
25
|
+
exports.buildExecutionProof = buildExecutionProof;
|
|
26
|
+
const node_crypto_1 = require("node:crypto");
|
|
27
|
+
/** Machine-readable schema id for this block. */
|
|
28
|
+
exports.EXECUTION_PROOF_SPEC = 'guard-execution-proof.v1';
|
|
29
|
+
const LIMITS = Object.freeze({
|
|
30
|
+
does_not_claim_change_safe: true,
|
|
31
|
+
does_not_claim_host_cannot_bypass: true,
|
|
32
|
+
does_not_claim_absent_field_is_compliance: true,
|
|
33
|
+
change_fp_is_what_was_checked_not_what_executed: true,
|
|
34
|
+
calls_outside_guarded_path_invisible: true,
|
|
35
|
+
execution_result_hash_is_not_artifact_match_proof: true,
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Runtime twin of the type-level enforced⟺receiptVerified invariant.
|
|
39
|
+
* Throws if enforced:true is paired with anything other than receiptVerified+preflighted.
|
|
40
|
+
* The proof block is read by consumers that do not have our TypeScript brands.
|
|
41
|
+
*/
|
|
42
|
+
function assertEnforcedReceiptInvariant(input) {
|
|
43
|
+
if (input.enforced === true) {
|
|
44
|
+
if (input.preflighted !== true || input.receiptVerified !== true) {
|
|
45
|
+
throw new Error('@coderifts/agent-guard: enforced:true without receiptVerified+preflighted (runtime invariant)');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function receiptVerifiedOf(verdict) {
|
|
50
|
+
if ('receiptVerified' in verdict && typeof verdict.receiptVerified === 'boolean') {
|
|
51
|
+
return verdict.receiptVerified === true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
function envelopeOf(verdict) {
|
|
56
|
+
if ('envelope' in verdict && verdict.envelope && typeof verdict.envelope === 'object') {
|
|
57
|
+
return verdict.envelope;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Honest byte hash of a factory return. Only string / Buffer / Uint8Array are hashed as raw bytes.
|
|
63
|
+
* Everything else is not_hashed with an explicit reason — never a JSON reformat hash.
|
|
64
|
+
*/
|
|
65
|
+
function hashExecutionResult(result) {
|
|
66
|
+
if (typeof result === 'string') {
|
|
67
|
+
return {
|
|
68
|
+
status: 'hashed',
|
|
69
|
+
algorithm: 'sha256',
|
|
70
|
+
value: 'sha256:' + (0, node_crypto_1.createHash)('sha256').update(result, 'utf8').digest('hex'),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(result)) {
|
|
74
|
+
return {
|
|
75
|
+
status: 'hashed',
|
|
76
|
+
algorithm: 'sha256',
|
|
77
|
+
value: 'sha256:' + (0, node_crypto_1.createHash)('sha256').update(result).digest('hex'),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (result instanceof Uint8Array) {
|
|
81
|
+
return {
|
|
82
|
+
status: 'hashed',
|
|
83
|
+
algorithm: 'sha256',
|
|
84
|
+
value: 'sha256:' + (0, node_crypto_1.createHash)('sha256').update(result).digest('hex'),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return { status: 'not_hashed', reason: 'result_not_byte_stable' };
|
|
88
|
+
}
|
|
89
|
+
function executionResultHashOf(input) {
|
|
90
|
+
if (input.executionAttempted && !input.executed && 'error' in input && input.error !== undefined) {
|
|
91
|
+
return { status: 'not_hashed', reason: 'execution_threw' };
|
|
92
|
+
}
|
|
93
|
+
if (!input.executed) {
|
|
94
|
+
return { status: 'not_hashed', reason: 'not_executed' };
|
|
95
|
+
}
|
|
96
|
+
if (!('result' in input)) {
|
|
97
|
+
return { status: 'not_hashed', reason: 'result_type_unsupported' };
|
|
98
|
+
}
|
|
99
|
+
return hashExecutionResult(input.result);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Build the proof block from guard-observed outcome facts only.
|
|
103
|
+
* Never accepts a caller-supplied proof object or partial field map.
|
|
104
|
+
*/
|
|
105
|
+
function buildExecutionProof(input) {
|
|
106
|
+
const receiptVerified = receiptVerifiedOf(input.verdict);
|
|
107
|
+
assertEnforcedReceiptInvariant({
|
|
108
|
+
enforced: input.enforced,
|
|
109
|
+
preflighted: input.preflighted,
|
|
110
|
+
receiptVerified,
|
|
111
|
+
});
|
|
112
|
+
const env = envelopeOf(input.verdict);
|
|
113
|
+
const hasEnvelope = env !== null;
|
|
114
|
+
let decision_id = null;
|
|
115
|
+
let expires_at = null;
|
|
116
|
+
let binds_to = null;
|
|
117
|
+
if (hasEnvelope && env) {
|
|
118
|
+
decision_id = typeof env.decision_id === 'string' ? env.decision_id : null;
|
|
119
|
+
expires_at = typeof env.expires_at === 'string' ? env.expires_at : null;
|
|
120
|
+
binds_to = Object.freeze({
|
|
121
|
+
operation: typeof env.operation === 'string' ? env.operation : null,
|
|
122
|
+
change_fp: typeof env.fingerprint === 'string' ? env.fingerprint : null,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// currently_authorized: only evaluable when a receipt path existed.
|
|
126
|
+
// verified ⇒ true (bind required VERIFIED_CURRENT). envelope present but not verified ⇒ false.
|
|
127
|
+
// no envelope (SKIPPED / some UNAVAILABLE) ⇒ null.
|
|
128
|
+
let currently_authorized = null;
|
|
129
|
+
if (hasEnvelope) {
|
|
130
|
+
currently_authorized = receiptVerified;
|
|
131
|
+
}
|
|
132
|
+
const proof = {
|
|
133
|
+
proof_spec: exports.EXECUTION_PROOF_SPEC,
|
|
134
|
+
preflighted: input.preflighted === true,
|
|
135
|
+
decision_id,
|
|
136
|
+
receipt: Object.freeze({
|
|
137
|
+
verified: receiptVerified,
|
|
138
|
+
status: receiptVerified ? 'VERIFIED_CURRENT' : null,
|
|
139
|
+
expires_at,
|
|
140
|
+
}),
|
|
141
|
+
binds_to: binds_to ? Object.freeze(binds_to) : null,
|
|
142
|
+
currently_authorized,
|
|
143
|
+
execution: Object.freeze({
|
|
144
|
+
attempted: input.executionAttempted === true,
|
|
145
|
+
executed: input.executed === true,
|
|
146
|
+
enforced: input.enforced === true,
|
|
147
|
+
}),
|
|
148
|
+
verdict_kind: typeof input.verdict?.kind === 'string' ? input.verdict.kind : 'UNKNOWN',
|
|
149
|
+
execution_result_hash: Object.freeze(executionResultHashOf(input)),
|
|
150
|
+
limits: LIMITS,
|
|
151
|
+
};
|
|
152
|
+
return freezeProof(proof);
|
|
153
|
+
}
|
|
154
|
+
function freezeProof(p) {
|
|
155
|
+
return Object.freeze(p);
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=execution-proof.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-proof.js","sourceRoot":"","sources":["../../src/execution-proof.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Freshness-safe prior content — PURE comparison core (TOCTOU close for the fresh-snapshot conjunct).
|
|
3
|
+
*
|
|
4
|
+
* Settled decisions (do not relitigate):
|
|
5
|
+
* 1. Freshness is CONTENT IDENTITY, not time. No TTL. Byte identity of `before` vs gate-time resolve.
|
|
6
|
+
* 2. The caller NAMES (artifact id); the gate RESOLVES prior content. A caller-supplied `before`
|
|
7
|
+
* is a claim, not a measurement — no fallback ladder that relabels a guess as measured.
|
|
8
|
+
* 3. Four outcomes, never collapsed: TARGET_MUTATED | STALE_CONTEXT | TAMPERED | UNKNOWN_FRESHNESS.
|
|
9
|
+
* 4. STALE_CONTEXT fails closed by default; policy may opt out deliberately.
|
|
10
|
+
* 5. Tree hash is OPTIONAL in the binding. Without it, STALE_CONTEXT is skipped, TARGET_MUTATED
|
|
11
|
+
* still runs, and the result SAYS the reduced level (never silently pretends full check ran).
|
|
12
|
+
*
|
|
13
|
+
* Merge-gate pattern generalized: recompute from current inputs; compare to what preflight bound;
|
|
14
|
+
* do not trust a claim about itself. Tree hash stays OUT of verdict_fingerprint and input_fingerprint
|
|
15
|
+
* (those preimages are frozen — their frozenness is what makes recompute meaningful).
|
|
16
|
+
*
|
|
17
|
+
* PURE: no I/O, no network, no Date.now(). Host supplies resolved content as inputs.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Four outcomes. Callers distinguish them by the `outcome` field (never by message text alone).
|
|
21
|
+
*
|
|
22
|
+
* TARGET_MUTATED — the contract `before` bytes moved (field removal, type change, …)
|
|
23
|
+
* STALE_CONTEXT — repository path-set tree moved, contract `before` identical (e.g. format-only
|
|
24
|
+
* neighbouring files, or raw blob change with same contract content). Message
|
|
25
|
+
* MUST state this is not tampering.
|
|
26
|
+
* TAMPERED — contract moved AND tree moved (both axes disagree)
|
|
27
|
+
* UNKNOWN_FRESHNESS — a candidate was named, but current state is not measurable (missing resolve)
|
|
28
|
+
*
|
|
29
|
+
* Plus FRESH when both applicable axes match.
|
|
30
|
+
*/
|
|
31
|
+
export type FreshnessOutcome = 'FRESH' | 'TARGET_MUTATED' | 'STALE_CONTEXT' | 'TAMPERED' | 'UNKNOWN_FRESHNESS';
|
|
32
|
+
/**
|
|
33
|
+
* Which axes were eligible to run.
|
|
34
|
+
* full — tree hash was bound; contract + tree both evaluated
|
|
35
|
+
* contract_only — no tree hash on the binding; only TARGET_MUTATED axis ran (reported, not silent)
|
|
36
|
+
*/
|
|
37
|
+
export type FreshnessCheckLevel = 'full' | 'contract_only';
|
|
38
|
+
export type FreshnessAssessInput = {
|
|
39
|
+
/**
|
|
40
|
+
* Contract `before` that entered preflight (and thus digests / the decision). Bound measurement —
|
|
41
|
+
* not a host claim at execute time.
|
|
42
|
+
*/
|
|
43
|
+
preflightBefore: string;
|
|
44
|
+
/**
|
|
45
|
+
* Gate-resolved prior content for the same artifact id NOW.
|
|
46
|
+
* null/undefined = current state not measurable → UNKNOWN_FRESHNESS.
|
|
47
|
+
* The gate (or host adapter feeding the gate) supplies this by resolving the caller's artifact id;
|
|
48
|
+
* a caller-supplied `before` string must NOT be passed here as if measured.
|
|
49
|
+
*/
|
|
50
|
+
resolvedBeforeNow: string | null | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Optional tree commitment bound at preflight (additive; NOT in input_fingerprint / verdict_fp).
|
|
53
|
+
* Absent/empty → level is contract_only; STALE_CONTEXT axis is skipped.
|
|
54
|
+
*/
|
|
55
|
+
preflightTreeHash?: string | null;
|
|
56
|
+
/**
|
|
57
|
+
* Tree commitment recomputed at gate time from the same path set + current blobs.
|
|
58
|
+
* Only consulted when preflightTreeHash is present.
|
|
59
|
+
* null/undefined when tree was bound but cannot be re-measured → UNKNOWN_FRESHNESS.
|
|
60
|
+
*/
|
|
61
|
+
resolvedTreeHashNow?: string | null | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Policy opt-out for STALE_CONTEXT only (default false = fail closed).
|
|
64
|
+
* TARGET_MUTATED / TAMPERED / UNKNOWN_FRESHNESS are never opted out by this flag.
|
|
65
|
+
* Same shape as an explicit team choice (approver allowlist): say so deliberately.
|
|
66
|
+
*/
|
|
67
|
+
allowStaleContext?: boolean;
|
|
68
|
+
};
|
|
69
|
+
export type FreshnessAssessResult = {
|
|
70
|
+
outcome: FreshnessOutcome;
|
|
71
|
+
/** Which axes ran. Always set — even on FRESH — so a reduced check cannot look like a full one. */
|
|
72
|
+
level: FreshnessCheckLevel;
|
|
73
|
+
/** True when the gate must refuse enforced execution. */
|
|
74
|
+
failClosed: boolean;
|
|
75
|
+
/** Contract before bytes match (only meaningful when resolvedBeforeNow was measurable). */
|
|
76
|
+
contractMatch: boolean | null;
|
|
77
|
+
/** Tree match; null when tree axis skipped or unmeasurable. */
|
|
78
|
+
treeMatch: boolean | null;
|
|
79
|
+
/**
|
|
80
|
+
* Human message. For STALE_CONTEXT always includes that this is not tampering.
|
|
81
|
+
* Machine consumers should branch on `outcome`, not parse the message.
|
|
82
|
+
*/
|
|
83
|
+
message: string;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Write-style call: path + new content only is the shape the composition residual names.
|
|
87
|
+
* Gateable requires an artifact identifier the gate can resolve — not a caller-supplied before.
|
|
88
|
+
*/
|
|
89
|
+
export type WriteStylePriorInput = {
|
|
90
|
+
/** Artifact id from a prior preflight artifacts[] entry (caller names; gate resolves). */
|
|
91
|
+
artifactId?: string | null;
|
|
92
|
+
path?: string | null;
|
|
93
|
+
/** New content (the write payload). */
|
|
94
|
+
after?: string | null;
|
|
95
|
+
/**
|
|
96
|
+
* If present, this is a CLAIM. It is never treated as a measurement and never substitutes
|
|
97
|
+
* for artifactId. Recorded only so tests can assert there is no "use claimed before" ladder.
|
|
98
|
+
*/
|
|
99
|
+
claimedBefore?: string | null;
|
|
100
|
+
};
|
|
101
|
+
export type WriteStylePriorResult = {
|
|
102
|
+
gateable: boolean;
|
|
103
|
+
reason: 'ok' | 'MISSING_ARTIFACT_ID' | 'CLAIMED_BEFORE_NOT_MEASUREMENT';
|
|
104
|
+
message: string;
|
|
105
|
+
/** Always false — claimedBefore is never elevated to a measurement. */
|
|
106
|
+
claimedBeforeAcceptedAsMeasurement: false;
|
|
107
|
+
};
|
|
108
|
+
/** Byte identity of two content strings (freshness definition: not time, not TTL). */
|
|
109
|
+
export declare function contentByteIdentical(a: string, b: string): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Optional path-set tree commitment. Additive only — never fold into input_fingerprint or
|
|
112
|
+
* verdict_fingerprint. Preimage: sorted path + sha256(content), then outer sha256.
|
|
113
|
+
* Missing content for a path is the caller's problem: pass only complete pairs.
|
|
114
|
+
*/
|
|
115
|
+
export declare function computePathSetTreeHash(entries: ReadonlyArray<{
|
|
116
|
+
path: string;
|
|
117
|
+
content: string;
|
|
118
|
+
}>): string;
|
|
119
|
+
/**
|
|
120
|
+
* Assess freshness of prior content by recompute-and-compare (merge-gate pattern generalized).
|
|
121
|
+
*
|
|
122
|
+
* Pure. Does not read the filesystem; the host/adapter resolves artifact id → content and passes
|
|
123
|
+
* `resolvedBeforeNow` / optional tree hashes as inputs.
|
|
124
|
+
*/
|
|
125
|
+
export declare function assessFreshness(input: FreshnessAssessInput): FreshnessAssessResult;
|
|
126
|
+
/**
|
|
127
|
+
* Write-style prior requirements (Decision 2).
|
|
128
|
+
* Caller must supply artifactId. claimedBefore is never accepted as measurement.
|
|
129
|
+
*/
|
|
130
|
+
export declare function assessWriteStylePrior(input: WriteStylePriorInput): WriteStylePriorResult;
|
|
131
|
+
/**
|
|
132
|
+
* Convenience: whether enforced execution is allowed for this freshness result.
|
|
133
|
+
* Equivalent to !failClosed: FRESH always; STALE_CONTEXT only when the team opted out;
|
|
134
|
+
* TARGET_MUTATED / TAMPERED / UNKNOWN never.
|
|
135
|
+
*/
|
|
136
|
+
export declare function freshnessAllowsEnforce(result: FreshnessAssessResult): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Whether a resolver ran for THIS call.
|
|
139
|
+
* ACTIVE — resolver was supplied and returned content for at least one artifact id
|
|
140
|
+
* NOT_CONFIGURED — no resolver on the host config; we never attempted measurement
|
|
141
|
+
* DEGRADED — resolver was supplied and threw, or returned nothing usable
|
|
142
|
+
*
|
|
143
|
+
* NOT_CONFIGURED ≠ UNKNOWN_FRESHNESS. The latter is an assessFreshness outcome after a measurement
|
|
144
|
+
* was attempted with empty/unusable resolved content under ACTIVE wiring.
|
|
145
|
+
*/
|
|
146
|
+
export type FreshnessWiringState = 'ACTIVE' | 'NOT_CONFIGURED' | 'DEGRADED';
|
|
147
|
+
export type FreshnessDegradeReason = 'resolver_threw' | 'resolver_returned_empty' | 'resolver_returned_non_string';
|
|
148
|
+
/**
|
|
149
|
+
* Per-call forensic basis. Rides on the GuardOutcome so a receipt chain audited later can see,
|
|
150
|
+
* call by call, whether the check ran — not only a composition-level "wired?" flag.
|
|
151
|
+
*/
|
|
152
|
+
export type FreshnessBasis = {
|
|
153
|
+
wiring: FreshnessWiringState;
|
|
154
|
+
/** Present when wiring === ACTIVE and assessFreshness ran against preflight before. */
|
|
155
|
+
assessment?: FreshnessAssessResult;
|
|
156
|
+
/** Present when wiring === DEGRADED — never report DEGRADED as NOT_CONFIGURED. */
|
|
157
|
+
degrade?: {
|
|
158
|
+
reason: FreshnessDegradeReason;
|
|
159
|
+
detail?: string;
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* Whether this call was treated as write-style (path + new content / needs prior resolve).
|
|
163
|
+
* Forensic: opt-out on a write is not silent.
|
|
164
|
+
*/
|
|
165
|
+
write_style: boolean;
|
|
166
|
+
/** Config requireFreshness for this call (policy). */
|
|
167
|
+
require_freshness: boolean;
|
|
168
|
+
};
|
|
169
|
+
/** Host callback: artifact id → current prior content. Async I/O lives here — never inside assessFreshness. */
|
|
170
|
+
export type PriorContentResolver = (req: {
|
|
171
|
+
artifactId: string;
|
|
172
|
+
path?: string;
|
|
173
|
+
toolName: string;
|
|
174
|
+
}) => Promise<string | null | undefined> | string | null | undefined;
|
|
175
|
+
/**
|
|
176
|
+
* Values the RUNNER collected before entering the pure guard path.
|
|
177
|
+
* The guard never invokes the resolver; it only consumes these values.
|
|
178
|
+
*/
|
|
179
|
+
export type FreshnessCallContext = {
|
|
180
|
+
wiring: FreshnessWiringState;
|
|
181
|
+
/** artifactId → resolved current before (only when wiring ACTIVE or partial DEGRADED with empties) */
|
|
182
|
+
priorResolved?: Record<string, string | null | undefined>;
|
|
183
|
+
degrade?: {
|
|
184
|
+
reason: FreshnessDegradeReason;
|
|
185
|
+
detail?: string;
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Detect write-style: contract-relevant path present, but no both-side artifacts on the descriptor.
|
|
190
|
+
* (edits[]/old_string+new_string binders already lift both sides — those are not write-style.)
|
|
191
|
+
*/
|
|
192
|
+
export declare function isWriteStyleCall(call: {
|
|
193
|
+
artifacts?: ReadonlyArray<{
|
|
194
|
+
before?: unknown;
|
|
195
|
+
after?: unknown;
|
|
196
|
+
}> | undefined;
|
|
197
|
+
arguments?: unknown;
|
|
198
|
+
filesTouched?: string[];
|
|
199
|
+
}): boolean;
|
|
200
|
+
/** Artifact ids the runner should ask the host to resolve (from lifted artifacts or path-derived id). */
|
|
201
|
+
export declare function artifactIdsForResolve(call: {
|
|
202
|
+
toolName?: string;
|
|
203
|
+
artifacts?: ReadonlyArray<{
|
|
204
|
+
id?: unknown;
|
|
205
|
+
}> | undefined;
|
|
206
|
+
arguments?: unknown;
|
|
207
|
+
}): string[];
|
|
208
|
+
/**
|
|
209
|
+
* RUNNER-side collection. Invokes the host resolver (async I/O). Never call from pure assessFreshness.
|
|
210
|
+
* - no resolver → NOT_CONFIGURED (did not try)
|
|
211
|
+
* - resolver throws → DEGRADED (opted in, failed)
|
|
212
|
+
* - resolver returns empty/non-string for all ids → DEGRADED
|
|
213
|
+
* - otherwise ACTIVE with priorResolved map
|
|
214
|
+
*/
|
|
215
|
+
export declare function collectFreshnessCallContext(input: {
|
|
216
|
+
call: {
|
|
217
|
+
toolName: string;
|
|
218
|
+
artifacts?: ReadonlyArray<{
|
|
219
|
+
id?: unknown;
|
|
220
|
+
before?: unknown;
|
|
221
|
+
}> | undefined;
|
|
222
|
+
arguments?: unknown;
|
|
223
|
+
};
|
|
224
|
+
resolvePriorContent?: PriorContentResolver | null;
|
|
225
|
+
}): Promise<FreshnessCallContext>;
|
|
226
|
+
/**
|
|
227
|
+
* Build the per-call basis and optional enforce block reason from context + preflight artifacts.
|
|
228
|
+
* Pure once priorResolved is a value (no I/O).
|
|
229
|
+
*/
|
|
230
|
+
export declare function buildFreshnessBasis(input: {
|
|
231
|
+
writeStyle: boolean;
|
|
232
|
+
requireFreshness: boolean;
|
|
233
|
+
ctx: FreshnessCallContext;
|
|
234
|
+
/** Preflight-bound before per artifact id (from call.artifacts after detect/bind). */
|
|
235
|
+
preflightBeforeById?: Record<string, string>;
|
|
236
|
+
allowStaleContext?: boolean;
|
|
237
|
+
preflightTreeHash?: string | null;
|
|
238
|
+
resolvedTreeHashNow?: string | null;
|
|
239
|
+
}): {
|
|
240
|
+
basis: FreshnessBasis;
|
|
241
|
+
/** If set, enforced execution must not proceed (permission fail-closed). */
|
|
242
|
+
blockCause?: 'FRESHNESS_REQUIRED' | 'FRESHNESS_FAILED';
|
|
243
|
+
};
|
|
244
|
+
//# sourceMappingURL=freshness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freshness.d.ts","sourceRoot":"","sources":["../../src/freshness.ts"],"names":[],"mappings":"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"}
|