@coderifts/agent-guard 3.0.1 → 4.1.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 (92) hide show
  1. package/README.md +46 -1
  2. package/dist/cjs/artifact-resolver.d.ts +8 -0
  3. package/dist/cjs/artifact-resolver.d.ts.map +1 -1
  4. package/dist/cjs/artifact-resolver.js +12 -1
  5. package/dist/cjs/artifact-resolver.js.map +1 -1
  6. package/dist/cjs/conditional-write.d.ts +92 -0
  7. package/dist/cjs/conditional-write.d.ts.map +1 -0
  8. package/dist/cjs/conditional-write.js +96 -0
  9. package/dist/cjs/conditional-write.js.map +1 -0
  10. package/dist/cjs/deploy-bind.d.ts +123 -0
  11. package/dist/cjs/deploy-bind.d.ts.map +1 -0
  12. package/dist/cjs/deploy-bind.js +112 -0
  13. package/dist/cjs/deploy-bind.js.map +1 -0
  14. package/dist/cjs/enforcement-gate.d.ts +13 -4
  15. package/dist/cjs/enforcement-gate.d.ts.map +1 -1
  16. package/dist/cjs/enforcement-gate.js +32 -7
  17. package/dist/cjs/enforcement-gate.js.map +1 -1
  18. package/dist/cjs/execution-proof.d.ts +145 -0
  19. package/dist/cjs/execution-proof.d.ts.map +1 -0
  20. package/dist/cjs/execution-proof.js +168 -0
  21. package/dist/cjs/execution-proof.js.map +1 -0
  22. package/dist/cjs/freshness.d.ts +244 -0
  23. package/dist/cjs/freshness.d.ts.map +1 -0
  24. package/dist/cjs/freshness.js +395 -0
  25. package/dist/cjs/freshness.js.map +1 -0
  26. package/dist/cjs/guard.d.ts +8 -1
  27. package/dist/cjs/guard.d.ts.map +1 -1
  28. package/dist/cjs/guard.js +181 -38
  29. package/dist/cjs/guard.js.map +1 -1
  30. package/dist/cjs/index.d.ts +12 -4
  31. package/dist/cjs/index.d.ts.map +1 -1
  32. package/dist/cjs/index.js +34 -3
  33. package/dist/cjs/index.js.map +1 -1
  34. package/dist/cjs/read-decision.d.ts +47 -0
  35. package/dist/cjs/read-decision.d.ts.map +1 -0
  36. package/dist/cjs/read-decision.js +161 -0
  37. package/dist/cjs/read-decision.js.map +1 -0
  38. package/dist/cjs/tool-registry.d.ts.map +1 -1
  39. package/dist/cjs/tool-registry.js +12 -1
  40. package/dist/cjs/tool-registry.js.map +1 -1
  41. package/dist/cjs/types.d.ts +47 -1
  42. package/dist/cjs/types.d.ts.map +1 -1
  43. package/dist/cjs/with-coderifts.d.ts +76 -8
  44. package/dist/cjs/with-coderifts.d.ts.map +1 -1
  45. package/dist/cjs/with-coderifts.js +185 -14
  46. package/dist/cjs/with-coderifts.js.map +1 -1
  47. package/dist/esm/artifact-resolver.d.ts +8 -0
  48. package/dist/esm/artifact-resolver.d.ts.map +1 -1
  49. package/dist/esm/artifact-resolver.js +11 -1
  50. package/dist/esm/artifact-resolver.js.map +1 -1
  51. package/dist/esm/conditional-write.d.ts +92 -0
  52. package/dist/esm/conditional-write.d.ts.map +1 -0
  53. package/dist/esm/conditional-write.js +91 -0
  54. package/dist/esm/conditional-write.js.map +1 -0
  55. package/dist/esm/deploy-bind.d.ts +123 -0
  56. package/dist/esm/deploy-bind.d.ts.map +1 -0
  57. package/dist/esm/deploy-bind.js +108 -0
  58. package/dist/esm/deploy-bind.js.map +1 -0
  59. package/dist/esm/enforcement-gate.d.ts +13 -4
  60. package/dist/esm/enforcement-gate.d.ts.map +1 -1
  61. package/dist/esm/enforcement-gate.js +32 -7
  62. package/dist/esm/enforcement-gate.js.map +1 -1
  63. package/dist/esm/execution-proof.d.ts +145 -0
  64. package/dist/esm/execution-proof.d.ts.map +1 -0
  65. package/dist/esm/execution-proof.js +162 -0
  66. package/dist/esm/execution-proof.js.map +1 -0
  67. package/dist/esm/freshness.d.ts +244 -0
  68. package/dist/esm/freshness.d.ts.map +1 -0
  69. package/dist/esm/freshness.js +384 -0
  70. package/dist/esm/freshness.js.map +1 -0
  71. package/dist/esm/guard.d.ts +8 -1
  72. package/dist/esm/guard.d.ts.map +1 -1
  73. package/dist/esm/guard.js +180 -37
  74. package/dist/esm/guard.js.map +1 -1
  75. package/dist/esm/index.d.ts +12 -4
  76. package/dist/esm/index.d.ts.map +1 -1
  77. package/dist/esm/index.js +12 -2
  78. package/dist/esm/index.js.map +1 -1
  79. package/dist/esm/read-decision.d.ts +47 -0
  80. package/dist/esm/read-decision.d.ts.map +1 -0
  81. package/dist/esm/read-decision.js +153 -0
  82. package/dist/esm/read-decision.js.map +1 -0
  83. package/dist/esm/tool-registry.d.ts.map +1 -1
  84. package/dist/esm/tool-registry.js +12 -1
  85. package/dist/esm/tool-registry.js.map +1 -1
  86. package/dist/esm/types.d.ts +47 -1
  87. package/dist/esm/types.d.ts.map +1 -1
  88. package/dist/esm/with-coderifts.d.ts +76 -8
  89. package/dist/esm/with-coderifts.d.ts.map +1 -1
  90. package/dist/esm/with-coderifts.js +185 -14
  91. package/dist/esm/with-coderifts.js.map +1 -1
  92. package/package.json +1 -1
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Conditional-execution surface (reporting only — this package never writes).
3
+ *
4
+ * ACTIVE + FRESH only proves content matched at measurement time. A host that resolves
5
+ * then writes unconditionally still races; the conditional write itself is the host's job.
6
+ * We define the surface, demand it by policy, and report whether the host said it happened.
7
+ *
8
+ * Host contract (executeIfUnchanged):
9
+ * The host SHOULD perform writes via executeIfUnchanged(write, expected_token) (or
10
+ * equivalent: only apply the mutation if the resource still holds expected_token).
11
+ * After the attempt, the host reports on the call context:
12
+ * - conditional_write: true — write was conditioned on a version token
13
+ * - conditional_write: false — write was unconditional (host admits it)
14
+ * - conditional_write: 'not_reported' — host did not report (DEFAULT; absence ≠ false)
15
+ * When true, conditioned_on_token is the opaque token the host conditioned on.
16
+ * Tokens are host-defined (git blob sha, etag, mtime-hash, …). This package never
17
+ * interprets them — only carries them and compares for equality (===).
18
+ */
19
+ /** Host-defined opaque version token. Compared only by string equality. */
20
+ export type VersionToken = string;
21
+ /**
22
+ * Host resolution surface: content plus an opaque version token.
23
+ * Returned by host resolvers that support conditional execution.
24
+ */
25
+ export type VersionedContent = {
26
+ content: string;
27
+ version_token: VersionToken;
28
+ };
29
+ /**
30
+ * Host report of whether the write was conditioned on a version token.
31
+ * `not_reported` is the default — absence of a report is not false
32
+ * (absent ≠ 0 ≠ null ≠ unknown).
33
+ */
34
+ export type ConditionalWriteReport = true | false | 'not_reported';
35
+ /**
36
+ * Per-call forensic basis for conditional write (on every GuardOutcome).
37
+ * Survives replay unchanged when recorded.
38
+ */
39
+ export type ConditionalWriteBasis = {
40
+ conditional_write: ConditionalWriteReport;
41
+ /**
42
+ * When conditional_write === true, the token the host says it conditioned on.
43
+ * Omitted when not_reported / false / not supplied.
44
+ */
45
+ conditioned_on_token?: VersionToken | null;
46
+ /** Config requireConditionalWrite for this call (policy). */
47
+ require_conditional_write: boolean;
48
+ /** Whether this call was treated as write-style. */
49
+ write_style: boolean;
50
+ };
51
+ /**
52
+ * Values the RUNNER collected / host reported before the pure guard path.
53
+ * Default when omitted: conditional_write 'not_reported'.
54
+ */
55
+ export type ConditionalWriteCallContext = {
56
+ conditional_write?: ConditionalWriteReport;
57
+ conditioned_on_token?: VersionToken | null;
58
+ /** Optional versioned content for token carry (equality only). */
59
+ versioned_content?: VersionedContent | null;
60
+ };
61
+ /** Equality compare only — never semantic interpretation of the token. */
62
+ export declare function tokensEqual(a: VersionToken | null | undefined, b: VersionToken | null | undefined): boolean;
63
+ /**
64
+ * Build per-call conditional-write basis + optional enforce block.
65
+ * Pure once the host report is a value (no I/O).
66
+ *
67
+ * Policy (mirrors requireFreshness Decision-1): when requireConditionalWrite is true
68
+ * and the call is write-style, conditional_write must be true for enforced execution
69
+ * to be eligible. false and not_reported both refuse (distinct from "host said false"
70
+ * vs "host silent" only on the basis field — both block under policy).
71
+ */
72
+ export declare function buildConditionalWriteBasis(input: {
73
+ writeStyle: boolean;
74
+ requireConditionalWrite: boolean;
75
+ ctx?: ConditionalWriteCallContext | null;
76
+ }): {
77
+ basis: ConditionalWriteBasis;
78
+ /** If set, enforced execution must not proceed. */
79
+ blockCause?: 'CONDITIONAL_WRITE_REQUIRED';
80
+ };
81
+ /** Residual name when policy requires conditional write but host did not report true. */
82
+ export declare const RESIDUAL_UNCONDITIONAL_WRITE = "composition_unconditional_write_under_policy";
83
+ /**
84
+ * Coverage residual when requireConditionalWrite is on and the host report is not true.
85
+ * inescapable_runtime must stay false — we report what the host told us, never claim compliance.
86
+ */
87
+ export declare function conditionalWriteResidual(input: {
88
+ requireConditionalWrite: boolean;
89
+ writeStyle: boolean;
90
+ conditionalWrite: ConditionalWriteReport;
91
+ }): string | null;
92
+ //# sourceMappingURL=conditional-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional-write.d.ts","sourceRoot":"","sources":["../../src/conditional-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAElC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,GAAG,KAAK,GAAG,cAAc,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,iBAAiB,EAAE,sBAAsB,CAAC;IAC1C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3C,6DAA6D;IAC7D,yBAAyB,EAAE,OAAO,CAAC;IACnC,oDAAoD;IACpD,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAC3C,oBAAoB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3C,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC7C,CAAC;AAEF,0EAA0E;AAC1E,wBAAgB,WAAW,CACzB,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,EAClC,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GACjC,OAAO,CAIT;AASD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,UAAU,EAAE,OAAO,CAAC;IACpB,uBAAuB,EAAE,OAAO,CAAC;IACjC,GAAG,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;CAC1C,GAAG;IACF,KAAK,EAAE,qBAAqB,CAAC;IAC7B,mDAAmD;IACnD,UAAU,CAAC,EAAE,4BAA4B,CAAC;CAC3C,CAgCA;AAED,yFAAyF;AACzF,eAAO,MAAM,4BAA4B,iDAAiD,CAAC;AAE3F;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,uBAAuB,EAAE,OAAO,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,sBAAsB,CAAC;CAC1C,GAAG,MAAM,GAAG,IAAI,CAKhB"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Conditional-execution surface (reporting only — this package never writes).
3
+ *
4
+ * ACTIVE + FRESH only proves content matched at measurement time. A host that resolves
5
+ * then writes unconditionally still races; the conditional write itself is the host's job.
6
+ * We define the surface, demand it by policy, and report whether the host said it happened.
7
+ *
8
+ * Host contract (executeIfUnchanged):
9
+ * The host SHOULD perform writes via executeIfUnchanged(write, expected_token) (or
10
+ * equivalent: only apply the mutation if the resource still holds expected_token).
11
+ * After the attempt, the host reports on the call context:
12
+ * - conditional_write: true — write was conditioned on a version token
13
+ * - conditional_write: false — write was unconditional (host admits it)
14
+ * - conditional_write: 'not_reported' — host did not report (DEFAULT; absence ≠ false)
15
+ * When true, conditioned_on_token is the opaque token the host conditioned on.
16
+ * Tokens are host-defined (git blob sha, etag, mtime-hash, …). This package never
17
+ * interprets them — only carries them and compares for equality (===).
18
+ */
19
+ 'use strict';
20
+ /** Equality compare only — never semantic interpretation of the token. */
21
+ export function tokensEqual(a, b) {
22
+ if (a == null || b == null)
23
+ return false;
24
+ if (typeof a !== 'string' || typeof b !== 'string')
25
+ return false;
26
+ return a === b;
27
+ }
28
+ function normalizeReport(raw) {
29
+ if (raw === true)
30
+ return true;
31
+ if (raw === false)
32
+ return false;
33
+ if (raw === 'not_reported')
34
+ return 'not_reported';
35
+ return 'not_reported';
36
+ }
37
+ /**
38
+ * Build per-call conditional-write basis + optional enforce block.
39
+ * Pure once the host report is a value (no I/O).
40
+ *
41
+ * Policy (mirrors requireFreshness Decision-1): when requireConditionalWrite is true
42
+ * and the call is write-style, conditional_write must be true for enforced execution
43
+ * to be eligible. false and not_reported both refuse (distinct from "host said false"
44
+ * vs "host silent" only on the basis field — both block under policy).
45
+ */
46
+ export function buildConditionalWriteBasis(input) {
47
+ const require_conditional_write = input.requireConditionalWrite === true;
48
+ const write_style = input.writeStyle === true;
49
+ const ctx = input.ctx && typeof input.ctx === 'object' ? input.ctx : {};
50
+ const conditional_write = normalizeReport(ctx.conditional_write);
51
+ const basis = {
52
+ conditional_write,
53
+ require_conditional_write,
54
+ write_style,
55
+ };
56
+ // Token carry: prefer explicit conditioned_on_token, else versioned_content.version_token.
57
+ if (conditional_write === true) {
58
+ if (typeof ctx.conditioned_on_token === 'string') {
59
+ basis.conditioned_on_token = ctx.conditioned_on_token;
60
+ }
61
+ else if (ctx.versioned_content
62
+ && typeof ctx.versioned_content === 'object'
63
+ && typeof ctx.versioned_content.version_token === 'string') {
64
+ basis.conditioned_on_token = ctx.versioned_content.version_token;
65
+ }
66
+ else if (ctx.conditioned_on_token === null) {
67
+ basis.conditioned_on_token = null;
68
+ }
69
+ }
70
+ // Policy on write: only conditional_write:true is eligible for enforced:true.
71
+ if (write_style && require_conditional_write && conditional_write !== true) {
72
+ return { basis, blockCause: 'CONDITIONAL_WRITE_REQUIRED' };
73
+ }
74
+ return { basis };
75
+ }
76
+ /** Residual name when policy requires conditional write but host did not report true. */
77
+ export const RESIDUAL_UNCONDITIONAL_WRITE = 'composition_unconditional_write_under_policy';
78
+ /**
79
+ * Coverage residual when requireConditionalWrite is on and the host report is not true.
80
+ * inescapable_runtime must stay false — we report what the host told us, never claim compliance.
81
+ */
82
+ export function conditionalWriteResidual(input) {
83
+ if (input.requireConditionalWrite !== true)
84
+ return null;
85
+ if (input.writeStyle !== true)
86
+ return null;
87
+ if (input.conditionalWrite === true)
88
+ return null;
89
+ return RESIDUAL_UNCONDITIONAL_WRITE;
90
+ }
91
+ //# sourceMappingURL=conditional-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional-write.js","sourceRoot":"","sources":["../../src/conditional-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,YAAY,CAAC;AAiDb,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CACzB,CAAkC,EAClC,CAAkC;IAElC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED,SAAS,eAAe,CAAC,GAAY;IACnC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,GAAG,KAAK,cAAc;QAAE,OAAO,cAAc,CAAC;IAClD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAI1C;IAKC,MAAM,yBAAyB,GAAG,KAAK,CAAC,uBAAuB,KAAK,IAAI,CAAC;IACzE,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC9C,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,iBAAiB,GAAG,eAAe,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEjE,MAAM,KAAK,GAA0B;QACnC,iBAAiB;QACjB,yBAAyB;QACzB,WAAW;KACZ,CAAC;IAEF,2FAA2F;IAC3F,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,IAAI,OAAO,GAAG,CAAC,oBAAoB,KAAK,QAAQ,EAAE,CAAC;YACjD,KAAK,CAAC,oBAAoB,GAAG,GAAG,CAAC,oBAAoB,CAAC;QACxD,CAAC;aAAM,IACL,GAAG,CAAC,iBAAiB;eAClB,OAAO,GAAG,CAAC,iBAAiB,KAAK,QAAQ;eACzC,OAAO,GAAG,CAAC,iBAAiB,CAAC,aAAa,KAAK,QAAQ,EAC1D,CAAC;YACD,KAAK,CAAC,oBAAoB,GAAG,GAAG,CAAC,iBAAiB,CAAC,aAAa,CAAC;QACnE,CAAC;aAAM,IAAI,GAAG,CAAC,oBAAoB,KAAK,IAAI,EAAE,CAAC;YAC7C,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACpC,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,IAAI,WAAW,IAAI,yBAAyB,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC3E,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,4BAA4B,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,MAAM,4BAA4B,GAAG,8CAA8C,CAAC;AAE3F;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAIxC;IACC,IAAI,KAAK,CAAC,uBAAuB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,KAAK,CAAC,gBAAgB,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,4BAA4B,CAAC;AACtC,CAAC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * bindDeploy — pure deploy-TIME composition over deployGate (#8).
3
+ *
4
+ * Why this exists: deployGate is the pure decision; nothing in this package used to
5
+ * invoke it at the moment of deploying. The merge gate has the same shape
6
+ * (gateDecision is pure; GitHub enforces via required checks the package does not
7
+ * control). Deploy generalises that pattern with two differences:
8
+ * 1. There is no pull request / required status check to hang on — the host must
9
+ * call this from the CD step itself.
10
+ * 2. The environment name is a HOST ASSERTION. The receipt's bound_environment is
11
+ * signed evidence; the deploy target's environment string is not verified by us.
12
+ * A host can claim "staging" while deploying to production. The output says so.
13
+ *
14
+ * This module performs NO I/O, does NOT re-verify receipts, and does NOT act on a
15
+ * pipeline. pipeline_action is always 'not_observed'. inescapable_deploy still comes
16
+ * only from deployGate (ENFORCING ∧ ¬bypass) — never flipped here.
17
+ *
18
+ * External note: coderifts-app CLI `deploy-gate` historically inlined a similar bind
19
+ * (deployBind). That is a consumer; this is the package-local pure entry hosts should
20
+ * call so the decision logic has a first-class caller in-repo.
21
+ */
22
+ import { type DeployEnforcementState, type DeployGateDecision, type DeployGateReason, type DeployReceiptView, type GateStatusState } from './deploy-gate.js';
23
+ /** Reasons a fresh re-preflight for this { env, artifact } can repair. */
24
+ declare const REPAIRABLE: ReadonlySet<DeployGateReason>;
25
+ /**
26
+ * Environment as supplied by the host at deploy time.
27
+ *
28
+ * provenance is ALWAYS 'host_asserted'. The package cannot observe the real CD
29
+ * target; treating this as verified would be the honesty failure this project keeps
30
+ * finding. Signed evidence lives on the receipt (bound_environment), not here.
31
+ */
32
+ export type HostAssertedEnvironment = {
33
+ name: string;
34
+ /** Fixed literal — never 'verified'. */
35
+ provenance: 'host_asserted';
36
+ };
37
+ export type BindDeployInput = {
38
+ /**
39
+ * Host-asserted deploy environment. Pass a string (wrapped as host_asserted) or
40
+ * an explicit HostAssertedEnvironment. Never reported as package-verified.
41
+ */
42
+ environment: string | HostAssertedEnvironment;
43
+ /** Artifact / digest being deployed (host-supplied identity for this moment). */
44
+ artifact_id: string;
45
+ service?: string;
46
+ pipeline_run_id?: string;
47
+ /**
48
+ * Finished receipt VIEW (fields already produced + lifecycle-evaluated elsewhere).
49
+ * This function does not verify signatures or re-issue receipts. null → no_receipt.
50
+ */
51
+ receipt: DeployReceiptView | null;
52
+ /**
53
+ * Host-observed pipeline enforcement (CD config / step policy). Same role as
54
+ * ProtectionState for merge — an input, not a package discovery.
55
+ */
56
+ pipeline_enforcement: DeployEnforcementState;
57
+ /** Operation the receipt must match (default 'deploy'). */
58
+ operation?: string;
59
+ expected_fingerprint?: string;
60
+ expected_body_hash?: string;
61
+ allowPending?: boolean;
62
+ allowWarnDeploy?: boolean;
63
+ allowPrefixCompare?: boolean;
64
+ };
65
+ /**
66
+ * Result of a deploy-time bind. Distinguish carefully:
67
+ * - gate / decision_allows_deploy — pure decision from deployGate
68
+ * - pipeline_action — always 'not_observed' (we never block or run a deploy)
69
+ * - environment.provenance — always 'host_asserted' (we never verified the target)
70
+ */
71
+ export type BindDeployResult = {
72
+ /** Full pure gate decision (includes inescapable_deploy, residual, detail). */
73
+ gate: DeployGateDecision;
74
+ /**
75
+ * Whether the pure decision allows deploy. Naming avoids "deploy was blocked"
76
+ * (that would claim pipeline enforcement). Same bit as gate.deploy_allowed.
77
+ */
78
+ decision_allows_deploy: boolean;
79
+ /** Mirror of gate.state for check-run / step status UIs. */
80
+ deploy_check_status: GateStatusState;
81
+ /** Gate reason code (or no_receipt when receipt was null). */
82
+ reason: DeployGateReason;
83
+ /** Whether re-preflighting this target can repair a deny. */
84
+ must_re_preflight: boolean;
85
+ /**
86
+ * Environment as accepted into the gate. provenance is always host_asserted —
87
+ * never verified, never measured by this package.
88
+ */
89
+ environment: HostAssertedEnvironment;
90
+ artifact_id: string;
91
+ /**
92
+ * Always 'not_observed'. The package does not run, block, or skip a pipeline
93
+ * step. Whether the host CD job exits non-zero on decision_allows_deploy:false
94
+ * is entirely the pipeline's business.
95
+ */
96
+ pipeline_action: 'not_observed';
97
+ /**
98
+ * Convenience: inescapable_deploy from the gate only (never a host flag).
99
+ * True only when pipeline_enforcement is ENFORCING and bypass_possible is false
100
+ * AND the gate would allow — same honesty as deployGate.
101
+ */
102
+ inescapable_deploy: boolean;
103
+ };
104
+ /**
105
+ * Pure deploy-time entry: bind host claims + finished receipt view into deployGate.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * const r = bindDeploy({
110
+ * environment: { name: 'production', provenance: 'host_asserted' },
111
+ * artifact_id: digest,
112
+ * receipt: receiptView,
113
+ * pipeline_enforcement: { enforcement: 'ENFORCING', bypass_possible: false },
114
+ * });
115
+ * // r.decision_allows_deploy — decision only
116
+ * // r.pipeline_action === 'not_observed' — we did not enforce
117
+ * // r.environment.provenance === 'host_asserted' — we did not verify the target name
118
+ * if (!r.decision_allows_deploy) process.exit(1); // host pipeline chooses to honour
119
+ * ```
120
+ */
121
+ export declare function bindDeploy(input: BindDeployInput): BindDeployResult;
122
+ export { REPAIRABLE as DEPLOY_REPAIRABLE_REASONS };
123
+ //# sourceMappingURL=deploy-bind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-bind.d.ts","sourceRoot":"","sources":["../../src/deploy-bind.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAE1B,0EAA0E;AAC1E,QAAA,MAAM,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAS5C,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,UAAU,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,WAAW,EAAE,MAAM,GAAG,uBAAuB,CAAC;IAC9C,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,oBAAoB,EAAE,sBAAsB,CAAC;IAC7C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,+EAA+E;IAC/E,IAAI,EAAE,kBAAkB,CAAC;IACzB;;;OAGG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAChC,4DAA4D;IAC5D,mBAAmB,EAAE,eAAe,CAAC;IACrC,8DAA8D;IAC9D,MAAM,EAAE,gBAAgB,CAAC;IACzB,6DAA6D;IAC7D,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,WAAW,EAAE,uBAAuB,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,eAAe,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAWF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAmDnE;AAED,OAAO,EAAE,UAAU,IAAI,yBAAyB,EAAE,CAAC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * bindDeploy — pure deploy-TIME composition over deployGate (#8).
3
+ *
4
+ * Why this exists: deployGate is the pure decision; nothing in this package used to
5
+ * invoke it at the moment of deploying. The merge gate has the same shape
6
+ * (gateDecision is pure; GitHub enforces via required checks the package does not
7
+ * control). Deploy generalises that pattern with two differences:
8
+ * 1. There is no pull request / required status check to hang on — the host must
9
+ * call this from the CD step itself.
10
+ * 2. The environment name is a HOST ASSERTION. The receipt's bound_environment is
11
+ * signed evidence; the deploy target's environment string is not verified by us.
12
+ * A host can claim "staging" while deploying to production. The output says so.
13
+ *
14
+ * This module performs NO I/O, does NOT re-verify receipts, and does NOT act on a
15
+ * pipeline. pipeline_action is always 'not_observed'. inescapable_deploy still comes
16
+ * only from deployGate (ENFORCING ∧ ¬bypass) — never flipped here.
17
+ *
18
+ * External note: coderifts-app CLI `deploy-gate` historically inlined a similar bind
19
+ * (deployBind). That is a consumer; this is the package-local pure entry hosts should
20
+ * call so the decision logic has a first-class caller in-repo.
21
+ */
22
+ import { deployGate, } from './deploy-gate.js';
23
+ /** Reasons a fresh re-preflight for this { env, artifact } can repair. */
24
+ const REPAIRABLE = new Set([
25
+ 'env_mismatch',
26
+ 'stale_artifact',
27
+ 'operation_mismatch',
28
+ 'receipt_not_authorized',
29
+ 'fingerprint_mismatch',
30
+ 'body_hash_mismatch',
31
+ 'no_receipt',
32
+ 'inputs_incomplete',
33
+ ]);
34
+ function asHostAssertedEnvironment(env) {
35
+ if (typeof env === 'string') {
36
+ return { name: env, provenance: 'host_asserted' };
37
+ }
38
+ const name = env && typeof env.name === 'string' ? env.name : '';
39
+ // Force provenance — a host cannot pass provenance: 'verified' through this API.
40
+ return { name, provenance: 'host_asserted' };
41
+ }
42
+ /**
43
+ * Pure deploy-time entry: bind host claims + finished receipt view into deployGate.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const r = bindDeploy({
48
+ * environment: { name: 'production', provenance: 'host_asserted' },
49
+ * artifact_id: digest,
50
+ * receipt: receiptView,
51
+ * pipeline_enforcement: { enforcement: 'ENFORCING', bypass_possible: false },
52
+ * });
53
+ * // r.decision_allows_deploy — decision only
54
+ * // r.pipeline_action === 'not_observed' — we did not enforce
55
+ * // r.environment.provenance === 'host_asserted' — we did not verify the target name
56
+ * if (!r.decision_allows_deploy) process.exit(1); // host pipeline chooses to honour
57
+ * ```
58
+ */
59
+ export function bindDeploy(input) {
60
+ const environment = asHostAssertedEnvironment(input.environment);
61
+ const artifact_id = input.artifact_id == null ? '' : String(input.artifact_id);
62
+ const operation = input.operation ?? 'deploy';
63
+ const deployTarget = {
64
+ environment: environment.name,
65
+ artifact_id,
66
+ ...(input.service != null ? { service: input.service } : {}),
67
+ ...(input.pipeline_run_id != null ? { pipeline_run_id: input.pipeline_run_id } : {}),
68
+ };
69
+ const requiredContext = {
70
+ operation,
71
+ enforcement: input.pipeline_enforcement || { enforcement: 'UNKNOWN', bypass_possible: true },
72
+ ...(input.service != null ? { service: input.service } : {}),
73
+ ...(input.expected_fingerprint != null
74
+ ? { expected_fingerprint: input.expected_fingerprint }
75
+ : {}),
76
+ ...(input.expected_body_hash != null
77
+ ? { expected_body_hash: input.expected_body_hash }
78
+ : {}),
79
+ ...(input.allowPending != null ? { allowPending: input.allowPending } : {}),
80
+ ...(input.allowWarnDeploy != null ? { allowWarnDeploy: input.allowWarnDeploy } : {}),
81
+ ...(input.allowPrefixCompare != null
82
+ ? { allowPrefixCompare: input.allowPrefixCompare }
83
+ : {}),
84
+ };
85
+ const gate = deployGate({
86
+ deployTarget,
87
+ receipt: input.receipt,
88
+ requiredContext,
89
+ ...(input.allowPending != null ? { allowPending: input.allowPending } : {}),
90
+ ...(input.allowWarnDeploy != null ? { allowWarnDeploy: input.allowWarnDeploy } : {}),
91
+ ...(input.allowPrefixCompare != null
92
+ ? { allowPrefixCompare: input.allowPrefixCompare }
93
+ : {}),
94
+ });
95
+ return {
96
+ gate,
97
+ decision_allows_deploy: gate.deploy_allowed === true,
98
+ deploy_check_status: gate.state,
99
+ reason: gate.reason,
100
+ must_re_preflight: REPAIRABLE.has(gate.reason),
101
+ environment, // always provenance: 'host_asserted'
102
+ artifact_id,
103
+ pipeline_action: 'not_observed',
104
+ inescapable_deploy: gate.inescapable_deploy === true,
105
+ };
106
+ }
107
+ export { REPAIRABLE as DEPLOY_REPAIRABLE_REASONS };
108
+ //# sourceMappingURL=deploy-bind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-bind.js","sourceRoot":"","sources":["../../src/deploy-bind.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,14 @@
1
1
  /**
2
2
  * Client-side authorization gate (P0-b/c) — mirrors the server §106 (binding), §111 (fail-closed on
3
- * degraded) and §115 (safe_for_agent) in the guard, so the client never executes off a raw
4
- * execution_action an attacker/proxy can flip. All checks are LOCAL and fail-closed.
3
+ * degraded) and §115 (safe_for_agent) in the guard. All checks are LOCAL and fail-closed.
4
+ *
5
+ * Threat model (bounded): a raw execution_action is not trusted alone when the response has NO
6
+ * receipt — without a signed decision_body_hash, a proxy or intermediary can flip fields. When a
7
+ * receipt IS present, decision_body_hash covers the RFC 8785-canonical envelope (minus receipt and
8
+ * the hash field itself) and the receipt signature covers that hash, so execution_action cannot be
9
+ * flipped without the recomputed hash diverging or a forged signature. The gate still reconciles
10
+ * decision↔action locally (stricter wins), fails closed on a PRESENT-but-unrecognised action
11
+ * (version skew — not a missing-action fallback), and never treats an unknown value as permission.
5
12
  *
6
13
  * Composes with the P0-a receipt binding (receipt-binding.ts). This module reconciles the DECISION
7
14
  * itself; receipt-binding authenticates the envelope the decision rides on.
@@ -25,6 +32,8 @@ export type GateResult = {
25
32
  };
26
33
  /**
27
34
  * Reconcile an envelope's decision fail-closed. Order:
35
+ * 0. execution_action PRESENT but not in closed set → EXECUTION_ACTION_UNRECOGNISED
36
+ * (version skew; distinct from DECISION_INCONSISTENT — reconciliation is impossible)
28
37
  * 1. decision present + valid enum (CE-EP-04) → DECISION_INCONSISTENT
29
38
  * 2. effective decision = STRICTEST(envelope.decision, action-implied, top-level decision/action)
30
39
  * (CE-EP-01, CE-CC-01) — BLOCK/REQUIRE_APPROVAL → clean block (positive control CE-EP-02 kept)
@@ -34,9 +43,9 @@ export type GateResult = {
34
43
  *
35
44
  * @param response the raw preflight response (for the top-level decision/action, CE-CC-01)
36
45
  * @param envelope the decision_result envelope
37
- * @param executionAction rd.executionAction from readDecision
46
+ * @param executionAction rd.executionAction from readDecision (closed Action, or raw string if unrecognised)
38
47
  * @param sentArtifacts the artifacts the guard sent to preflight (for the digest bind)
39
48
  */
