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,228 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ export const TENANT_POLICY_APPROVAL_SCHEMA = 'enigma.tenant_policy_approval.v1';
7
+ export const TENANT_POLICY_APPROVAL_RESULT_SCHEMA = 'enigma.tenant_policy_approval_result.v1';
8
+
9
+ const ENTERPRISE_POLICY_SCHEMA = 'enigma.enterprise_policy.v1';
10
+ const ACCEPTED_STATUSES = new Set(['approved', 'accepted', 'go', 'verified']);
11
+ const SHA256_PREFIXED_DIGEST = /^sha256:[0-9a-f]{64}$/;
12
+ const SECRET_VALUE_RE = /(?:Bearer\s+[A-Za-z0-9._~+/=-]{12,}|Basic\s+[A-Za-z0-9+/=-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|https?:\/\/[^\s/@]+:[^\s/@]+@|raw memory|private prompt|full transcript|decrypted capsule|sk-[A-Za-z0-9_-]{16,}|AKIA[0-9A-Z]{16})/iu;
13
+ const SECRET_KEY_RE = /(?:password|passwd|pwd|token|api[_-]?key|private[_-]?key|secret|raw[_-]?memory|plaintext|plain[_-]?text|prompt|completion|transcript|embedding|provider[_-]?response)/iu;
14
+
15
+ function isPlainObject(value) {
16
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
17
+ }
18
+
19
+ function nonEmptyString(value) {
20
+ return typeof value === 'string' && value.trim().length > 0;
21
+ }
22
+
23
+ function positiveInteger(value) {
24
+ return Number.isSafeInteger(value) && value > 0;
25
+ }
26
+
27
+ function isoLike(value) {
28
+ return nonEmptyString(value) && !Number.isNaN(Date.parse(value));
29
+ }
30
+
31
+ function blocker(message, path) {
32
+ return { message, path };
33
+ }
34
+
35
+ function assertNoSecrets(value, path = 'tenant_policy') {
36
+ if (typeof value === 'string') {
37
+ if (!/\.claim_boundary\[\d+\]$/.test(path) && SECRET_VALUE_RE.test(value)) throw new Error(`${path} contains secret or raw-memory-looking data`);
38
+ return;
39
+ }
40
+ if (Array.isArray(value)) {
41
+ value.forEach((item, index) => assertNoSecrets(item, `${path}[${index}]`));
42
+ return;
43
+ }
44
+ if (!isPlainObject(value)) return;
45
+ for (const [key, child] of Object.entries(value)) {
46
+ if (SECRET_KEY_RE.test(key)) throw new Error(`${path}.${key} uses a forbidden field name`);
47
+ assertNoSecrets(child, `${path}.${key}`);
48
+ }
49
+ }
50
+
51
+ function statusAccepted(value) {
52
+ return typeof value === 'string' && ACCEPTED_STATUSES.has(value.trim().toLowerCase());
53
+ }
54
+
55
+ function nonEmptyStringArray(value) {
56
+ return Array.isArray(value) && value.length > 0 && value.every(nonEmptyString);
57
+ }
58
+
59
+ function validateMetadata(metadata, blockers) {
60
+ if (!isPlainObject(metadata)) {
61
+ blockers.push(blocker('metadata is required', 'metadata'));
62
+ return;
63
+ }
64
+ for (const field of ['approval_id', 'environment', 'tenant', 'owner', 'approved_at', 'approval_ref', 'status']) {
65
+ if (!nonEmptyString(metadata[field])) blockers.push(blocker(`metadata.${field} is required`, `metadata.${field}`));
66
+ }
67
+ if (!statusAccepted(metadata.status)) blockers.push(blocker('metadata.status must be approved/accepted/go/verified', 'metadata.status'));
68
+ if (!isoLike(metadata.approved_at)) blockers.push(blocker('metadata.approved_at must be ISO time', 'metadata.approved_at'));
69
+ }
70
+
71
+ function validateEnterprisePolicy(policy, blockers) {
72
+ if (!isPlainObject(policy)) {
73
+ blockers.push(blocker('enterprise_policy object is required', 'enterprise_policy'));
74
+ return false;
75
+ }
76
+ if (policy.schema !== ENTERPRISE_POLICY_SCHEMA) blockers.push(blocker('enterprise_policy.schema must be enigma.enterprise_policy.v1', 'enterprise_policy.schema'));
77
+ for (const field of ['policy_id', 'tenant_id', 'mode', 'created_at', 'updated_at', 'policy_hash']) {
78
+ if (!nonEmptyString(policy[field])) blockers.push(blocker(`enterprise_policy.${field} is required`, `enterprise_policy.${field}`));
79
+ }
80
+ if (!SHA256_PREFIXED_DIGEST.test(String(policy.policy_hash ?? ''))) blockers.push(blocker('enterprise_policy.policy_hash must be sha256-prefixed digest', 'enterprise_policy.policy_hash'));
81
+ if (policy.default_action !== 'deny_unknown') blockers.push(blocker('enterprise_policy.default_action must be deny_unknown', 'enterprise_policy.default_action'));
82
+ if (policy.provider_native_memory !== 'cache_only') blockers.push(blocker('enterprise_policy.provider_native_memory must be cache_only', 'enterprise_policy.provider_native_memory'));
83
+ if (policy.public_proof !== 'hash_only') blockers.push(blocker('enterprise_policy.public_proof must be hash_only', 'enterprise_policy.public_proof'));
84
+ if (!positiveInteger(policy.retention_days)) blockers.push(blocker('enterprise_policy.retention_days must be positive integer', 'enterprise_policy.retention_days'));
85
+ for (const field of ['allowed_operations', 'allowed_providers', 'allowed_models', 'allowed_regions', 'allowed_purposes', 'denied_sensitivities']) {
86
+ if (!nonEmptyStringArray(policy[field])) blockers.push(blocker(`enterprise_policy.${field} must be non-empty string array`, `enterprise_policy.${field}`));
87
+ }
88
+ if (!Array.isArray(policy.legal_holds)) blockers.push(blocker('enterprise_policy.legal_holds must be an array', 'enterprise_policy.legal_holds'));
89
+ return true;
90
+ }
91
+
92
+ function validateApproval(approval, blockers) {
93
+ if (!isPlainObject(approval)) {
94
+ blockers.push(blocker('approval object is required', 'approval'));
95
+ return false;
96
+ }
97
+ for (const field of ['policy_owner', 'approver', 'approval_ref', 'approved_at', 'rollback_policy_hash', 'rollback_ref', 'status']) {
98
+ if (!nonEmptyString(approval[field])) blockers.push(blocker(`approval.${field} is required`, `approval.${field}`));
99
+ }
100
+ if (!statusAccepted(approval.status)) blockers.push(blocker('approval.status must be approved/accepted/go/verified', 'approval.status'));
101
+ if (!isoLike(approval.approved_at)) blockers.push(blocker('approval.approved_at must be ISO time', 'approval.approved_at'));
102
+ if (!SHA256_PREFIXED_DIGEST.test(String(approval.rollback_policy_hash ?? ''))) blockers.push(blocker('approval.rollback_policy_hash must be sha256-prefixed digest', 'approval.rollback_policy_hash'));
103
+ return true;
104
+ }
105
+
106
+ function validateRetentionDeletion(retention, policy, blockers) {
107
+ if (!isPlainObject(retention)) {
108
+ blockers.push(blocker('retention_deletion object is required', 'retention_deletion'));
109
+ return false;
110
+ }
111
+ for (const field of ['tombstone_receipt_ref', 'legal_hold_policy_ref', 'audit_route_ref', 'retention_policy_ref']) {
112
+ if (!nonEmptyString(retention[field])) blockers.push(blocker(`retention_deletion.${field} is required`, `retention_deletion.${field}`));
113
+ }
114
+ if (!positiveInteger(retention.retention_days)) blockers.push(blocker('retention_deletion.retention_days must be positive integer', 'retention_deletion.retention_days'));
115
+ if (isPlainObject(policy) && positiveInteger(policy.retention_days) && retention.retention_days !== policy.retention_days) blockers.push(blocker('retention_deletion.retention_days must match enterprise_policy.retention_days', 'retention_deletion.retention_days'));
116
+ if (retention.tombstone_receipt_required !== true) blockers.push(blocker('retention_deletion.tombstone_receipt_required must be true', 'retention_deletion.tombstone_receipt_required'));
117
+ if (retention.legal_hold_delete_blocks !== true) blockers.push(blocker('retention_deletion.legal_hold_delete_blocks must be true', 'retention_deletion.legal_hold_delete_blocks'));
118
+ if (retention.provider_deletion_claimed !== false) blockers.push(blocker('retention_deletion.provider_deletion_claimed must be false', 'retention_deletion.provider_deletion_claimed'));
119
+ return true;
120
+ }
121
+
122
+ function validateAuditControls(audit, blockers) {
123
+ if (!isPlainObject(audit)) {
124
+ blockers.push(blocker('audit_controls object is required', 'audit_controls'));
125
+ return false;
126
+ }
127
+ for (const field of ['gateway_decision_ref', 'siem_event_ref', 'evidence_retention_ref', 'review_ref']) {
128
+ if (!nonEmptyString(audit[field])) blockers.push(blocker(`audit_controls.${field} is required`, `audit_controls.${field}`));
129
+ }
130
+ if (audit.gateway_decision_required !== true) blockers.push(blocker('audit_controls.gateway_decision_required must be true', 'audit_controls.gateway_decision_required'));
131
+ if (audit.siem_event_required !== true) blockers.push(blocker('audit_controls.siem_event_required must be true', 'audit_controls.siem_event_required'));
132
+ if (audit.minimized_events_only !== true) blockers.push(blocker('audit_controls.minimized_events_only must be true', 'audit_controls.minimized_events_only'));
133
+ return true;
134
+ }
135
+
136
+ function validateChangeControl(change, blockers) {
137
+ if (!isPlainObject(change)) {
138
+ blockers.push(blocker('change_control object is required', 'change_control'));
139
+ return false;
140
+ }
141
+ for (const field of ['change_ticket_ref', 'canary_ref', 'rollback_ref', 'emergency_freeze_ref', 'owner']) {
142
+ if (!nonEmptyString(change[field])) blockers.push(blocker(`change_control.${field} is required`, `change_control.${field}`));
143
+ }
144
+ if (change.force_push_allowed !== false) blockers.push(blocker('change_control.force_push_allowed must be false', 'change_control.force_push_allowed'));
145
+ return true;
146
+ }
147
+
148
+ export function validateTenantPolicyApproval(packet, options = {}) {
149
+ if (!isPlainObject(packet)) throw new Error('tenant policy approval must be an object');
150
+ assertNoSecrets(packet);
151
+ const blockers = [];
152
+ if (packet.schema !== TENANT_POLICY_APPROVAL_SCHEMA) blockers.push(blocker('schema mismatch', 'schema'));
153
+ validateMetadata(packet.metadata, blockers);
154
+ const policyOk = validateEnterprisePolicy(packet.enterprise_policy, blockers);
155
+ const approvalOk = validateApproval(packet.approval, blockers);
156
+ const retentionOk = validateRetentionDeletion(packet.retention_deletion, packet.enterprise_policy, blockers);
157
+ const auditOk = validateAuditControls(packet.audit_controls, blockers);
158
+ const changeOk = validateChangeControl(packet.change_control, blockers);
159
+
160
+ const result = {
161
+ schema: TENANT_POLICY_APPROVAL_RESULT_SCHEMA,
162
+ generated_at: options.generated_at ?? options.generatedAt ?? new Date(0).toISOString(),
163
+ ok: blockers.length === 0,
164
+ status: blockers.length === 0 ? 'accepted' : 'blocked',
165
+ blockers,
166
+ checked: {
167
+ enterprise_policy: policyOk,
168
+ approval: approvalOk,
169
+ retention_deletion: retentionOk,
170
+ audit_controls: auditOk,
171
+ change_control: changeOk,
172
+ policy_hash: isPlainObject(packet.enterprise_policy) ? packet.enterprise_policy.policy_hash ?? null : null,
173
+ },
174
+ claim_boundary: [
175
+ 'Tenant policy approval validation checks declared policy approval shape only; it does not deploy policy, mutate tenant state, or prove hosted readiness.',
176
+ 'Provider-native memory must remain cache_only and provider deletion must not be claimed by tenant policy evidence.',
177
+ 'Secrets, raw memory, prompts, transcripts, provider responses, decrypted content, credentials, and private key material must remain outside tenant policy artifacts.',
178
+ ],
179
+ };
180
+ assertNoSecrets(result, 'result');
181
+ return result;
182
+ }
183
+
184
+ function parseArgs(argv = process.argv.slice(2)) {
185
+ const flags = new Map();
186
+ for (let index = 0; index < argv.length; index += 1) {
187
+ const arg = argv[index];
188
+ if (!arg.startsWith('--')) continue;
189
+ const eq = arg.indexOf('=');
190
+ if (eq !== -1) flags.set(arg.slice(2, eq), arg.slice(eq + 1));
191
+ else if (!argv[index + 1] || argv[index + 1].startsWith('--')) flags.set(arg.slice(2), true);
192
+ else {
193
+ flags.set(arg.slice(2), argv[index + 1]);
194
+ index += 1;
195
+ }
196
+ }
197
+ return flags;
198
+ }
199
+
200
+ function getFlag(flags, names) {
201
+ for (const name of names) if (flags.has(name)) return flags.get(name);
202
+ return undefined;
203
+ }
204
+
205
+ async function main() {
206
+ const flags = parseArgs();
207
+ const policyPath = getFlag(flags, ['approval', 'policy', 'in']);
208
+ if (!nonEmptyString(policyPath)) throw new Error('--approval <path> is required');
209
+ const packet = JSON.parse(await readFile(resolve(String(policyPath)), 'utf8'));
210
+ const result = validateTenantPolicyApproval(packet, { generated_at: new Date().toISOString() });
211
+ const out = getFlag(flags, ['out']);
212
+ const text = `${JSON.stringify(result, null, 2)}\n`;
213
+ if (out && out !== true) {
214
+ const outPath = resolve(String(out));
215
+ await mkdir(dirname(outPath), { recursive: true });
216
+ await writeFile(outPath, text, 'utf8');
217
+ }
218
+ process.stdout.write(text);
219
+ process.exitCode = result.ok ? 0 : 1;
220
+ }
221
+
222
+ const invokedPath = process.argv[1] ? resolve(process.argv[1]) : '';
223
+ if (invokedPath === fileURLToPath(import.meta.url)) {
224
+ main().catch((error) => {
225
+ process.stderr.write(`${error.name ?? 'Error'}: ${error.message}\n`);
226
+ process.exitCode = 1;
227
+ });
228
+ }
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import {
6
+ USAGE_AGGREGATE_SCHEMA,
7
+ USAGE_EVENT_SCHEMA,
8
+ aggregateUsageEvents,
9
+ } from '../packages/metering/src/index.js';
10
+
11
+ export const USAGE_METERING_RESULT_SCHEMA = 'enigma.usage_metering_result.v1';
12
+
13
+ const SECRET_VALUE_RE = /(?:Bearer\s+[A-Za-z0-9._~+/=-]{12,}|Basic\s+[A-Za-z0-9+/=-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|https?:\/\/[^\s/@]+:[^\s/@]+@|raw memory|private prompt|full transcript|decrypted capsule|sk-[A-Za-z0-9_-]{16,}|AKIA[0-9A-Z]{16})/iu;
14
+ const FORBIDDEN_KEY_RE = /(?:^|_)(?:raw|plaintext|plain_text|prompt|prompts|message|messages|text|content|document|documents|transcript|response|responses|provider_response|response_body|credential|credentials|api_key|secret|password|private_key|seed|mnemonic)(?:$|_)/iu;
15
+ const SAFE_METRIC_KEYS = new Set([
16
+ 'prompt_tokens',
17
+ 'completion_tokens',
18
+ 'memory_baseline_tokens',
19
+ 'memory_optimized_tokens',
20
+ 'memory_savings_tokens',
21
+ 'billable_prompt_tokens',
22
+ 'billable_completion_tokens',
23
+ 'total_prompt_tokens',
24
+ 'total_completion_tokens',
25
+ 'total_memory_baseline_tokens',
26
+ 'total_memory_optimized_tokens',
27
+ 'total_memory_savings_tokens',
28
+ ]);
29
+ const HASH_RE = /^sha256:[0-9a-f]{64}$/;
30
+
31
+ function isPlainObject(value) {
32
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
33
+ }
34
+
35
+ function blocker(message, path) {
36
+ return { message, path };
37
+ }
38
+
39
+ function assertNoSensitivePayload(value, path = 'usage_metering') {
40
+ if (typeof value === 'string') {
41
+ if (!/\.(claim_boundary\[\d+\]|product_thesis|blockers\[\d+\]\.message)$/.test(path) && SECRET_VALUE_RE.test(value)) throw new Error(`${path} contains secret-looking data`);
42
+ return;
43
+ }
44
+ if (Array.isArray(value)) {
45
+ value.forEach((item, index) => assertNoSensitivePayload(item, `${path}[${index}]`));
46
+ return;
47
+ }
48
+ if (!isPlainObject(value)) return;
49
+ for (const [key, child] of Object.entries(value)) {
50
+ const childPath = `${path}.${key}`;
51
+ if (FORBIDDEN_KEY_RE.test(key) && !SAFE_METRIC_KEYS.has(key) && !/^result\.blockers\[\d+\]\.message$/.test(childPath)) throw new Error(`${childPath} is not allowed in usage metering artifacts`);
52
+ assertNoSensitivePayload(child, childPath);
53
+ }
54
+ }
55
+
56
+ function finiteNonNegative(value) {
57
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0;
58
+ }
59
+
60
+ function validUsageEvent(event, blockers, path) {
61
+ if (!isPlainObject(event)) {
62
+ blockers.push(blocker('usage event must be an object', path));
63
+ return false;
64
+ }
65
+ if (event.schema !== USAGE_EVENT_SCHEMA) blockers.push(blocker('usage event schema mismatch', `${path}.schema`));
66
+ if (!HASH_RE.test(String(event.event_hash ?? ''))) blockers.push(blocker('usage event hash must be sha256', `${path}.event_hash`));
67
+ if (!/^uevt_[a-f0-9]{32}$/.test(String(event.event_id ?? ''))) blockers.push(blocker('usage event id must be deterministic uevt hash id', `${path}.event_id`));
68
+ const usage = event.usage;
69
+ if (!isPlainObject(usage)) blockers.push(blocker('usage event usage object is required', `${path}.usage`));
70
+ else {
71
+ for (const field of ['prompt_tokens', 'completion_tokens', 'memory_baseline_tokens', 'memory_optimized_tokens', 'memory_savings_tokens', 'billable_prompt_tokens', 'billable_completion_tokens']) {
72
+ if (!finiteNonNegative(usage[field])) blockers.push(blocker(`${path}.usage.${field} must be non-negative number`, `${path}.usage.${field}`));
73
+ }
74
+ if (finiteNonNegative(usage.memory_baseline_tokens) && finiteNonNegative(usage.memory_optimized_tokens)) {
75
+ if (usage.memory_optimized_tokens > usage.memory_baseline_tokens) blockers.push(blocker('memory_optimized_tokens exceeds baseline', `${path}.usage.memory_optimized_tokens`));
76
+ if (usage.memory_savings_tokens !== usage.memory_baseline_tokens - usage.memory_optimized_tokens) blockers.push(blocker('memory_savings_tokens must equal baseline minus optimized', `${path}.usage.memory_savings_tokens`));
77
+ if (usage.billable_prompt_tokens !== usage.memory_optimized_tokens) blockers.push(blocker('billable_prompt_tokens must equal memory_optimized_tokens', `${path}.usage.billable_prompt_tokens`));
78
+ }
79
+ }
80
+ const settlement = event.settlement_boundary;
81
+ if (!isPlainObject(settlement)) blockers.push(blocker('settlement_boundary is required', `${path}.settlement_boundary`));
82
+ else {
83
+ for (const field of ['token_roi_claim', 'provider_invoice_savings_claim', 'decentralized_inference_claim']) {
84
+ if (settlement[field] !== false) blockers.push(blocker(`${path}.settlement_boundary.${field} must be false`, `${path}.settlement_boundary.${field}`));
85
+ }
86
+ if (settlement.permissionless_access !== true) blockers.push(blocker(`${path}.settlement_boundary.permissionless_access must be true`, `${path}.settlement_boundary.permissionless_access`));
87
+ }
88
+ return true;
89
+ }
90
+
91
+ function validAggregate(aggregate, blockers, path) {
92
+ if (!isPlainObject(aggregate)) {
93
+ blockers.push(blocker('usage aggregate must be an object', path));
94
+ return false;
95
+ }
96
+ if (aggregate.schema !== USAGE_AGGREGATE_SCHEMA) blockers.push(blocker('usage aggregate schema mismatch', `${path}.schema`));
97
+ if (!HASH_RE.test(String(aggregate.aggregate_hash ?? ''))) blockers.push(blocker('usage aggregate hash must be sha256', `${path}.aggregate_hash`));
98
+ if (!/^uagg_[a-f0-9]{32}$/.test(String(aggregate.aggregate_id ?? ''))) blockers.push(blocker('usage aggregate id must be deterministic uagg hash id', `${path}.aggregate_id`));
99
+ if (!Number.isSafeInteger(aggregate.event_count) || aggregate.event_count <= 0) blockers.push(blocker('usage aggregate event_count must be positive integer', `${path}.event_count`));
100
+ if (!Array.isArray(aggregate.event_hashes) || aggregate.event_hashes.length !== aggregate.event_count || aggregate.event_hashes.some((hash) => !HASH_RE.test(String(hash)))) {
101
+ blockers.push(blocker('usage aggregate event_hashes must match event_count and contain sha256 hashes', `${path}.event_hashes`));
102
+ }
103
+ const totals = aggregate.totals;
104
+ if (!isPlainObject(totals)) blockers.push(blocker('usage aggregate totals object is required', `${path}.totals`));
105
+ else {
106
+ for (const field of ['prompt_tokens', 'completion_tokens', 'memory_baseline_tokens', 'memory_optimized_tokens', 'memory_savings_tokens', 'cost_before_memory', 'cost_after_memory', 'estimated_memory_credit']) {
107
+ if (!finiteNonNegative(totals[field])) blockers.push(blocker(`${path}.totals.${field} must be non-negative number`, `${path}.totals.${field}`));
108
+ }
109
+ if (finiteNonNegative(totals.memory_baseline_tokens) && finiteNonNegative(totals.memory_optimized_tokens)) {
110
+ if (totals.memory_optimized_tokens > totals.memory_baseline_tokens) blockers.push(blocker('aggregate optimized tokens exceed baseline', `${path}.totals.memory_optimized_tokens`));
111
+ if (totals.memory_savings_tokens !== totals.memory_baseline_tokens - totals.memory_optimized_tokens) blockers.push(blocker('aggregate memory_savings_tokens must equal baseline minus optimized', `${path}.totals.memory_savings_tokens`));
112
+ }
113
+ }
114
+ if (!Array.isArray(aggregate.claim_boundary) || aggregate.claim_boundary.length === 0) blockers.push(blocker('usage aggregate claim_boundary is required', `${path}.claim_boundary`));
115
+ return true;
116
+ }
117
+
118
+ function normalizeInput(input) {
119
+ if (Array.isArray(input)) return { events: input };
120
+ if (isPlainObject(input) && Array.isArray(input.events)) return { events: input.events, tenant_id: input.tenant_id, meter_id: input.meter_id, generated_at: input.generated_at };
121
+ return { artifact: input };
122
+ }
123
+
124
+ export function validateUsageMetering(input, options = {}) {
125
+ assertNoSensitivePayload(input);
126
+ const normalized = normalizeInput(input);
127
+ const blockers = [];
128
+ let artifact = normalized.artifact;
129
+ let mode = 'artifact';
130
+ let checkedEvents = 0;
131
+ if (normalized.events) {
132
+ mode = 'events';
133
+ normalized.events.forEach((event, index) => validUsageEvent(event, blockers, `events[${index}]`));
134
+ checkedEvents = normalized.events.length;
135
+ if (blockers.length === 0) {
136
+ try {
137
+ artifact = aggregateUsageEvents({
138
+ events: normalized.events,
139
+ tenant_id: normalized.tenant_id,
140
+ meter_id: normalized.meter_id,
141
+ generated_at: normalized.generated_at,
142
+ });
143
+ } catch (error) {
144
+ blockers.push(blocker(error.message, 'events'));
145
+ }
146
+ }
147
+ }
148
+ if (artifact?.schema === USAGE_EVENT_SCHEMA) {
149
+ validUsageEvent(artifact, blockers, 'artifact');
150
+ checkedEvents = Math.max(checkedEvents, 1);
151
+ } else if (artifact?.schema === USAGE_AGGREGATE_SCHEMA) {
152
+ validAggregate(artifact, blockers, 'artifact');
153
+ } else if (!normalized.events) {
154
+ blockers.push(blocker('artifact must be usage event, usage aggregate, or events array', 'artifact.schema'));
155
+ }
156
+ const result = {
157
+ schema: USAGE_METERING_RESULT_SCHEMA,
158
+ generated_at: options.generated_at ?? options.generatedAt ?? new Date(0).toISOString(),
159
+ ok: blockers.length === 0,
160
+ status: blockers.length === 0 ? 'accepted' : 'blocked',
161
+ mode,
162
+ blockers,
163
+ checked: {
164
+ events: checkedEvents,
165
+ aggregate_schema: artifact?.schema === USAGE_AGGREGATE_SCHEMA ? artifact.schema : null,
166
+ event_schema: artifact?.schema === USAGE_EVENT_SCHEMA ? artifact.schema : null,
167
+ memory_savings_tokens: artifact?.usage?.memory_savings_tokens ?? artifact?.totals?.memory_savings_tokens ?? null,
168
+ event_count: artifact?.event_count ?? (artifact?.schema === USAGE_EVENT_SCHEMA ? 1 : 0),
169
+ },
170
+ claim_boundary: [
171
+ 'Usage metering validation checks content-minimized Enigma usage math only; it is not a provider invoice guarantee.',
172
+ 'A pass result does not claim token ROI, token profit, decentralized inference, provider deletion, model forgetting, or compliance status.',
173
+ 'Raw prompts, completions, provider responses, transcripts, decrypted memory, credentials, keys, and seed phrases are forbidden in usage metering artifacts.',
174
+ ],
175
+ };
176
+ assertNoSensitivePayload(result, 'result');
177
+ return result;
178
+ }
179
+
180
+ function parseArgs(argv = process.argv.slice(2)) {
181
+ const flags = new Map();
182
+ for (let index = 0; index < argv.length; index += 1) {
183
+ const arg = argv[index];
184
+ if (!arg.startsWith('--')) continue;
185
+ const eq = arg.indexOf('=');
186
+ if (eq !== -1) flags.set(arg.slice(2, eq), arg.slice(eq + 1));
187
+ else if (!argv[index + 1] || argv[index + 1].startsWith('--')) flags.set(arg.slice(2), true);
188
+ else {
189
+ flags.set(arg.slice(2), argv[index + 1]);
190
+ index += 1;
191
+ }
192
+ }
193
+ return flags;
194
+ }
195
+
196
+ function getFlag(flags, names) {
197
+ for (const name of names) if (flags.has(name)) return flags.get(name);
198
+ return undefined;
199
+ }
200
+
201
+ async function main() {
202
+ const flags = parseArgs();
203
+ const meteringPath = getFlag(flags, ['metering', 'usage', 'in']);
204
+ if (typeof meteringPath !== 'string' || meteringPath.trim() === '') throw new Error('--metering <path> is required');
205
+ const input = JSON.parse(await readFile(resolve(meteringPath), 'utf8'));
206
+ const result = validateUsageMetering(input, { generated_at: new Date().toISOString() });
207
+ const out = getFlag(flags, ['out']);
208
+ const text = `${JSON.stringify(result, null, 2)}\n`;
209
+ if (out && out !== true) {
210
+ const outPath = resolve(String(out));
211
+ await mkdir(dirname(outPath), { recursive: true });
212
+ await writeFile(outPath, text, 'utf8');
213
+ }
214
+ process.stdout.write(text);
215
+ process.exitCode = result.ok ? 0 : 1;
216
+ }
217
+
218
+ const invokedPath = process.argv[1] ? resolve(process.argv[1]) : '';
219
+ if (invokedPath === fileURLToPath(import.meta.url)) {
220
+ main().catch((error) => {
221
+ process.stderr.write(`${error.name ?? 'Error'}: ${error.message}\n`);
222
+ process.exitCode = 1;
223
+ });
224
+ }
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ export const WHITEPAPER_CLAIMS_RESULT_SCHEMA = 'enigma.whitepaper_claims_result.v1';
7
+
8
+ const REQUIRED_HEADINGS = Object.freeze([
9
+ '# Enigma Memory technical whitepaper',
10
+ '## Abstract',
11
+ '## 2. System model',
12
+ '## 3. Commitment and receipt chain',
13
+ '## 4. Context selection and optimization',
14
+ '## 5. How Enigma differs from adjacent systems',
15
+ '### 5.6 Memory-layer evaluation framework',
16
+ '## 6. Privacy and leakage model',
17
+ '## 7. Production readiness boundary',
18
+ '## 8. Claim boundary',
19
+ ]);
20
+
21
+ const REQUIRED_TERMS = Object.freeze([
22
+ 'provider-neutral memory custody',
23
+ 'local/BYOC',
24
+ 'active_set_root',
25
+ 'T_{base}',
26
+ 'T_{opt}',
27
+ 'D_E(X)',
28
+ 'RawMemory \\notin PublicEvidence',
29
+ 'hosted_live_ready',
30
+ 'npm run memory:benchmark',
31
+ ]);
32
+
33
+ const ABSOLUTE_CLAIM_RE = /(?:\$\s*100\s*billion|100\s*billion|best\s+in\s+the\s+world|guaranteed|guarantee|universal\s+(?:invoice\s+)?savings|provider[-\s]?side\s+deletion|model\s+forgetting|token\s+ROI|compliance\s+certification|tamper-proof|live\s+hosted\s+backend\s+readiness)/iu;
34
+ const DENY_CONTEXT_RE = /(?:does\s+\W*not\s+\W*claim|must\s+\W*not\s+\W*claim|must\s+not\s+infer|not\s+a|not\s+provider|not\s+hosted|not\s+ready|without\s+separate\s+evidence|before\s+production\s+dependencies|is\s+not\s+a|should\s+not)/iu;
35
+ const SECRET_RE = /(?:Bearer\s+[A-Za-z0-9._~+/=-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|sk-[A-Za-z0-9_-]{16,}|https?:\/\/[^\s/@]+:[^\s/@]+@)/iu;
36
+ const LOCAL_PATH_RE = /(?:[A-Z]:\\Users\\|\/Users\/|\/home\/)/u;
37
+
38
+ function countRegex(text, regex) {
39
+ return [...text.matchAll(regex)].length;
40
+ }
41
+
42
+ function lineNumberedFindings(text, regex, allowedContext) {
43
+ const findings = [];
44
+ const lines = text.split(/\r?\n/u);
45
+ let denyBlock = false;
46
+ for (let index = 0; index < lines.length; index += 1) {
47
+ const line = lines[index];
48
+ const normalizedLine = line.replace(/[*_`]/gu, '');
49
+ const normalizedWindow = [lines[index - 2] ?? '', lines[index - 1] ?? '', line]
50
+ .join(' ')
51
+ .replace(/[*_`]/gu, '');
52
+ if (/^##\s+/u.test(line) && !/claim boundary/iu.test(line)) denyBlock = false;
53
+ if (allowedContext?.test(normalizedWindow)) denyBlock = true;
54
+ if (!regex.test(line)) continue;
55
+ if (allowedContext?.test(normalizedLine) || allowedContext?.test(normalizedWindow) || denyBlock) continue;
56
+ findings.push({ line: index + 1, text: line.trim().slice(0, 160) });
57
+ }
58
+ return findings;
59
+ }
60
+
61
+ export function validateWhitepaperClaims(markdown, options = {}) {
62
+ if (typeof markdown !== 'string' || markdown.trim().length === 0) throw new Error('whitepaper markdown is required');
63
+ const blockers = [];
64
+ const warnings = [];
65
+ const headingMissing = REQUIRED_HEADINGS.filter((heading) => !markdown.includes(heading));
66
+ const termMissing = REQUIRED_TERMS.filter((term) => !markdown.includes(term));
67
+ for (const heading of headingMissing) blockers.push(`missing heading: ${heading}`);
68
+ for (const term of termMissing) blockers.push(`missing required technical term: ${term}`);
69
+
70
+ const equationBlockCount = countRegex(markdown, /^\$\$/gmu) / 2;
71
+ const mermaidCount = countRegex(markdown, /```mermaid/gmu);
72
+ const mathSymbolCount = countRegex(markdown, /(?:T_\{base\}|T_\{opt\}|\Delta_\{|D_E\(X\)|MerkleSetRoot|PublicEvidence|RawMemory)/gu);
73
+ if (equationBlockCount < 10) blockers.push(`expected at least 10 displayed equation blocks; found ${equationBlockCount}`);
74
+ if (mermaidCount < 4) blockers.push(`expected at least 4 Mermaid diagrams; found ${mermaidCount}`);
75
+ if (mathSymbolCount < 8) blockers.push(`expected at least 8 math/evaluation symbols; found ${mathSymbolCount}`);
76
+
77
+ const absoluteFindings = lineNumberedFindings(markdown, ABSOLUTE_CLAIM_RE, DENY_CONTEXT_RE);
78
+ for (const finding of absoluteFindings) blockers.push(`unsupported absolute claim on line ${finding.line}: ${finding.text}`);
79
+ const secretFindings = lineNumberedFindings(markdown, SECRET_RE);
80
+ for (const finding of secretFindings) blockers.push(`secret-looking content on line ${finding.line}`);
81
+ const pathFindings = lineNumberedFindings(markdown, LOCAL_PATH_RE);
82
+ for (const finding of pathFindings) blockers.push(`local path content on line ${finding.line}`);
83
+
84
+ if (!/This is an evaluation framework, not a theorem of universal superiority\./u.test(markdown)) blockers.push('missing explicit evaluation-framework claim boundary');
85
+ if (!/This is deliberately not a provider invoice guarantee\./u.test(markdown)) blockers.push('missing provider-invoice savings boundary');
86
+ if (!/A hosted deployment is not ready because code exists\./u.test(markdown)) blockers.push('missing hosted readiness boundary');
87
+ if (!/Raw memory is excluded:/u.test(markdown)) blockers.push('missing raw-memory public evidence exclusion');
88
+ if (/better than anything else out there/iu.test(markdown)) warnings.push('marketing superlative phrase should stay out of technical whitepaper');
89
+
90
+ return {
91
+ schema: WHITEPAPER_CLAIMS_RESULT_SCHEMA,
92
+ generated_at: options.generated_at ?? options.generatedAt ?? new Date(0).toISOString(),
93
+ ok: blockers.length === 0,
94
+ status: blockers.length === 0 ? 'accepted' : 'blocked',
95
+ path: options.path ?? null,
96
+ counts: {
97
+ headings_required: REQUIRED_HEADINGS.length,
98
+ headings_missing: headingMissing.length,
99
+ required_terms: REQUIRED_TERMS.length,
100
+ required_terms_missing: termMissing.length,
101
+ displayed_equation_blocks: equationBlockCount,
102
+ mermaid_diagrams: mermaidCount,
103
+ math_symbol_mentions: mathSymbolCount,
104
+ unsupported_absolute_claims: absoluteFindings.length,
105
+ secret_findings: secretFindings.length,
106
+ local_path_findings: pathFindings.length,
107
+ },
108
+ warnings,
109
+ blockers,
110
+ claim_boundary: [
111
+ 'This validator checks that the whitepaper contains math, diagrams, and explicit claim boundaries; it does not prove market leadership or $100B value.',
112
+ 'Passing validation means the document is evidence-bounded and structurally complete, not that hosted infrastructure is live.',
113
+ ],
114
+ };
115
+ }
116
+
117
+ function parseArgs(argv = process.argv.slice(2)) {
118
+ const out = { file: 'docs/enigma-memory-technical-whitepaper.md', out: null, help: false };
119
+ for (let index = 0; index < argv.length; index += 1) {
120
+ const token = argv[index];
121
+ if (token === '--help' || token === '-h') {
122
+ out.help = true;
123
+ continue;
124
+ }
125
+ const readValue = () => {
126
+ const value = argv[index + 1];
127
+ if (typeof value !== 'string' || value.length === 0 || value.startsWith('--')) throw new Error(`${token} requires a value`);
128
+ index += 1;
129
+ return value;
130
+ };
131
+ if (token === '--file') out.file = readValue();
132
+ else if (token === '--out') out.out = readValue();
133
+ else throw new Error(`unknown option ${token}`);
134
+ }
135
+ return out;
136
+ }
137
+
138
+ function usage() {
139
+ return 'Usage: node scripts/validate-whitepaper-claims.mjs [--file docs/enigma-memory-technical-whitepaper.md] [--out <file>]\n\nValidates math/diagram coverage and claim boundaries for the Enigma Memory technical whitepaper.\n';
140
+ }
141
+
142
+ async function runCli(argv = process.argv.slice(2)) {
143
+ const args = parseArgs(argv);
144
+ if (args.help) return { text: usage(), code: 0 };
145
+ const file = resolve(args.file);
146
+ const markdown = await readFile(file, 'utf8');
147
+ const result = validateWhitepaperClaims(markdown, { path: args.file, generated_at: new Date().toISOString() });
148
+ const json = `${JSON.stringify(result, null, 2)}\n`;
149
+ if (args.out) {
150
+ const outPath = resolve(args.out);
151
+ await mkdir(dirname(outPath), { recursive: true });
152
+ await writeFile(outPath, json, 'utf8');
153
+ }
154
+ return { text: json, code: result.ok ? 0 : 1 };
155
+ }
156
+
157
+ if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
158
+ try {
159
+ const { text, code } = await runCli();
160
+ process.stdout.write(text);
161
+ process.exitCode = code;
162
+ } catch (error) {
163
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
164
+ process.exitCode = 2;
165
+ }
166
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.enigma.ai/boundary-manifest-v1.schema.json",
4
+ "title": "Enigma Boundary Manifest v1",
5
+ "type": "object",
6
+ "required": ["schema", "manifest_id", "system_id", "created_at", "paths", "default_action"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "schema": { "const": "enigma.boundary_manifest.v1" },
10
+ "manifest_id": { "type": "string", "minLength": 8 },
11
+ "system_id": { "type": "string", "minLength": 1 },
12
+ "created_at": { "type": "string", "format": "date-time" },
13
+ "default_action": { "const": "fail_unknown" },
14
+ "paths": {
15
+ "type": "array",
16
+ "minItems": 1,
17
+ "items": {
18
+ "type": "object",
19
+ "required": ["path_id", "surface", "classification"],
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "path_id": { "type": "string", "minLength": 1 },
23
+ "surface": {
24
+ "type": "string",
25
+ "enum": ["model_input", "model_output", "tool_args", "tool_result", "scratchpad", "memory_write", "memory_read", "rag_ingest", "rag_retrieve", "file_write", "log", "telemetry", "browser_dom", "mcp_resource", "network", "inter_agent", "cache", "human_approval"]
26
+ },
27
+ "classification": { "type": "string", "enum": ["committed", "blocked", "declared_out_of_scope", "broken"] },
28
+ "adapter": { "type": "string" },
29
+ "reason": { "type": "string" },
30
+ "coverage_receipt_required": { "type": "boolean" }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ }