enigma-memory 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 (105) hide show
  1. package/LICENSE +55 -0
  2. package/README.md +379 -0
  3. package/apps/cli/bin/enigma.mjs +1117 -0
  4. package/apps/desktop/src/app.js +1327 -0
  5. package/apps/desktop/src/index.html +1373 -0
  6. package/apps/desktop/src/styles.css +386 -0
  7. package/apps/gateway/bin/enigma-gateway.mjs +52 -0
  8. package/apps/gateway/src/server.mjs +1403 -0
  9. package/apps/native-host/README.md +265 -0
  10. package/apps/native-host/bin/enigma-native-host.mjs +499 -0
  11. package/apps/native-host/manifests/com.enigma.native_host.chrome.json +9 -0
  12. package/apps/native-host/manifests/com.enigma.native_host.edge.json +9 -0
  13. package/apps/native-host/manifests/com.enigma.native_host.firefox.json +9 -0
  14. package/apps/relay/bin/enigma-relay.mjs +52 -0
  15. package/apps/relay/src/server.mjs +1571 -0
  16. package/apps/verifier/bin/enigma-verify.mjs +240 -0
  17. package/deploy/docker-compose.production.example.yml +150 -0
  18. package/deploy/kubernetes/enigma-backend.example.yaml +580 -0
  19. package/package.json +196 -0
  20. package/packages/adapters/PACKAGE_CONTRACT.md +47 -0
  21. package/packages/adapters/src/index.js +183 -0
  22. package/packages/boundary/src/index.js +468 -0
  23. package/packages/connectors/src/index.js +533 -0
  24. package/packages/core/src/index.js +766 -0
  25. package/packages/enterprise/src/index.js +505 -0
  26. package/packages/importers/src/index.js +1083 -0
  27. package/packages/mcp-server/bin/enigma-mcp.mjs +19 -0
  28. package/packages/mcp-server/src/index.js +1185 -0
  29. package/packages/mesh/src/index.js +531 -0
  30. package/packages/metering/PACKAGE_CONTRACT.md +20 -0
  31. package/packages/metering/src/index.js +246 -0
  32. package/packages/optimizer/src/index.js +707 -0
  33. package/packages/passport/src/index.js +651 -0
  34. package/packages/settlement/PACKAGE_CONTRACT.md +28 -0
  35. package/packages/settlement/src/index.js +369 -0
  36. package/packages/storage/PACKAGE_CONTRACT.md +23 -0
  37. package/packages/storage/src/index.js +392 -0
  38. package/packages/vault/src/index.js +904 -0
  39. package/scripts/build-ai-orchestration-plan.mjs +248 -0
  40. package/scripts/build-cloudflare-pages-release-packet.mjs +287 -0
  41. package/scripts/build-cloudflare-token-policy.mjs +239 -0
  42. package/scripts/build-cloudflare-token-request.mjs +314 -0
  43. package/scripts/build-demo-assets.mjs +263 -0
  44. package/scripts/build-edge-backend-workers.mjs +353 -0
  45. package/scripts/build-goal-completion-audit.mjs +398 -0
  46. package/scripts/build-hosted-probe-worker.mjs +191 -0
  47. package/scripts/build-operator-acceptance-packet.mjs +254 -0
  48. package/scripts/build-operator-evidence-starter.mjs +525 -0
  49. package/scripts/build-production-backend-env-kit.mjs +384 -0
  50. package/scripts/build-production-dependency-report.mjs +369 -0
  51. package/scripts/build-production-handoff-packet.mjs +475 -0
  52. package/scripts/build-production-readiness-manifest.mjs +209 -0
  53. package/scripts/build-production-status-board.mjs +297 -0
  54. package/scripts/build-production-storage-migration.mjs +86 -0
  55. package/scripts/build-production-workplan.mjs +371 -0
  56. package/scripts/build-review-packet.mjs +594 -0
  57. package/scripts/check.mjs +419 -0
  58. package/scripts/cloudflare-ops.mjs +1672 -0
  59. package/scripts/cloudflare-secret-env.mjs +128 -0
  60. package/scripts/collect-hosted-backend-live-evidence.mjs +263 -0
  61. package/scripts/infrastructure-readiness.mjs +944 -0
  62. package/scripts/install-enigma-local.mjs +270 -0
  63. package/scripts/memory-optimization-benchmark.mjs +242 -0
  64. package/scripts/monitor-live-endpoints.mjs +358 -0
  65. package/scripts/release-audit.mjs +5588 -0
  66. package/scripts/release-provenance.mjs +250 -0
  67. package/scripts/run-backend-readiness-smoke.mjs +220 -0
  68. package/scripts/validate-backup-restore-drill.mjs +166 -0
  69. package/scripts/validate-cloudflare-credentials.mjs +112 -0
  70. package/scripts/validate-cloudflare-worker-inspect.mjs +179 -0
  71. package/scripts/validate-domain-tls.mjs +248 -0
  72. package/scripts/validate-hosted-backend-live.mjs +319 -0
  73. package/scripts/validate-incident-drill.mjs +221 -0
  74. package/scripts/validate-kms-custody.mjs +235 -0
  75. package/scripts/validate-legal-compliance-approval.mjs +274 -0
  76. package/scripts/validate-monitoring-alerting.mjs +263 -0
  77. package/scripts/validate-network-access-policy.mjs +285 -0
  78. package/scripts/validate-operator-acceptance.mjs +298 -0
  79. package/scripts/validate-production-manifests.mjs +325 -0
  80. package/scripts/validate-public-site-security.mjs +252 -0
  81. package/scripts/validate-security-threat-model.mjs +285 -0
  82. package/scripts/validate-service-settlement.mjs +256 -0
  83. package/scripts/validate-support-sla.mjs +190 -0
  84. package/scripts/validate-tenant-policy-approval.mjs +228 -0
  85. package/scripts/validate-usage-metering.mjs +224 -0
  86. package/scripts/validate-whitepaper-claims.mjs +166 -0
  87. package/specs/boundary-manifest-v1.schema.json +35 -0
  88. package/specs/capsule-v1.schema.json +55 -0
  89. package/specs/claim-boundary-manifest-v1.schema.json +22 -0
  90. package/specs/connector-profile-v1.schema.json +62 -0
  91. package/specs/deletion-tombstone-v1.schema.json +26 -0
  92. package/specs/enterprise-policy-v1.schema.json +59 -0
  93. package/specs/gateway-request-v1.schema.json +32 -0
  94. package/specs/goal-completion-audit-v1.schema.json +70 -0
  95. package/specs/hosted-backend-live-evidence-v1.schema.json +147 -0
  96. package/specs/import-report-v1.schema.json +214 -0
  97. package/specs/infrastructure-readiness-manifest-v1.schema.json +130 -0
  98. package/specs/memory-event-v1.schema.json +42 -0
  99. package/specs/mesh-node-v1.schema.json +126 -0
  100. package/specs/passport-v1.schema.json +50 -0
  101. package/specs/production-handoff-packet-v1.schema.json +149 -0
  102. package/specs/receipt-v1.schema.json +61 -0
  103. package/specs/relay-record-v1.schema.json +43 -0
  104. package/specs/state-checkpoint-v1.schema.json +37 -0
  105. package/specs/trust-bundle-v1.schema.json +56 -0