40
- export declare function evaluateEnvelope(response: unknown, envelope: Record<string, unknown>, executionAction: Action, sentArtifacts: Artifact[]): GateResult;
49
+ export declare function evaluateEnvelope(response: unknown, envelope: Record<string, unknown>, executionAction: Action | string, sentArtifacts: Artifact[]): GateResult;
41
50
  export {};
42
51
  //# sourceMappingURL=enforcement-gate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"enforcement-gate.d.ts","sourceRoot":"","sources":["../../src/enforcement-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3D,KAAK,MAAM,GAAG,UAAU,GAAG,0BAA0B,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAoBpF,wGAAwG;AACxG,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAMnE;AAED,6FAA6F;AAC7F,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAKtE;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAC/C;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,OAAO,GAAG,kBAAkB,CAAA;CAAE,GACnE;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,QAAQ,EAAE,GACxB,UAAU,CAkDZ"}
1
+ {"version":3,"file":"enforcement-gate.d.ts","sourceRoot":"","sources":["../../src/enforcement-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3D,KAAK,MAAM,GAAG,UAAU,GAAG,0BAA0B,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAoBpF,wGAAwG;AACxG,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAMnE;AAED,6FAA6F;AAC7F,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAKtE;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,GAC/C;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,OAAO,GAAG,kBAAkB,CAAA;CAAE,GACnE;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,aAAa,EAAE,QAAQ,EAAE,GACxB,UAAU,CAoEZ"}
@@ -1,7 +1,14 @@
1
1
  /**
2
2
  * Client-side authorization gate (P0-b/c) — mirrors the server §106 (binding), §111 (fail-closed on
3
- * degraded) and §115 (safe_for_agent) in the guard, so the client never executes off a raw
4
- * execution_action an attacker/proxy can flip. All checks are LOCAL and fail-closed.
3
+ * degraded) and §115 (safe_for_agent) in the guard. All checks are LOCAL and fail-closed.
4
+ *
5
+ * Threat model (bounded): a raw execution_action is not trusted alone when the response has NO
6
+ * receipt — without a signed decision_body_hash, a proxy or intermediary can flip fields. When a
7
+ * receipt IS present, decision_body_hash covers the RFC 8785-canonical envelope (minus receipt and
8
+ * the hash field itself) and the receipt signature covers that hash, so execution_action cannot be
9
+ * flipped without the recomputed hash diverging or a forged signature. The gate still reconciles
10
+ * decision↔action locally (stricter wins), fails closed on a PRESENT-but-unrecognised action
11
+ * (version skew — not a missing-action fallback), and never treats an unknown value as permission.
5
12
  *
6
13
  * Composes with the P0-a receipt binding (receipt-binding.ts). This module reconciles the DECISION
7
14
  * itself; receipt-binding authenticates the envelope the decision rides on.
@@ -40,6 +47,8 @@ export function computeBundleFingerprint(artifacts) {
40
47
  }
41
48
  /**
42
49
  * Reconcile an envelope's decision fail-closed. Order:
50
+ * 0. execution_action PRESENT but not in closed set → EXECUTION_ACTION_UNRECOGNISED
51
+ * (version skew; distinct from DECISION_INCONSISTENT — reconciliation is impossible)
43
52
  * 1. decision present + valid enum (CE-EP-04) → DECISION_INCONSISTENT
44
53
  * 2. effective decision = STRICTEST(envelope.decision, action-implied, top-level decision/action)
45
54
  * (CE-EP-01, CE-CC-01) — BLOCK/REQUIRE_APPROVAL → clean block (positive control CE-EP-02 kept)
@@ -49,18 +58,34 @@ export function computeBundleFingerprint(artifacts) {
49
58
  *
50
59
  * @param response the raw preflight response (for the top-level decision/action, CE-CC-01)
51
60
  * @param envelope the decision_result envelope
52
- * @param executionAction rd.executionAction from readDecision
61
+ * @param executionAction rd.executionAction from readDecision (closed Action, or raw string if unrecognised)
53
62
  * @param sentArtifacts the artifacts the guard sent to preflight (for the digest bind)
54
63
  */
55
64
  export function evaluateEnvelope(response, envelope, executionAction, sentArtifacts) {
65
+ const top = (response && typeof response === 'object') ? response : {};
66
+ // 0. PRESENT-but-unrecognised action — before any decision map or reconciliation.
67
+ // Missing action is not handled here (readDecision maps legacy missing → closed Action).
68
+ const candidates = [executionAction, envelope.execution_action, top.execution_action];
69
+ for (const cand of candidates) {
70
+ if (cand === undefined || cand === null || cand === '')
71
+ continue; // missing — skip
72
+ if (!isAction(cand)) {
73
+ return {
74
+ verdict: 'fail-closed',
75
+ cause: 'EXECUTION_ACTION_UNRECOGNISED',
76
+ detail: `execution_action=${JSON.stringify(cand)} is present but not in the closed set`,
77
+ };
78
+ }
79
+ }
56
80
  // 1. decision required + valid enum.
57
81
  const dec = envelope.decision;
58
82
  if (!isDecision(dec)) {
59
83
  return { verdict: 'fail-closed', cause: 'DECISION_INCONSISTENT', detail: `decision=${JSON.stringify(dec)} is missing/invalid` };
60
84
  }
85
+ // Known closed action from here (step 0 rejected unknowns).
86
+ const action = executionAction;
61
87
  // 2. Strictest of every decision signal present (envelope, action-implied, top-level).
62
- const signals = [dec, ACTION_TO_DECISION[executionAction]];
63
- const top = (response && typeof response === 'object') ? response : {};
88
+ const signals = [dec, ACTION_TO_DECISION[action]];
64
89
  if (isDecision(top.decision))
65
90
  signals.push(top.decision);
66
91
  if (isAction(top.execution_action))
@@ -71,8 +96,8 @@ export function evaluateEnvelope(response, envelope, executionAction, sentArtifa
71
96
  return { verdict: 'block-strict', decision: effective };
72
97
  }
73
98
  // (effective is ALLOW or WARN — but ALSO require the envelope's own action to agree, else tamper.)
74
- if (DECISION_TO_ACTION[dec] !== executionAction) {
75
- return { verdict: 'fail-closed', cause: 'DECISION_INCONSISTENT', detail: `decision=${dec} ≠ execution_action=${executionAction}` };
99
+ if (DECISION_TO_ACTION[dec] !== action) {
100
+ return { verdict: 'fail-closed', cause: 'DECISION_INCONSISTENT', detail: `decision=${dec} ≠ execution_action=${action}` };
76
101
  }
77
102
  // 3. §115 — safe_for_agent=false is NEVER executable, regardless of action.
78
103
  if (envelope.safe_for_agent === false) {
@@ -1 +1 @@
1
- {"version":3,"file":"enforcement-gate.js","sourceRoot":"","sources":["../../src/enforcement-gate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"enforcement-gate.js","sourceRoot":"","sources":["../../src/enforcement-gate.ts"],"names":[],"mappings":"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"}