@gate-forge/core 0.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 (242) hide show
  1. package/LICENSE +202 -0
  2. package/dist/baselines/adoption.d.ts +76 -0
  3. package/dist/baselines/adoption.d.ts.map +1 -0
  4. package/dist/baselines/adoption.js +163 -0
  5. package/dist/baselines/adoption.js.map +1 -0
  6. package/dist/baselines/index.d.ts +102 -0
  7. package/dist/baselines/index.d.ts.map +1 -0
  8. package/dist/baselines/index.js +186 -0
  9. package/dist/baselines/index.js.map +1 -0
  10. package/dist/canonical-json.d.ts +51 -0
  11. package/dist/canonical-json.d.ts.map +1 -0
  12. package/dist/canonical-json.js +112 -0
  13. package/dist/canonical-json.js.map +1 -0
  14. package/dist/classifier/bind.d.ts +64 -0
  15. package/dist/classifier/bind.d.ts.map +1 -0
  16. package/dist/classifier/bind.js +188 -0
  17. package/dist/classifier/bind.js.map +1 -0
  18. package/dist/classifier/classify.d.ts +154 -0
  19. package/dist/classifier/classify.d.ts.map +1 -0
  20. package/dist/classifier/classify.js +1207 -0
  21. package/dist/classifier/classify.js.map +1 -0
  22. package/dist/classifier/glob.d.ts +48 -0
  23. package/dist/classifier/glob.d.ts.map +1 -0
  24. package/dist/classifier/glob.js +104 -0
  25. package/dist/classifier/glob.js.map +1 -0
  26. package/dist/classifier/index.d.ts +10 -0
  27. package/dist/classifier/index.d.ts.map +1 -0
  28. package/dist/classifier/index.js +21 -0
  29. package/dist/classifier/index.js.map +1 -0
  30. package/dist/classifier/schema.d.ts +150 -0
  31. package/dist/classifier/schema.d.ts.map +1 -0
  32. package/dist/classifier/schema.js +139 -0
  33. package/dist/classifier/schema.js.map +1 -0
  34. package/dist/config/index.d.ts +259 -0
  35. package/dist/config/index.d.ts.map +1 -0
  36. package/dist/config/index.js +523 -0
  37. package/dist/config/index.js.map +1 -0
  38. package/dist/fingerprints.d.ts +56 -0
  39. package/dist/fingerprints.d.ts.map +1 -0
  40. package/dist/fingerprints.js +59 -0
  41. package/dist/fingerprints.js.map +1 -0
  42. package/dist/graph/build.d.ts +16 -0
  43. package/dist/graph/build.d.ts.map +1 -0
  44. package/dist/graph/build.js +423 -0
  45. package/dist/graph/build.js.map +1 -0
  46. package/dist/graph/index.d.ts +12 -0
  47. package/dist/graph/index.d.ts.map +1 -0
  48. package/dist/graph/index.js +10 -0
  49. package/dist/graph/index.js.map +1 -0
  50. package/dist/graph/schema.d.ts +448 -0
  51. package/dist/graph/schema.d.ts.map +1 -0
  52. package/dist/graph/schema.js +237 -0
  53. package/dist/graph/schema.js.map +1 -0
  54. package/dist/graph/symbols.d.ts +129 -0
  55. package/dist/graph/symbols.d.ts.map +1 -0
  56. package/dist/graph/symbols.js +177 -0
  57. package/dist/graph/symbols.js.map +1 -0
  58. package/dist/graph/util.d.ts +40 -0
  59. package/dist/graph/util.d.ts.map +1 -0
  60. package/dist/graph/util.js +41 -0
  61. package/dist/graph/util.js.map +1 -0
  62. package/dist/index.d.ts +683 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +563 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/mapping/resolve.d.ts +177 -0
  67. package/dist/mapping/resolve.d.ts.map +1 -0
  68. package/dist/mapping/resolve.js +523 -0
  69. package/dist/mapping/resolve.js.map +1 -0
  70. package/dist/policy/coverage.d.ts +79 -0
  71. package/dist/policy/coverage.d.ts.map +1 -0
  72. package/dist/policy/coverage.js +119 -0
  73. package/dist/policy/coverage.js.map +1 -0
  74. package/dist/policy/evaluate.d.ts +275 -0
  75. package/dist/policy/evaluate.d.ts.map +1 -0
  76. package/dist/policy/evaluate.js +382 -0
  77. package/dist/policy/evaluate.js.map +1 -0
  78. package/dist/policy/index.d.ts +15 -0
  79. package/dist/policy/index.d.ts.map +1 -0
  80. package/dist/policy/index.js +14 -0
  81. package/dist/policy/index.js.map +1 -0
  82. package/dist/policy/trusted.d.ts +59 -0
  83. package/dist/policy/trusted.d.ts.map +1 -0
  84. package/dist/policy/trusted.js +96 -0
  85. package/dist/policy/trusted.js.map +1 -0
  86. package/dist/provenance.d.ts +170 -0
  87. package/dist/provenance.d.ts.map +1 -0
  88. package/dist/provenance.js +306 -0
  89. package/dist/provenance.js.map +1 -0
  90. package/dist/receipt/index.d.ts +74 -0
  91. package/dist/receipt/index.d.ts.map +1 -0
  92. package/dist/receipt/index.js +154 -0
  93. package/dist/receipt/index.js.map +1 -0
  94. package/dist/report/index.d.ts +100 -0
  95. package/dist/report/index.d.ts.map +1 -0
  96. package/dist/report/index.js +355 -0
  97. package/dist/report/index.js.map +1 -0
  98. package/dist/schemas/adoption.d.ts +40 -0
  99. package/dist/schemas/adoption.d.ts.map +1 -0
  100. package/dist/schemas/adoption.js +87 -0
  101. package/dist/schemas/adoption.js.map +1 -0
  102. package/dist/schemas/baseline.d.ts +19 -0
  103. package/dist/schemas/baseline.d.ts.map +1 -0
  104. package/dist/schemas/baseline.js +45 -0
  105. package/dist/schemas/baseline.js.map +1 -0
  106. package/dist/schemas/claim.d.ts +32 -0
  107. package/dist/schemas/claim.d.ts.map +1 -0
  108. package/dist/schemas/claim.js +34 -0
  109. package/dist/schemas/claim.js.map +1 -0
  110. package/dist/schemas/classification-policy.d.ts +84 -0
  111. package/dist/schemas/classification-policy.d.ts.map +1 -0
  112. package/dist/schemas/classification-policy.js +130 -0
  113. package/dist/schemas/classification-policy.js.map +1 -0
  114. package/dist/schemas/classification-signal.d.ts +125 -0
  115. package/dist/schemas/classification-signal.d.ts.map +1 -0
  116. package/dist/schemas/classification-signal.js +126 -0
  117. package/dist/schemas/classification-signal.js.map +1 -0
  118. package/dist/schemas/classification.d.ts +120 -0
  119. package/dist/schemas/classification.d.ts.map +1 -0
  120. package/dist/schemas/classification.js +154 -0
  121. package/dist/schemas/classification.js.map +1 -0
  122. package/dist/schemas/common.d.ts +73 -0
  123. package/dist/schemas/common.d.ts.map +1 -0
  124. package/dist/schemas/common.js +60 -0
  125. package/dist/schemas/common.js.map +1 -0
  126. package/dist/schemas/coverage-policy.d.ts +89 -0
  127. package/dist/schemas/coverage-policy.d.ts.map +1 -0
  128. package/dist/schemas/coverage-policy.js +81 -0
  129. package/dist/schemas/coverage-policy.js.map +1 -0
  130. package/dist/schemas/evidence.d.ts +65 -0
  131. package/dist/schemas/evidence.d.ts.map +1 -0
  132. package/dist/schemas/evidence.js +64 -0
  133. package/dist/schemas/evidence.js.map +1 -0
  134. package/dist/schemas/execution-result.d.ts +214 -0
  135. package/dist/schemas/execution-result.d.ts.map +1 -0
  136. package/dist/schemas/execution-result.js +240 -0
  137. package/dist/schemas/execution-result.js.map +1 -0
  138. package/dist/schemas/gate-receipt.d.ts +86 -0
  139. package/dist/schemas/gate-receipt.d.ts.map +1 -0
  140. package/dist/schemas/gate-receipt.js +193 -0
  141. package/dist/schemas/gate-receipt.js.map +1 -0
  142. package/dist/schemas/index.d.ts +22 -0
  143. package/dist/schemas/index.d.ts.map +1 -0
  144. package/dist/schemas/index.js +22 -0
  145. package/dist/schemas/index.js.map +1 -0
  146. package/dist/schemas/obligation.d.ts +37 -0
  147. package/dist/schemas/obligation.d.ts.map +1 -0
  148. package/dist/schemas/obligation.js +46 -0
  149. package/dist/schemas/obligation.js.map +1 -0
  150. package/dist/schemas/plugin.d.ts +19 -0
  151. package/dist/schemas/plugin.d.ts.map +1 -0
  152. package/dist/schemas/plugin.js +20 -0
  153. package/dist/schemas/plugin.js.map +1 -0
  154. package/dist/schemas/policy.d.ts +73 -0
  155. package/dist/schemas/policy.d.ts.map +1 -0
  156. package/dist/schemas/policy.js +46 -0
  157. package/dist/schemas/policy.js.map +1 -0
  158. package/dist/schemas/resource.d.ts +26 -0
  159. package/dist/schemas/resource.d.ts.map +1 -0
  160. package/dist/schemas/resource.js +29 -0
  161. package/dist/schemas/resource.js.map +1 -0
  162. package/dist/schemas/run-manifest.d.ts +72 -0
  163. package/dist/schemas/run-manifest.d.ts.map +1 -0
  164. package/dist/schemas/run-manifest.js +125 -0
  165. package/dist/schemas/run-manifest.js.map +1 -0
  166. package/dist/schemas/runner-adapter.d.ts +169 -0
  167. package/dist/schemas/runner-adapter.d.ts.map +1 -0
  168. package/dist/schemas/runner-adapter.js +2 -0
  169. package/dist/schemas/runner-adapter.js.map +1 -0
  170. package/dist/schemas/test-catalog.d.ts +472 -0
  171. package/dist/schemas/test-catalog.d.ts.map +1 -0
  172. package/dist/schemas/test-catalog.js +311 -0
  173. package/dist/schemas/test-catalog.js.map +1 -0
  174. package/dist/schemas/test-map.d.ts +99 -0
  175. package/dist/schemas/test-map.d.ts.map +1 -0
  176. package/dist/schemas/test-map.js +103 -0
  177. package/dist/schemas/test-map.js.map +1 -0
  178. package/dist/schemas/verdict.d.ts +73 -0
  179. package/dist/schemas/verdict.d.ts.map +1 -0
  180. package/dist/schemas/verdict.js +92 -0
  181. package/dist/schemas/verdict.js.map +1 -0
  182. package/dist/schemas/waiver.d.ts +36 -0
  183. package/dist/schemas/waiver.d.ts.map +1 -0
  184. package/dist/schemas/waiver.js +42 -0
  185. package/dist/schemas/waiver.js.map +1 -0
  186. package/dist/supervision/index.d.ts +170 -0
  187. package/dist/supervision/index.d.ts.map +1 -0
  188. package/dist/supervision/index.js +354 -0
  189. package/dist/supervision/index.js.map +1 -0
  190. package/dist/testing/clock.d.ts +50 -0
  191. package/dist/testing/clock.d.ts.map +1 -0
  192. package/dist/testing/clock.js +75 -0
  193. package/dist/testing/clock.js.map +1 -0
  194. package/dist/testing/env.d.ts +66 -0
  195. package/dist/testing/env.d.ts.map +1 -0
  196. package/dist/testing/env.js +106 -0
  197. package/dist/testing/env.js.map +1 -0
  198. package/dist/testing/gate-runner.d.ts +141 -0
  199. package/dist/testing/gate-runner.d.ts.map +1 -0
  200. package/dist/testing/gate-runner.js +173 -0
  201. package/dist/testing/gate-runner.js.map +1 -0
  202. package/dist/testing/gf19.d.ts +106 -0
  203. package/dist/testing/gf19.d.ts.map +1 -0
  204. package/dist/testing/gf19.js +282 -0
  205. package/dist/testing/gf19.js.map +1 -0
  206. package/dist/testing/index.d.ts +20 -0
  207. package/dist/testing/index.d.ts.map +1 -0
  208. package/dist/testing/index.js +14 -0
  209. package/dist/testing/index.js.map +1 -0
  210. package/dist/testing/red-probe.d.ts +138 -0
  211. package/dist/testing/red-probe.d.ts.map +1 -0
  212. package/dist/testing/red-probe.js +251 -0
  213. package/dist/testing/red-probe.js.map +1 -0
  214. package/dist/testing/temp-repo.d.ts +126 -0
  215. package/dist/testing/temp-repo.d.ts.map +1 -0
  216. package/dist/testing/temp-repo.js +214 -0
  217. package/dist/testing/temp-repo.js.map +1 -0
  218. package/dist/verdict/cause.d.ts +99 -0
  219. package/dist/verdict/cause.d.ts.map +1 -0
  220. package/dist/verdict/cause.js +206 -0
  221. package/dist/verdict/cause.js.map +1 -0
  222. package/dist/verdict/evaluate.d.ts +135 -0
  223. package/dist/verdict/evaluate.d.ts.map +1 -0
  224. package/dist/verdict/evaluate.js +1513 -0
  225. package/dist/verdict/evaluate.js.map +1 -0
  226. package/dist/verdict/index.d.ts +21 -0
  227. package/dist/verdict/index.d.ts.map +1 -0
  228. package/dist/verdict/index.js +20 -0
  229. package/dist/verdict/index.js.map +1 -0
  230. package/dist/verdict/pack-verifiers.d.ts +97 -0
  231. package/dist/verdict/pack-verifiers.d.ts.map +1 -0
  232. package/dist/verdict/pack-verifiers.js +763 -0
  233. package/dist/verdict/pack-verifiers.js.map +1 -0
  234. package/dist/verdict/registry.d.ts +180 -0
  235. package/dist/verdict/registry.d.ts.map +1 -0
  236. package/dist/verdict/registry.js +67 -0
  237. package/dist/verdict/registry.js.map +1 -0
  238. package/dist/waivers/index.d.ts +103 -0
  239. package/dist/waivers/index.d.ts.map +1 -0
  240. package/dist/waivers/index.js +192 -0
  241. package/dist/waivers/index.js.map +1 -0
  242. package/package.json +40 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Closed-world CRUD coverage evaluator (plan 2026-09-13 §3.6, Phase 0
3
+ * item 7, ADR 0005 D5). Pure and deterministic: given the owner-owned
4
+ * coverage policy tables, the CURRENT run's user-facing table inventory,
5
+ * and the resolved test mappings, it returns typed blocking
6
+ * `CRUD_COVERAGE_MISSING` findings for every required operation lacking
7
+ * mapped browser-e2e coverage and lacking an owner disposition.
8
+ *
9
+ * Fail-closed by construction:
10
+ * - The caller MUST pass the resource inventory. A policy table absent
11
+ * from it yields a CONFIG-ERROR result (callers turn that into exit 2):
12
+ * a name the inventory cannot see is silently uncheckable, and a
13
+ * silently dropped table is a violation, never coverage.
14
+ * - Inventory tables the policy does NOT enumerate are violations too
15
+ * (the policy is closed-world over the inventory).
16
+ * - Only `browser-e2e` mappings satisfy (plan §3.2: api-e2e cannot
17
+ * substitute for browser behavior); the mapping subsystem may pass an
18
+ * empty list for now — the honest result is that enabled, undispositioned
19
+ * tables block until mappings or dispositions exist.
20
+ */
21
+ import { compareStrings } from '../graph/util.js';
22
+ import { CAUSE_NEXT_ACTIONS } from '../schemas/verdict.js';
23
+ /** Cause + next action for every blocking finding (plan §5.4). */
24
+ const CRUD_COVERAGE_MISSING_CAUSE = CAUSE_NEXT_ACTIONS['CRUD_COVERAGE_MISSING'];
25
+ /**
26
+ * Evaluates the coverage policy against the current inventory and
27
+ * resolved mappings. Pure: identical inputs produce byte-identical
28
+ * results; findings sort by table then operation.
29
+ *
30
+ * Semantics:
31
+ * - policy table absent from the inventory → CONFIG-ERROR
32
+ * (`COVERAGE_TABLE_UNKNOWN`);
33
+ * - inventory table absent from the policy → blocking (closed-world: a
34
+ * silently dropped table is a violation);
35
+ * - dispositioned table → excused (the disposition is a trusted owner
36
+ * act recorded in config, never an agent self-approval);
37
+ * - otherwise each required operation without a `browser-e2e` mapping →
38
+ * blocking `CRUD_COVERAGE_MISSING`.
39
+ *
40
+ * Args:
41
+ * tables: the policy's table entries (validated `CoveragePolicySchema`).
42
+ * inventory: the current run's user-facing table inventory (REQUIRED).
43
+ * mappedCoverage: resolved test mappings; may be empty while the
44
+ * mapping subsystem is unbuilt (Phase 2-3).
45
+ *
46
+ * Returns:
47
+ * CoveragePolicyResult: sorted config errors and blocking findings.
48
+ */
49
+ export function evaluateCoveragePolicy(tables, inventory, mappedCoverage = []) {
50
+ const inventoryByName = new Map();
51
+ for (const entry of inventory) {
52
+ const existing = inventoryByName.get(entry.name);
53
+ if (existing === undefined)
54
+ inventoryByName.set(entry.name, [entry]);
55
+ else
56
+ existing.push(entry);
57
+ }
58
+ const policyNames = new Set(tables.map((table) => table.name));
59
+ const configErrors = [];
60
+ const blocking = [];
61
+ for (const table of tables) {
62
+ const known = inventoryByName.get(table.name);
63
+ if (known === undefined) {
64
+ configErrors.push({
65
+ code: 'COVERAGE_TABLE_UNKNOWN',
66
+ table: table.name,
67
+ detail: `coverage policy names table '${table.name}' which is not present in the current ` +
68
+ 'resource inventory; a name the inventory cannot see is silently uncheckable, so ' +
69
+ 'the run fails as a configuration error (a silently dropped table is a violation, ' +
70
+ 'never coverage)',
71
+ });
72
+ continue;
73
+ }
74
+ // A recorded owner disposition excuses the table's required
75
+ // operations (trusted-policy act, ADR 0005 D5).
76
+ if (table.disposition !== undefined)
77
+ continue;
78
+ for (const operation of table.requiredOperations) {
79
+ const covered = mappedCoverage.some((mapping) => mapping.table === table.name &&
80
+ mapping.operation === operation &&
81
+ mapping.testKind === 'browser-e2e');
82
+ if (covered)
83
+ continue;
84
+ blocking.push({
85
+ code: 'CRUD_COVERAGE_MISSING',
86
+ cause: 'CRUD_COVERAGE_MISSING',
87
+ table: table.name,
88
+ operation,
89
+ detail: `coverage policy: table '${table.name}' has no mapped browser-e2e '${operation}' ` +
90
+ 'coverage and no owner disposition',
91
+ nextAction: CRUD_COVERAGE_MISSING_CAUSE,
92
+ });
93
+ }
94
+ }
95
+ // Closed-world: an inventory table the policy does not enumerate is a
96
+ // dropped violation, not coverage (plan Phase 0 item 7).
97
+ for (const [name, entries] of inventoryByName) {
98
+ if (policyNames.has(name))
99
+ continue;
100
+ const operations = [
101
+ ...new Set(entries.flatMap((entry) => [...entry.operations])),
102
+ ].sort(compareStrings);
103
+ blocking.push({
104
+ code: 'CRUD_COVERAGE_MISSING',
105
+ cause: 'CRUD_COVERAGE_MISSING',
106
+ table: name,
107
+ operation: null,
108
+ detail: `coverage policy: user-facing table '${name}' is present in the resource inventory ` +
109
+ `but the policy does not enumerate it (enabled operations: ` +
110
+ `[${operations.join(', ')}]); a silently dropped table is a violation, never coverage`,
111
+ nextAction: CRUD_COVERAGE_MISSING_CAUSE,
112
+ });
113
+ }
114
+ configErrors.sort((a, b) => compareStrings(a.table, b.table));
115
+ blocking.sort((a, b) => compareStrings(a.table, b.table) ||
116
+ compareStrings(a.operation ?? '', b.operation ?? ''));
117
+ return { configErrors, blocking };
118
+ }
119
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/policy/coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Policy engine (plan §5.2, G2): evaluates declarative policies
3
+ * (`PolicyFile`) against the classified resources of a built
4
+ * {@link ResourceGraph} and produces obligations plus the blocking
5
+ * verdict entries the gate must stay visible for (invariants 1, 8).
6
+ *
7
+ * Semantics (plan §5.2 + ADR 0001):
8
+ * - `crud:create|read|update|delete` obligations are LIFECYCLE-GATED:
9
+ * a contract is emitted only when the classification's lifecycle
10
+ * flag for that operation is `true` (user-facing + `lifecycle.create`
11
+ * ⇒ `crud:create`, etc.). Non-uniform lifecycles fall out naturally:
12
+ * immutable/read-only resources generate only `crud:read`, append-only
13
+ * resources `crud:create` + `crud:read`, archive-not-delete resources
14
+ * `crud:delete` with `deleteSemantics: 'archive'` in the fingerprint.
15
+ * - Non-`crud:` contracts pass through ungated (the policy author
16
+ * explicitly required them).
17
+ * - Internal resources generate NO CRUD obligations — their claims are
18
+ * invalid (ADR 0001). Non-CRUD contracts still apply.
19
+ * - Unclassified and unresolved resources produce blocking entries and
20
+ * no obligations until classified/resolved, but stay gate-visible.
21
+ * So do detector/graph `findings` (a partial discovery must never
22
+ * yield a green gate) and `stale` references (invariant 9).
23
+ * - Policies are evaluated in file order; the first policy generating
24
+ * a given `<resourceId>:<contract>` owns it (obligation ids are
25
+ * unique identities — pin #1's fingerprint keys on them).
26
+ */
27
+ import { z } from 'zod';
28
+ import { type ContractName } from '../schemas/common.js';
29
+ import { type PolicyFile } from '../schemas/policy.js';
30
+ import { type Claim } from '../schemas/claim.js';
31
+ import { type ResourceGraph } from '../graph/schema.js';
32
+ /** The CRUD contract namespace gated by lifecycle flags. */
33
+ export declare const CRUD_CONTRACT_PREFIX = "crud:";
34
+ /**
35
+ * The persistence-level CRUD contract namespace (audit round 5):
36
+ * lifecycle-gated exactly like `crud:`, but graded on the witness's own
37
+ * engine-side observations (absence/presence, before/after deltas,
38
+ * owner-declared archive state). UI-semantic `crud:` contracts stay
39
+ * fail-closed in the verdict engine until a witness-controlled UI
40
+ * observation channel exists.
41
+ */
42
+ export declare const PERSISTENCE_CONTRACT_PREFIX = "persistence:";
43
+ /**
44
+ * Fail-closed policy-engine error: thrown for policy documents that
45
+ * are structurally invalid (zod) or use the `crud:` namespace with an
46
+ * unknown operation — a config/usage problem, never a silent skip.
47
+ */
48
+ export declare class PolicyEvaluationError extends Error {
49
+ constructor(message: string);
50
+ }
51
+ /** Why a resource currently generates no obligations. */
52
+ export declare const BlockingEntrySchema: z.ZodObject<{
53
+ kind: z.ZodEnum<{
54
+ unclassified: "unclassified";
55
+ unresolved: "unresolved";
56
+ classification: "classification";
57
+ finding: "finding";
58
+ "stale-reference": "stale-reference";
59
+ }>;
60
+ resourceId: z.ZodNullable<z.ZodString>;
61
+ name: z.ZodNullable<z.ZodString>;
62
+ detail: z.ZodString;
63
+ location: z.ZodNullable<z.ZodObject<{
64
+ file: z.ZodString;
65
+ line: z.ZodNumber;
66
+ col: z.ZodNumber;
67
+ }, z.core.$strict>>;
68
+ cause: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
69
+ TEST_INVENTORY_INCOMPLETE: "TEST_INVENTORY_INCOMPLETE";
70
+ TEST_KIND_UNKNOWN: "TEST_KIND_UNKNOWN";
71
+ TEST_MAPPING_MISSING: "TEST_MAPPING_MISSING";
72
+ TEST_MAPPING_AMBIGUOUS: "TEST_MAPPING_AMBIGUOUS";
73
+ TEST_MAPPING_STALE: "TEST_MAPPING_STALE";
74
+ EVIDENCE_NOT_COLLECTED: "EVIDENCE_NOT_COLLECTED";
75
+ VERIFIER_UNSUPPORTED: "VERIFIER_UNSUPPORTED";
76
+ TEST_NOT_EXECUTED: "TEST_NOT_EXECUTED";
77
+ TEST_FAILED: "TEST_FAILED";
78
+ RUN_INCOMPLETE: "RUN_INCOMPLETE";
79
+ EVIDENCE_STALE: "EVIDENCE_STALE";
80
+ CHANGE_UNMAPPED: "CHANGE_UNMAPPED";
81
+ EVIDENCE_SCOPE_INCOMPLETE: "EVIDENCE_SCOPE_INCOMPLETE";
82
+ ENFORCEMENT_UNTRUSTED: "ENFORCEMENT_UNTRUSTED";
83
+ EVIDENCE_VALUE_MISMATCH: "EVIDENCE_VALUE_MISMATCH";
84
+ SERVER_PROBE_UNAVAILABLE: "SERVER_PROBE_UNAVAILABLE";
85
+ CRUD_COVERAGE_MISSING: "CRUD_COVERAGE_MISSING";
86
+ DIAGNOSTIC_TEST_FAILURE: "DIAGNOSTIC_TEST_FAILURE";
87
+ DIAGNOSTIC_RUN_INCOMPLETE: "DIAGNOSTIC_RUN_INCOMPLETE";
88
+ DIAGNOSTIC_RESULT_STALE: "DIAGNOSTIC_RESULT_STALE";
89
+ }>>>;
90
+ nextAction: z.ZodOptional<z.ZodNullable<z.ZodString>>;
91
+ }, z.core.$strict>;
92
+ /** Inferred blocking-entry shape. */
93
+ export type BlockingEntry = z.infer<typeof BlockingEntrySchema>;
94
+ /**
95
+ * The adopted identity of a classification-blocked resource (two-layer
96
+ * adoption): the ONE canonical string both `gateforge adopt` captures
97
+ * into the receipt's `classificationBlocked` set and the check matches
98
+ * against when waiving — so the two sides can never disagree.
99
+ *
100
+ * - The plane-qualified `resourceId` when the entry carries one (blocks
101
+ * on otherwise-classified resources, e.g. delete-semantics).
102
+ * - Else the bare resource name under a `name:` namespace — a resource
103
+ * with NO derivable plane (PLANE_UNRESOLVED) has no plane-qualified id
104
+ * by definition, and its bare name is the stable, merge-surviving
105
+ * identity. The `name:` prefix keeps the fallback out of the
106
+ * plane-qualified id space (`tenant.users` et al.).
107
+ * - Both the `classification` entry (the typed block) AND the
108
+ * `unclassified` shadow entry (the definitional "no effective
109
+ * classification" block the policy engine emits for the SAME resource)
110
+ * map to the same identity: waiving the resource waives its whole
111
+ * adopted block, or the gate could never return to green.
112
+ *
113
+ * Returns null for entries that are never resource-scoped (document-level
114
+ * classifier blocks — stale targets, invalid signals — and
115
+ * unresolved/finding/stale-reference kinds): those can never be adopted
116
+ * by this layer.
117
+ */
118
+ export declare function classificationBlockedIdentity(entry: BlockingEntry): string | null;
119
+ /** Assessment of one watched claim against the generated obligations. */
120
+ export declare const ClaimAssessmentSchema: z.ZodObject<{
121
+ claim: z.ZodObject<{
122
+ schemaVersion: z.ZodLiteral<1>;
123
+ obligationId: z.ZodString;
124
+ testId: z.ZodString;
125
+ testFile: z.ZodOptional<z.ZodString>;
126
+ location: z.ZodOptional<z.ZodObject<{
127
+ file: z.ZodString;
128
+ line: z.ZodNumber;
129
+ col: z.ZodNumber;
130
+ }, z.core.$strict>>;
131
+ }, z.core.$strict>;
132
+ status: z.ZodEnum<{
133
+ invalid: "invalid";
134
+ valid: "valid";
135
+ }>;
136
+ reason: z.ZodNullable<z.ZodString>;
137
+ }, z.core.$strict>;
138
+ /** Inferred claim-assessment shape. */
139
+ export type ClaimAssessment = z.infer<typeof ClaimAssessmentSchema>;
140
+ /** The complete policy-engine result. Deterministic; fully sorted. */
141
+ export declare const PolicyEvaluationResultSchema: z.ZodObject<{
142
+ schemaVersion: z.ZodLiteral<1>;
143
+ obligations: z.ZodArray<z.ZodObject<{
144
+ schemaVersion: z.ZodLiteral<1>;
145
+ id: z.ZodString;
146
+ resourceId: z.ZodString;
147
+ contract: z.ZodString;
148
+ policyId: z.ZodString;
149
+ lifecycle: z.ZodObject<{
150
+ create: z.ZodBoolean;
151
+ read: z.ZodBoolean;
152
+ update: z.ZodBoolean;
153
+ delete: z.ZodBoolean;
154
+ deleteSemantics: z.ZodOptional<z.ZodEnum<{
155
+ hard: "hard";
156
+ archive: "archive";
157
+ }>>;
158
+ archiveFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
159
+ updateableFields: z.ZodOptional<z.ZodArray<z.ZodString>>;
160
+ }, z.core.$strict>;
161
+ }, z.core.$strict>>;
162
+ blocking: z.ZodArray<z.ZodObject<{
163
+ kind: z.ZodEnum<{
164
+ unclassified: "unclassified";
165
+ unresolved: "unresolved";
166
+ classification: "classification";
167
+ finding: "finding";
168
+ "stale-reference": "stale-reference";
169
+ }>;
170
+ resourceId: z.ZodNullable<z.ZodString>;
171
+ name: z.ZodNullable<z.ZodString>;
172
+ detail: z.ZodString;
173
+ location: z.ZodNullable<z.ZodObject<{
174
+ file: z.ZodString;
175
+ line: z.ZodNumber;
176
+ col: z.ZodNumber;
177
+ }, z.core.$strict>>;
178
+ cause: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
179
+ TEST_INVENTORY_INCOMPLETE: "TEST_INVENTORY_INCOMPLETE";
180
+ TEST_KIND_UNKNOWN: "TEST_KIND_UNKNOWN";
181
+ TEST_MAPPING_MISSING: "TEST_MAPPING_MISSING";
182
+ TEST_MAPPING_AMBIGUOUS: "TEST_MAPPING_AMBIGUOUS";
183
+ TEST_MAPPING_STALE: "TEST_MAPPING_STALE";
184
+ EVIDENCE_NOT_COLLECTED: "EVIDENCE_NOT_COLLECTED";
185
+ VERIFIER_UNSUPPORTED: "VERIFIER_UNSUPPORTED";
186
+ TEST_NOT_EXECUTED: "TEST_NOT_EXECUTED";
187
+ TEST_FAILED: "TEST_FAILED";
188
+ RUN_INCOMPLETE: "RUN_INCOMPLETE";
189
+ EVIDENCE_STALE: "EVIDENCE_STALE";
190
+ CHANGE_UNMAPPED: "CHANGE_UNMAPPED";
191
+ EVIDENCE_SCOPE_INCOMPLETE: "EVIDENCE_SCOPE_INCOMPLETE";
192
+ ENFORCEMENT_UNTRUSTED: "ENFORCEMENT_UNTRUSTED";
193
+ EVIDENCE_VALUE_MISMATCH: "EVIDENCE_VALUE_MISMATCH";
194
+ SERVER_PROBE_UNAVAILABLE: "SERVER_PROBE_UNAVAILABLE";
195
+ CRUD_COVERAGE_MISSING: "CRUD_COVERAGE_MISSING";
196
+ DIAGNOSTIC_TEST_FAILURE: "DIAGNOSTIC_TEST_FAILURE";
197
+ DIAGNOSTIC_RUN_INCOMPLETE: "DIAGNOSTIC_RUN_INCOMPLETE";
198
+ DIAGNOSTIC_RESULT_STALE: "DIAGNOSTIC_RESULT_STALE";
199
+ }>>>;
200
+ nextAction: z.ZodOptional<z.ZodNullable<z.ZodString>>;
201
+ }, z.core.$strict>>;
202
+ claims: z.ZodArray<z.ZodObject<{
203
+ claim: z.ZodObject<{
204
+ schemaVersion: z.ZodLiteral<1>;
205
+ obligationId: z.ZodString;
206
+ testId: z.ZodString;
207
+ testFile: z.ZodOptional<z.ZodString>;
208
+ location: z.ZodOptional<z.ZodObject<{
209
+ file: z.ZodString;
210
+ line: z.ZodNumber;
211
+ col: z.ZodNumber;
212
+ }, z.core.$strict>>;
213
+ }, z.core.$strict>;
214
+ status: z.ZodEnum<{
215
+ invalid: "invalid";
216
+ valid: "valid";
217
+ }>;
218
+ reason: z.ZodNullable<z.ZodString>;
219
+ }, z.core.$strict>>;
220
+ }, z.core.$strict>;
221
+ /** Inferred policy-evaluation-result shape. */
222
+ export type PolicyEvaluationResult = z.infer<typeof PolicyEvaluationResultSchema>;
223
+ /**
224
+ * Whether a contract is allowed by a lifecycle. `crud:` and
225
+ * `persistence:` contracts map to their lifecycle flag (`crud:create` ⇔
226
+ * `lifecycle.create === true`, etc. — unknown operations in either
227
+ * namespace are a policy-authoring error); every other contract passes
228
+ * through ungated.
229
+ *
230
+ * Args:
231
+ * contract: the required contract name, e.g. `crud:update`.
232
+ * lifecycle: the classification's lifecycle flags.
233
+ *
234
+ * Returns:
235
+ * boolean: true when an obligation for this contract must be generated.
236
+ * @throws PolicyEvaluationError for `crud:`/`persistence:` contracts
237
+ * outside the four lifecycle operations.
238
+ */
239
+ export declare function lifecycleAllowsContract(contract: ContractName, lifecycle: {
240
+ create: boolean;
241
+ read: boolean;
242
+ update: boolean;
243
+ delete: boolean;
244
+ archiveFields?: Record<string, string | number | boolean>;
245
+ }): boolean;
246
+ export interface PolicyEvaluationInput {
247
+ /** A graph built by `buildResourceGraph`. */
248
+ graph: ResourceGraph;
249
+ /** The declarative policies document (validated fail-closed). */
250
+ policies: PolicyFile;
251
+ /** Claims to assess against the generated obligations (ADR 0001). */
252
+ claims?: Claim[];
253
+ /**
254
+ * Pre-projected blocking entries from the classifier (plan phase 5),
255
+ * appended verbatim before the deterministic sort.
256
+ */
257
+ extraBlocking?: BlockingEntry[];
258
+ }
259
+ /**
260
+ * Evaluates the policy document against a built resource graph.
261
+ *
262
+ * Args:
263
+ * input: graph + policies (+ claims to assess). The policy document
264
+ * is validated fail-closed; resources are consumed in the graph's
265
+ * deterministic order.
266
+ *
267
+ * Returns:
268
+ * PolicyEvaluationResult: obligations, blocking entries, and claim
269
+ * assessments — all sorted, byte-for-byte deterministic.
270
+ * @throws z.ZodError when the policy document is invalid (config error).
271
+ * @throws PolicyEvaluationError for `crud:` contracts outside the four
272
+ * lifecycle operations.
273
+ */
274
+ export declare function evaluatePolicies(input: PolicyEvaluationInput): PolicyEvaluationResult;
275
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/policy/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAsC,KAAK,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AAG5G,OAAO,EAAiC,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAmD,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGzG,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,iBAAiB,CAAC;AAK1D;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,EAAE,MAAM;CAI5B;AAED,yDAAyD;AACzD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsC5B,CAAC;AAEL,qCAAqC;AACrC,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAKjF;AAED,yEAAyE;AACzE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;kBAM9B,CAAC;AAEL,uCAAuC;AACvC,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,sEAAsE;AACtE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAcrC,CAAC;AAEL,+CAA+C;AAC/C,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE;IACT,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CAC3D,GACA,OAAO,CAaT;AAED,MAAM,WAAW,qBAAqB;IACpC,6CAA6C;IAC7C,KAAK,EAAE,aAAa,CAAC;IACrB,iEAAiE;IACjE,QAAQ,EAAE,UAAU,CAAC;IACrB,qEAAqE;IACrE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAC;CACjC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CAmErF"}