@@ -0,0 +1,468 @@
1
+ import { canonicalize, createMemoryAddress, sha256Hex } from '../../core/src/index.js';
2
+
3
+ const MANIFEST_SCHEMA = 'enigma.boundary_manifest.v1';
4
+ const DEFAULT_ACTION = 'fail_unknown';
5
+ const DEFAULT_CREATED_AT = '1970-01-01T00:00:00.000Z';
6
+ const DEFAULT_HMAC_KEY = 'enigma-boundary-local-proof-key';
7
+ const FACT_DOMAIN = 'enigma.boundary.fact.v1';
8
+
9
+ const SURFACES = Object.freeze([
10
+ 'model_input',
11
+ 'model_output',
12
+ 'tool_args',
13
+ 'tool_result',
14
+ 'scratchpad',
15
+ 'clipboard',
16
+ 'memory_write',
17
+ 'memory_read',
18
+ 'rag_ingest',
19
+ 'rag_retrieve',
20
+ 'file_write',
21
+ 'log',
22
+ 'telemetry',
23
+ 'browser_dom',
24
+ 'mcp_resource',
25
+ 'network',
26
+ 'inter_agent',
27
+ 'cache',
28
+ 'human_approval'
29
+ ]);
30
+
31
+ const CLASSIFICATIONS = Object.freeze([
32
+ 'committed',
33
+ 'blocked',
34
+ 'declared_out_of_scope',
35
+ 'broken',
36
+ 'fail_closed'
37
+ ]);
38
+
39
+ const SURFACE_SET = new Set(SURFACES);
40
+ const CLASSIFICATION_SET = new Set(CLASSIFICATIONS);
41
+
42
+ function assertPlainRecord(value, name) {
43
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
44
+ throw new TypeError(`${name} must be an object`);
45
+ }
46
+ }
47
+
48
+
49
+ function factCommitment(fact, { hmacKey = DEFAULT_HMAC_KEY, runId = 'boundary-sim', scenario = 'unspecified' } = {}) {
50
+ return createMemoryAddress({
51
+ secret: hmacKey,
52
+ namespace: FACT_DOMAIN,
53
+ subject_id: scenario,
54
+ value: { fact, runId },
55
+ prefix: 'boundary'
56
+ });
57
+ }
58
+
59
+ function defaultBoundaryPaths() {
60
+ return [
61
+ { path_id: 'model_input:committed', surface: 'model_input', classification: 'committed', coverage_receipt_required: true },
62
+ { path_id: 'model_output:committed', surface: 'model_output', classification: 'committed', coverage_receipt_required: true },
63
+ { path_id: 'tool_args:committed', surface: 'tool_args', classification: 'committed', coverage_receipt_required: true },
64
+ { path_id: 'tool_result:raw', surface: 'tool_result', classification: 'broken', reason: 'Uninstrumented tool result can move exact facts without an Enigma receipt.' },
65
+ { path_id: 'tool_result:committed', surface: 'tool_result', classification: 'committed', coverage_receipt_required: true },
66
+ { path_id: 'scratchpad:raw', surface: 'scratchpad', classification: 'broken', reason: 'Uninstrumented scratchpad can carry exact facts outside the committed channel.' },
67
+ { path_id: 'scratchpad:committed', surface: 'scratchpad', classification: 'committed', coverage_receipt_required: true },
68
+ { path_id: 'clipboard:raw', surface: 'clipboard', classification: 'broken', reason: 'Uninstrumented clipboard can carry exact facts outside the committed channel.' },
69
+ { path_id: 'clipboard:committed', surface: 'clipboard', classification: 'committed', coverage_receipt_required: true },
70
+ { path_id: 'memory_write:committed', surface: 'memory_write', classification: 'committed', coverage_receipt_required: true },
71
+ { path_id: 'memory_read:committed', surface: 'memory_read', classification: 'committed', coverage_receipt_required: true },
72
+ { path_id: 'rag_ingest:blocked', surface: 'rag_ingest', classification: 'blocked', reason: 'Semantic/vector ingestion is not admitted by the exact boundary harness.' },
73
+ { path_id: 'rag_retrieve:semantic', surface: 'rag_retrieve', classification: 'declared_out_of_scope', reason: 'Semantic/RAG paraphrase equivalence is outside exact CANP claims.' },
74
+ { path_id: 'file_write:raw', surface: 'file_write', classification: 'broken', reason: 'File artifacts can leak exact facts unless routed through committed receipts.' },
75
+ { path_id: 'log:raw', surface: 'log', classification: 'broken', reason: 'Logs can leak exact facts unless blocked or committed.' },
76
+ { path_id: 'telemetry:blocked', surface: 'telemetry', classification: 'blocked', reason: 'Telemetry egress is denied for boundary canaries.' },
77
+ { path_id: 'browser_dom:blocked', surface: 'browser_dom', classification: 'blocked', reason: 'Browser DOM injection is denied in the local harness.' },
78
+ { path_id: 'mcp_resource:committed', surface: 'mcp_resource', classification: 'committed', coverage_receipt_required: true },
79
+ { path_id: 'network:callback', surface: 'network', classification: 'broken', reason: 'Network callbacks can leak exact facts unless blocked or committed.' },
80
+ { path_id: 'inter_agent:committed', surface: 'inter_agent', classification: 'committed', coverage_receipt_required: true },
81
+ { path_id: 'cache:blocked', surface: 'cache', classification: 'blocked', reason: 'Cache side paths are denied in the local harness.' },
82
+ { path_id: 'human_approval:committed', surface: 'human_approval', classification: 'committed', coverage_receipt_required: true }
83
+ ];
84
+ }
85
+
86
+ function normalizePath(path) {
87
+ assertPlainRecord(path, 'boundary path');
88
+ const out = {
89
+ path_id: String(path.path_id ?? ''),
90
+ surface: String(path.surface ?? ''),
91
+ classification: String(path.classification ?? '')
92
+ };
93
+
94
+ if (path.adapter !== undefined) out.adapter = String(path.adapter);
95
+ if (path.reason !== undefined) out.reason = String(path.reason);
96
+ if (path.coverage_receipt_required !== undefined) out.coverage_receipt_required = Boolean(path.coverage_receipt_required);
97
+ return out;
98
+ }
99
+
100
+ export function createBoundaryManifest(options = {}) {
101
+ assertPlainRecord(options, 'options');
102
+ const systemId = String(options.systemId ?? options.system_id ?? 'local-boundary-sim');
103
+ const createdAt = String(options.createdAt ?? options.created_at ?? DEFAULT_CREATED_AT);
104
+ const paths = (options.paths ?? defaultBoundaryPaths()).map(normalizePath);
105
+ const manifestWithoutId = {
106
+ schema: MANIFEST_SCHEMA,
107
+ manifest_id: 'pending',
108
+ system_id: systemId,
109
+ created_at: createdAt,
110
+ paths,
111
+ default_action: DEFAULT_ACTION
112
+ };
113
+ const manifestId = String(options.manifestId ?? options.manifest_id ?? sha256Hex(canonicalize({ ...manifestWithoutId, manifest_id: '' })).slice(0, 24));
114
+ return { ...manifestWithoutId, manifest_id: manifestId };
115
+ }
116
+
117
+ export function verifyBoundaryManifest(manifest) {
118
+ const errors = [];
119
+ const warnings = [];
120
+
121
+ if (manifest === null || typeof manifest !== 'object' || Array.isArray(manifest)) {
122
+ return { ok: false, status: 'FAIL', errors: ['MANIFEST_NOT_OBJECT'], warnings, manifestHash: null };
123
+ }
124
+
125
+ const allowedRoot = new Set(['schema', 'manifest_id', 'system_id', 'created_at', 'paths', 'default_action']);
126
+ for (const key of Object.keys(manifest)) {
127
+ if (!allowedRoot.has(key)) errors.push(`UNKNOWN_ROOT_PROPERTY:${key}`);
128
+ }
129
+
130
+ if (manifest.schema !== MANIFEST_SCHEMA) errors.push('BAD_SCHEMA');
131
+ if (typeof manifest.manifest_id !== 'string' || manifest.manifest_id.length < 8) errors.push('BAD_MANIFEST_ID');
132
+ if (typeof manifest.system_id !== 'string' || manifest.system_id.length < 1) errors.push('BAD_SYSTEM_ID');
133
+ if (typeof manifest.created_at !== 'string' || Number.isNaN(Date.parse(manifest.created_at))) errors.push('BAD_CREATED_AT');
134
+ if (manifest.default_action !== DEFAULT_ACTION) errors.push('DEFAULT_ACTION_MUST_FAIL_UNKNOWN');
135
+ if (!Array.isArray(manifest.paths) || manifest.paths.length === 0) errors.push('PATHS_REQUIRED');
136
+
137
+ const seenIds = new Set();
138
+ const coveredSurfaces = new Set();
139
+ let hasBroken = false;
140
+ let hasOutOfScope = false;
141
+
142
+ if (Array.isArray(manifest.paths)) {
143
+ for (const [index, path] of manifest.paths.entries()) {
144
+ if (path === null || typeof path !== 'object' || Array.isArray(path)) {
145
+ errors.push(`PATH_NOT_OBJECT:${index}`);
146
+ continue;
147
+ }
148
+
149
+ const allowedPath = new Set(['path_id', 'surface', 'classification', 'adapter', 'reason', 'coverage_receipt_required']);
150
+ for (const key of Object.keys(path)) {
151
+ if (!allowedPath.has(key)) errors.push(`UNKNOWN_PATH_PROPERTY:${index}:${key}`);
152
+ }
153
+
154
+ if (typeof path.path_id !== 'string' || path.path_id.length < 1) errors.push(`BAD_PATH_ID:${index}`);
155
+ else if (seenIds.has(path.path_id)) errors.push(`DUPLICATE_PATH_ID:${path.path_id}`);
156
+ else seenIds.add(path.path_id);
157
+
158
+ if (!SURFACE_SET.has(path.surface)) errors.push(`UNKNOWN_SURFACE:${path.path_id ?? index}`);
159
+ else coveredSurfaces.add(path.surface);
160
+
161
+ if (!CLASSIFICATION_SET.has(path.classification)) errors.push(`UNKNOWN_CLASSIFICATION:${path.path_id ?? index}`);
162
+ if (path.classification === 'broken' || path.classification === 'fail_closed') hasBroken = true;
163
+ if (path.classification === 'declared_out_of_scope') hasOutOfScope = true;
164
+ if (path.coverage_receipt_required !== undefined && typeof path.coverage_receipt_required !== 'boolean') {
165
+ errors.push(`BAD_COVERAGE_RECEIPT_REQUIRED:${path.path_id ?? index}`);
166
+ }
167
+ }
168
+ }
169
+
170
+ for (const surface of SURFACES) {
171
+ if (!coveredSurfaces.has(surface)) errors.push(`MISSING_SURFACE:${surface}`);
172
+ }
173
+
174
+ if (hasBroken) warnings.push('BROKEN_PATH_DECLARED');
175
+ if (hasOutOfScope) warnings.push('OUT_OF_SCOPE_PATH_DECLARED');
176
+
177
+ const manifestHash = errors.length === 0 ? sha256Hex(canonicalize(manifest)) : null;
178
+ const status = errors.length > 0 || hasBroken ? 'FAIL' : hasOutOfScope ? 'NARROW_GO' : 'PASS';
179
+ return { ok: errors.length === 0, status, errors, warnings, manifestHash };
180
+ }
181
+
182
+ export function classifyBoundaryPath(manifest, pathRef) {
183
+ const verification = verifyBoundaryManifest(manifest);
184
+ if (!verification.ok) {
185
+ return {
186
+ known: false,
187
+ classification: 'fail_closed',
188
+ fail_closed: true,
189
+ canp: 'UNKNOWN_BOUNDARY',
190
+ verdict: 'FAIL',
191
+ reason: verification.errors.includes('MANIFEST_NOT_OBJECT') ? 'MISSING_OR_INVALID_MANIFEST' : 'INVALID_MANIFEST',
192
+ manifestErrors: verification.errors
193
+ };
194
+ }
195
+
196
+ const ref = typeof pathRef === 'string' ? { path_id: pathRef } : pathRef;
197
+ if (ref === null || typeof ref !== 'object' || Array.isArray(ref)) {
198
+ return {
199
+ known: false,
200
+ classification: 'fail_closed',
201
+ fail_closed: true,
202
+ canp: 'UNKNOWN_BOUNDARY',
203
+ verdict: 'FAIL',
204
+ reason: 'BAD_PATH_REF'
205
+ };
206
+ }
207
+
208
+ const hasPathId = typeof ref.path_id === 'string' && ref.path_id.length > 0;
209
+ const hasSurface = typeof ref.surface === 'string' && ref.surface.length > 0;
210
+ let matches = [];
211
+
212
+ if (hasPathId) {
213
+ matches = manifest.paths.filter((path) => path.path_id === ref.path_id);
214
+ if (matches.length !== 1) {
215
+ return {
216
+ known: false,
217
+ classification: 'fail_closed',
218
+ fail_closed: true,
219
+ canp: 'UNKNOWN_BOUNDARY',
220
+ verdict: 'FAIL',
221
+ reason: matches.length === 0 ? 'UNCLASSIFIED_PATH' : 'AMBIGUOUS_PATH'
222
+ };
223
+ }
224
+ if (hasSurface && matches[0].surface !== ref.surface) {
225
+ return {
226
+ known: false,
227
+ classification: 'fail_closed',
228
+ fail_closed: true,
229
+ canp: 'UNKNOWN_BOUNDARY',
230
+ verdict: 'FAIL',
231
+ reason: 'AMBIGUOUS_PATH'
232
+ };
233
+ }
234
+ } else if (hasSurface) {
235
+ matches = manifest.paths.filter((path) => path.surface === ref.surface);
236
+ if (matches.length !== 1) {
237
+ return {
238
+ known: false,
239
+ classification: 'fail_closed',
240
+ fail_closed: true,
241
+ canp: 'UNKNOWN_BOUNDARY',
242
+ verdict: 'FAIL',
243
+ reason: matches.length === 0 ? 'UNCLASSIFIED_PATH' : 'AMBIGUOUS_PATH'
244
+ };
245
+ }
246
+ } else {
247
+ return {
248
+ known: false,
249
+ classification: 'fail_closed',
250
+ fail_closed: true,
251
+ canp: 'UNKNOWN_BOUNDARY',
252
+ verdict: 'FAIL',
253
+ reason: 'BAD_PATH_REF'
254
+ };
255
+ }
256
+
257
+ const [path] = matches;
258
+ const canpByClassification = {
259
+ committed: 'COMMITTED_PATH',
260
+ blocked: 'BLOCKED_PATH',
261
+ declared_out_of_scope: 'OUT_OF_SCOPE',
262
+ broken: 'BROKEN_PATH',
263
+ fail_closed: 'UNKNOWN_BOUNDARY'
264
+ };
265
+ const verdictByClassification = {
266
+ committed: 'PASS',
267
+ blocked: 'PASS',
268
+ declared_out_of_scope: 'NARROW_GO',
269
+ broken: 'FAIL',
270
+ fail_closed: 'FAIL'
271
+ };
272
+
273
+ return {
274
+ known: true,
275
+ fail_closed: path.classification === 'broken' || path.classification === 'fail_closed',
276
+ path,
277
+ classification: path.classification,
278
+ canp: canpByClassification[path.classification],
279
+ verdict: verdictByClassification[path.classification],
280
+ reason: path.reason ?? null
281
+ };
282
+ }
283
+
284
+ function scenarioDefinitions() {
285
+ return [
286
+ {
287
+ scenario: 'control never sent',
288
+ pathId: 'model_input:committed',
289
+ fact: 'control-boundary-canary',
290
+ bGotVia: 'none',
291
+ committed: false
292
+ },
293
+ {
294
+ scenario: 'honest committed crossing',
295
+ pathId: 'model_input:committed',
296
+ fact: 'honest-committed-canary',
297
+ bGotVia: 'committed_channel',
298
+ committed: true
299
+ },
300
+ {
301
+ scenario: 'scratchpad leak',
302
+ pathId: 'scratchpad:raw',
303
+ fact: 'scratchpad-leak-canary',
304
+ bGotVia: 'scratchpad',
305
+ committed: false
306
+ },
307
+ {
308
+ scenario: 'tool-output leak',
309
+ pathId: 'tool_result:raw',
310
+ fact: 'tool-output-leak-canary',
311
+ bGotVia: 'tool_result',
312
+ committed: false
313
+ },
314
+ {
315
+ scenario: 'clipboard leak',
316
+ pathId: 'clipboard:raw',
317
+ fact: 'clipboard-leak-canary',
318
+ bGotVia: 'clipboard',
319
+ committed: false
320
+ },
321
+ {
322
+ scenario: 'log leak',
323
+ pathId: 'log:raw',
324
+ fact: 'log-leak-canary',
325
+ bGotVia: 'log',
326
+ committed: false
327
+ },
328
+ {
329
+ scenario: 'file artifact leak',
330
+ pathId: 'file_write:raw',
331
+ fact: 'file-artifact-leak-canary',
332
+ bGotVia: 'file_artifact',
333
+ committed: false
334
+ },
335
+ {
336
+ scenario: 'network callback leak',
337
+ pathId: 'network:callback',
338
+ fact: 'network-callback-leak-canary',
339
+ bGotVia: 'network_callback',
340
+ committed: false
341
+ },
342
+ {
343
+ scenario: 'mitigated scratchpad route-through-channel',
344
+ pathId: 'scratchpad:committed',
345
+ fact: 'mitigated-scratchpad-canary',
346
+ bGotVia: 'scratchpad_via_committed_channel',
347
+ committed: true
348
+ },
349
+ {
350
+ scenario: 'mitigated clipboard route-through-channel',
351
+ pathId: 'clipboard:committed',
352
+ fact: 'mitigated-clipboard-canary',
353
+ bGotVia: 'clipboard_via_committed_channel',
354
+ committed: true
355
+ },
356
+ {
357
+ scenario: 'mitigated tool route-through-channel',
358
+ pathId: 'tool_result:committed',
359
+ fact: 'mitigated-tool-canary',
360
+ bGotVia: 'tool_result_via_committed_channel',
361
+ committed: true
362
+ },
363
+ {
364
+ scenario: 'unknown provider route',
365
+ pathId: 'provider_native:tool_result',
366
+ fact: 'unknown-provider-route-canary',
367
+ bGotVia: 'provider_native_tool',
368
+ committed: false
369
+ },
370
+ {
371
+ scenario: 'ambiguous tool surface route',
372
+ pathId: 'tool_result:*',
373
+ pathRef: { surface: 'tool_result' },
374
+ fact: 'ambiguous-tool-surface-canary',
375
+ bGotVia: 'tool_surface',
376
+ committed: false
377
+ },
378
+ {
379
+ scenario: 'semantic/RAG paraphrase declared out-of-scope',
380
+ pathId: 'rag_retrieve:semantic',
381
+ fact: 'semantic-rag-paraphrase-canary',
382
+ bGotVia: 'rag_paraphrase',
383
+ committed: false,
384
+ semantic: true
385
+ }
386
+ ];
387
+ }
388
+
389
+ function evaluateScenario(manifest, scenario, options) {
390
+ const pathRef = scenario.pathRef ?? scenario.pathId;
391
+ const classification = classifyBoundaryPath(manifest, pathRef);
392
+ const address = factCommitment(scenario.fact, { hmacKey: options.hmacKey, runId: options.runId, scenario: scenario.scenario });
393
+ const bHasFact = scenario.bGotVia !== 'none';
394
+ const committedSet = new Set(scenario.committed ? [address] : []);
395
+ const crossedCommittedChannel = committedSet.has(address);
396
+
397
+ let canp;
398
+ let verdict;
399
+
400
+ if (!classification.known) {
401
+ canp = 'UNKNOWN_BOUNDARY';
402
+ verdict = 'FAIL';
403
+ } else if (classification.classification === 'declared_out_of_scope') {
404
+ canp = 'OUT_OF_SCOPE';
405
+ verdict = 'NARROW_GO';
406
+ } else if (classification.classification === 'blocked') {
407
+ canp = bHasFact ? 'FALSE_ASSURANCE' : 'BLOCKED';
408
+ verdict = bHasFact ? 'FAIL' : 'PASS';
409
+ } else if (crossedCommittedChannel) {
410
+ canp = 'CROSSED';
411
+ verdict = 'PASS';
412
+ } else if (bHasFact) {
413
+ canp = 'FALSE_ASSURANCE';
414
+ verdict = 'FAIL';
415
+ } else {
416
+ canp = 'NEVER_CROSSED_COMMITTED_CHANNEL';
417
+ verdict = 'PASS';
418
+ }
419
+
420
+ return {
421
+ row: {
422
+ scenario: scenario.scenario,
423
+ pathId: scenario.pathId,
424
+ bGotVia: scenario.bGotVia,
425
+ classification: classification.classification,
426
+ failClosed: verdict === 'FAIL' || classification.fail_closed === true,
427
+ canp,
428
+ verdict,
429
+ reason: classification.reason
430
+ },
431
+ commitment: {
432
+ scenario: scenario.scenario,
433
+ fact_address: address,
434
+ path_id: scenario.pathId
435
+ }
436
+ };
437
+ }
438
+
439
+ export function runBoundarySimulation(options = {}) {
440
+ assertPlainRecord(options, 'options');
441
+ const runId = String(options.runId ?? options.run_id ?? 'boundary-sim-local');
442
+ const hmacKey = String(options.hmacKey ?? options.hmac_key ?? DEFAULT_HMAC_KEY);
443
+ const manifest = Object.prototype.hasOwnProperty.call(options, 'manifest') ? options.manifest : createBoundaryManifest({ systemId: options.systemId, createdAt: options.createdAt });
444
+ const manifestVerification = verifyBoundaryManifest(manifest);
445
+ const scenarios = options.scenarios ?? scenarioDefinitions();
446
+ const evaluated = scenarios.map((scenario) => evaluateScenario(manifest, scenario, { hmacKey, runId }));
447
+ const rows = evaluated.map((item) => item.row);
448
+ const commitments = evaluated.map((item) => item.commitment);
449
+
450
+ let status = 'PASS';
451
+ if (!manifestVerification.ok || rows.some((row) => row.verdict === 'FAIL')) status = 'FAIL';
452
+ else if (rows.some((row) => row.verdict === 'NARROW_GO') || manifestVerification.status === 'NARROW_GO') status = 'NARROW_GO';
453
+
454
+ return {
455
+ schema: 'enigma.boundary_simulation.v1',
456
+ run_id: runId,
457
+ manifest_hash: manifestVerification.manifestHash,
458
+ manifest_status: manifestVerification.status,
459
+ rows,
460
+ status,
461
+ finalStatus: status,
462
+ commitments,
463
+ honesty_text: 'This report proves exact facts about declared Enigma-instrumented paths. It does not prove provider deletion, model forgetting, semantic forgetting, model-weight deletion, or absence of uninstrumented provider-internal side channels.'
464
+ };
465
+ }
466
+
467
+ export const boundarySurfaces = SURFACES;
468
+ export const boundaryClassifications = CLASSIFICATIONS;