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,112 @@
1
+ #!/usr/bin/env node
2
+ import { writeFile, mkdir } from 'node:fs/promises';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { dirname } from 'node:path';
5
+ import { applyCloudflareSecretEnvFile } from './cloudflare-secret-env.mjs';
6
+
7
+ export const CLOUDFLARE_CREDENTIALS_RESULT_SCHEMA = 'enigma.cloudflare_credentials_result.v1';
8
+
9
+ const REQUIRED_KEYS = Object.freeze(['CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNT_ID']);
10
+ const SECRET_OUTPUT_RE = /(?:Bearer\s+[A-Za-z0-9._~+/=-]{12,}|Basic\s+[A-Za-z0-9+/=-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|sk-[A-Za-z0-9_-]{16,}|https?:\/\/[^\s/@]+:[^\s/@]+@|AKIA[0-9A-Z]{16})/iu;
11
+
12
+ function parseArgs(argv = process.argv.slice(2)) {
13
+ const out = { envFile: null, out: null, help: false };
14
+ for (let index = 0; index < argv.length; index += 1) {
15
+ const token = argv[index];
16
+ const readValue = () => {
17
+ const value = argv[index + 1];
18
+ if (typeof value !== 'string' || value.length === 0 || value.startsWith('--')) throw new Error(`${token} requires a value`);
19
+ index += 1;
20
+ return value;
21
+ };
22
+ if (token === '--cloudflare-env-file') out.envFile = readValue();
23
+ else if (typeof token === 'string' && token.startsWith('--cloudflare-env-file=')) out.envFile = token.slice('--cloudflare-env-file='.length);
24
+ else if (token === '--out') out.out = readValue();
25
+ else if (token === '--help' || token === '-h') out.help = true;
26
+ else throw new Error(`Unknown Cloudflare credential validator option: ${token}`);
27
+ }
28
+ return out;
29
+ }
30
+
31
+ function usage() {
32
+ return 'Usage: node scripts/validate-cloudflare-credentials.mjs [--cloudflare-env-file <file>] [--out <file>]\n\nValidates Cloudflare credential presence without printing token values, account ids, or local paths.\n';
33
+ }
34
+
35
+ function assertPublicSafe(result) {
36
+ const text = JSON.stringify(result);
37
+ if (SECRET_OUTPUT_RE.test(text)) throw new Error('Cloudflare credential result contains secret-looking material');
38
+ if (/[A-Za-z]:[\\/]/u.test(text)) throw new Error('Cloudflare credential result contains a local path');
39
+ return true;
40
+ }
41
+
42
+ export async function validateCloudflareCredentials(options = {}) {
43
+ let loaded;
44
+ try {
45
+ loaded = await applyCloudflareSecretEnvFile(options.env ?? process.env, {
46
+ path: options.envFile ?? null,
47
+ includePath: false,
48
+ });
49
+ } catch (error) {
50
+ const result = {
51
+ schema: CLOUDFLARE_CREDENTIALS_RESULT_SCHEMA,
52
+ ok: false,
53
+ credentials_present: false,
54
+ source_loaded: false,
55
+ present_keys: [],
56
+ loaded_key_count: 0,
57
+ missing_keys: REQUIRED_KEYS,
58
+ blockers: ['Cloudflare secret env file could not be read or parsed'],
59
+ token_value_printed: false,
60
+ account_id_printed: false,
61
+ claim_boundary: [
62
+ 'This validator checks credential presence only; it does not verify Cloudflare permissions or deploy resources.',
63
+ 'Credential values, account ids, env file paths, and contact data are intentionally omitted from output.',
64
+ ],
65
+ };
66
+ assertPublicSafe(result);
67
+ return result;
68
+ }
69
+ const present = new Set(loaded.present_keys ?? []);
70
+ const missing = REQUIRED_KEYS.filter((key) => !present.has(key));
71
+ const result = {
72
+ schema: CLOUDFLARE_CREDENTIALS_RESULT_SCHEMA,
73
+ ok: missing.length === 0,
74
+ credentials_present: missing.length === 0,
75
+ source_loaded: loaded.source !== null,
76
+ present_keys: REQUIRED_KEYS.filter((key) => present.has(key)),
77
+ loaded_key_count: Array.isArray(loaded.loaded_keys) ? loaded.loaded_keys.length : 0,
78
+ missing_keys: missing,
79
+ blockers: missing.map((key) => `${key} absent from current environment`),
80
+ token_value_printed: false,
81
+ account_id_printed: false,
82
+ claim_boundary: [
83
+ 'This validator checks credential presence only; it does not verify Cloudflare permissions or deploy resources.',
84
+ 'Credential values, account ids, env file paths, and contact data are intentionally omitted from output.',
85
+ ],
86
+ };
87
+ assertPublicSafe(result);
88
+ return result;
89
+ }
90
+
91
+ export async function main(argv = process.argv.slice(2), options = {}) {
92
+ const args = parseArgs(argv);
93
+ if (args.help) return { text: usage(), status: 0 };
94
+ const result = await validateCloudflareCredentials({ ...options, envFile: args.envFile });
95
+ const json = `${JSON.stringify(result, null, 2)}\n`;
96
+ if (SECRET_OUTPUT_RE.test(json)) throw new Error('Cloudflare credential validator output appears to contain a secret');
97
+ if (args.out) {
98
+ await mkdir(dirname(args.out), { recursive: true });
99
+ await writeFile(args.out, json, 'utf8');
100
+ }
101
+ return { text: json, status: result.ok ? 0 : 1 };
102
+ }
103
+
104
+ if (fileURLToPath(import.meta.url) === process.argv[1]) {
105
+ main().then(({ text, status }) => {
106
+ process.stdout.write(text);
107
+ process.exitCode = status;
108
+ }).catch((error) => {
109
+ process.stdout.write(`${JSON.stringify({ schema: CLOUDFLARE_CREDENTIALS_RESULT_SCHEMA, ok: false, credentials_present: false, blockers: [error.message], token_value_printed: false, account_id_printed: false }, null, 2)}\n`);
110
+ process.exitCode = 1;
111
+ });
112
+ }
@@ -0,0 +1,179 @@
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 CLOUDFLARE_WORKER_INSPECTION_RESULT_SCHEMA = 'enigma.cloudflare_worker_inspection_result.v1';
7
+
8
+ 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/@]+@|sk-[A-Za-z0-9_-]{16,}|AKIA[0-9A-Z]{16}|cf-[A-Za-z0-9_-]{12,}|raw memory|private prompt|full transcript|decrypted capsule)/iu;
9
+ const ACCOUNT_ID_RE = /\b[0-9a-f]{32}\b/iu;
10
+ const LOCAL_PATH_RE = /(?:[A-Z]:\\Users\\[^\r\n"']+|[A-Z]:\\tmp\\[^\r\n"']+|\/Users\/[^\r\n"']+|\/home\/[^\r\n"']+|\/tmp\/[^\r\n"']+|\/private\/tmp\/[^\r\n"']+|\/var\/folders\/[^\r\n"']+)/iu;
11
+ const FORBIDDEN_KEY_RE = /(?:password|passwd|pwd|api[_-]?key|private[_-]?key|secret|raw[_-]?memory|plaintext|plain[_-]?text|prompt|completion|transcript|provider[_-]?response|cookie|session)/iu;
12
+ const SAFE_KEY_RE = /^(?:tokenPrinted|token_printed|requiresToken|tokenScope|claimBoundary)$/u;
13
+
14
+ function isPlainObject(value) {
15
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
16
+ }
17
+
18
+ function blocker(message, path) {
19
+ return { message, path };
20
+ }
21
+
22
+ function assertPublicSafe(value, path = 'worker_inspection') {
23
+ if (typeof value === 'string') {
24
+ if (SECRET_VALUE_RE.test(value) || ACCOUNT_ID_RE.test(value) || LOCAL_PATH_RE.test(value)) throw new Error(`${path} contains non-public diagnostic material`);
25
+ return;
26
+ }
27
+ if (Array.isArray(value)) {
28
+ value.forEach((item, index) => assertPublicSafe(item, `${path}[${index}]`));
29
+ return;
30
+ }
31
+ if (!isPlainObject(value)) return;
32
+ for (const [key, child] of Object.entries(value)) {
33
+ const childPath = `${path}.${key}`;
34
+ if (FORBIDDEN_KEY_RE.test(key) && !SAFE_KEY_RE.test(key)) throw new Error(`${childPath} is not allowed in Worker inspection evidence`);
35
+ assertPublicSafe(child, childPath);
36
+ }
37
+ }
38
+
39
+ function nonEmptyString(value) {
40
+ return typeof value === 'string' && value.trim().length > 0;
41
+ }
42
+
43
+ function numericStatus(value) {
44
+ return Number.isSafeInteger(value) && value >= 100 && value <= 599;
45
+ }
46
+
47
+ function cloudflareErrorCode(evidence) {
48
+ const errors = evidence?.response?.payload?.errors;
49
+ if (!Array.isArray(errors) || errors.length === 0) return null;
50
+ const code = errors[0]?.code;
51
+ return Number.isSafeInteger(code) ? code : null;
52
+ }
53
+
54
+ export function validateCloudflareWorkerInspection(evidence, options = {}) {
55
+ if (!isPlainObject(evidence)) throw new Error('Cloudflare Worker inspection evidence must be an object');
56
+ assertPublicSafe(evidence);
57
+ const blockers = [];
58
+ const permissionBlockers = [];
59
+
60
+ if (evidence.schema !== 'enigma.cloudflare_ops.v1') blockers.push(blocker('schema must be enigma.cloudflare_ops.v1', 'schema'));
61
+ if (evidence.operation !== 'workers.inspect-probe') blockers.push(blocker('operation must be workers.inspect-probe', 'operation'));
62
+ if (evidence.mutates_cloudflare !== false) blockers.push(blocker('mutates_cloudflare must be false', 'mutates_cloudflare'));
63
+ if (evidence.execute !== true) blockers.push(blocker('execute must be true for an observed API inspection', 'execute'));
64
+ if (evidence.tokenPrinted !== false) blockers.push(blocker('tokenPrinted must be false', 'tokenPrinted'));
65
+ if (!nonEmptyString(evidence.service_name)) blockers.push(blocker('service_name is required', 'service_name'));
66
+ if (typeof evidence.service_observed !== 'boolean') blockers.push(blocker('service_observed must be boolean', 'service_observed'));
67
+ if (!numericStatus(evidence.status)) blockers.push(blocker('status must be HTTP status integer', 'status'));
68
+ if (!isPlainObject(evidence.plan)) blockers.push(blocker('plan object is required', 'plan'));
69
+ else {
70
+ if (evidence.plan.operation !== 'workers.service') blockers.push(blocker('plan.operation must be workers.service', 'plan.operation'));
71
+ if (evidence.plan.method !== 'GET') blockers.push(blocker('plan.method must be GET', 'plan.method'));
72
+ if (evidence.plan.requiresToken !== true) blockers.push(blocker('plan.requiresToken must be true', 'plan.requiresToken'));
73
+ if (evidence.plan.tokenPrinted !== false) blockers.push(blocker('plan.tokenPrinted must be false', 'plan.tokenPrinted'));
74
+ if (evidence.plan.tokenScope !== 'account') blockers.push(blocker('plan.tokenScope must be account', 'plan.tokenScope'));
75
+ if (!nonEmptyString(evidence.plan.url) || !String(evidence.plan.url).includes('/accounts/<account-id>/workers/services/')) blockers.push(blocker('plan.url must be account-redacted Worker service URL', 'plan.url'));
76
+ }
77
+ if (!isPlainObject(evidence.response)) blockers.push(blocker('response object is required', 'response'));
78
+ else if (!numericStatus(evidence.response.status) || evidence.response.status !== evidence.status) blockers.push(blocker('response.status must match status', 'response.status'));
79
+
80
+ const code = cloudflareErrorCode(evidence);
81
+ const visibleServiceReady = evidence.ok === true && evidence.status >= 200 && evidence.status < 300 && evidence.service_observed === true && Array.isArray(evidence.blockers) && evidence.blockers.length === 0;
82
+ const missingServicePermissionReady = evidence.ok === false && evidence.status === 404 && code === 10090 && evidence.service_observed === false;
83
+ const workerPermissionReady = visibleServiceReady || missingServicePermissionReady;
84
+ if (evidence.ok === true && !visibleServiceReady) blockers.push(blocker('ok:true requires 2xx status, service_observed:true, and zero blockers', 'ok'));
85
+ if (evidence.ok === false) {
86
+ if (!Array.isArray(evidence.blockers) || evidence.blockers.length === 0) blockers.push(blocker('blocked inspection must include blockers', 'blockers'));
87
+ if (evidence.status === 403 || code === 10000) permissionBlockers.push('Cloudflare Worker service visibility is blocked by token/account permission');
88
+ else if (!missingServicePermissionReady) permissionBlockers.push('Cloudflare Worker service visibility is not ready');
89
+ }
90
+ if (visibleServiceReady && code !== null) blockers.push(blocker('ready inspection must not include Cloudflare error codes', 'response.payload.errors'));
91
+
92
+ const result = {
93
+ schema: CLOUDFLARE_WORKER_INSPECTION_RESULT_SCHEMA,
94
+ generated_at: options.generated_at ?? options.generatedAt ?? new Date(0).toISOString(),
95
+ ok: blockers.length === 0,
96
+ status: blockers.length === 0 ? 'accepted' : 'blocked',
97
+ worker_permission_ready: blockers.length === 0 && workerPermissionReady,
98
+ service_observed: evidence.service_observed === true,
99
+ service_missing: missingServicePermissionReady,
100
+ service_name: nonEmptyString(evidence.service_name) ? evidence.service_name : null,
101
+ observed_status: numericStatus(evidence.status) ? evidence.status : null,
102
+ cloudflare_error_code: code,
103
+ permission_blockers: blockers.length === 0 ? permissionBlockers : [],
104
+ blockers,
105
+ checked: {
106
+ operation: evidence.operation ?? null,
107
+ mutates_cloudflare: evidence.mutates_cloudflare ?? null,
108
+ token_printed: evidence.tokenPrinted ?? null,
109
+ account_id_redacted: typeof evidence.plan?.url === 'string' && evidence.plan.url.includes('/accounts/<account-id>/'),
110
+ local_paths_redacted: true,
111
+ },
112
+ claim_boundary: [
113
+ 'This validator checks public-safe Cloudflare Worker inspection evidence only; it never deploys a Worker or changes Cloudflare state.',
114
+ 'worker_permission_ready:true means the account-scoped Worker service endpoint was visible; it does not prove the hosted relay/gateway infrastructure is live.',
115
+ 'A redacted 403/code-10000 result remains a token/account permission blocker; a redacted 404/code-10090 result means permission is sufficient but the probe Worker still needs deployment if that evidence is required.',
116
+ ],
117
+ };
118
+
119
+ assertPublicSafe(result, 'result');
120
+ return result;
121
+ }
122
+
123
+ function redactDiagnosticMessage(value) {
124
+ return String(value)
125
+ .replace(SECRET_VALUE_RE, '[redacted]')
126
+ .replace(ACCOUNT_ID_RE, '<hex32>')
127
+ .replace(LOCAL_PATH_RE, '<local-path>');
128
+ }
129
+
130
+ function parseArgs(argv = process.argv.slice(2)) {
131
+ const out = { evidence: null, out: null, help: false };
132
+ for (let index = 0; index < argv.length; index += 1) {
133
+ const token = argv[index];
134
+ if (token === '--help' || token === '-h') {
135
+ out.help = true;
136
+ continue;
137
+ }
138
+ const readValue = () => {
139
+ const value = argv[index + 1];
140
+ if (typeof value !== 'string' || value.length === 0 || value.startsWith('--')) throw new Error(`${token} requires a value`);
141
+ index += 1;
142
+ return value;
143
+ };
144
+ if (token === '--evidence') out.evidence = readValue();
145
+ else if (token === '--out') out.out = readValue();
146
+ else throw new Error(`unknown option ${token}`);
147
+ }
148
+ return out;
149
+ }
150
+
151
+ function usage() {
152
+ return 'Usage: node scripts/validate-cloudflare-worker-inspect.mjs --evidence <worker-inspect.json> [--out <file>]\n\nValidates public-safe output from `npm run cloudflare:ops -- workers inspect-probe --out <file>`. A redacted 403/code-10000 packet is accepted permission-blocked evidence; a redacted 404/code-10090 packet is accepted permission-ready missing-service evidence.\n';
153
+ }
154
+
155
+ async function runCli(argv = process.argv.slice(2)) {
156
+ const args = parseArgs(argv);
157
+ if (args.help) return { text: usage(), code: 0 };
158
+ if (!args.evidence) throw new Error('--evidence is required');
159
+ const evidence = JSON.parse(await readFile(resolve(args.evidence), 'utf8'));
160
+ const result = validateCloudflareWorkerInspection(evidence, { generated_at: new Date().toISOString() });
161
+ const json = `${JSON.stringify(result, null, 2)}\n`;
162
+ if (args.out) {
163
+ const outPath = resolve(args.out);
164
+ await mkdir(dirname(outPath), { recursive: true });
165
+ await writeFile(outPath, json, 'utf8');
166
+ }
167
+ return { text: json, code: result.ok ? 0 : 1 };
168
+ }
169
+
170
+ if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
171
+ try {
172
+ const { text, code } = await runCli();
173
+ process.stdout.write(text);
174
+ process.exitCode = code;
175
+ } catch (error) {
176
+ process.stderr.write(`${redactDiagnosticMessage(error instanceof Error ? error.message : String(error))}\n`);
177
+ process.exitCode = 2;
178
+ }
179
+ }
@@ -0,0 +1,248 @@
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 DOMAIN_TLS_EVIDENCE_SCHEMA = 'enigma.domain_tls_evidence.v1';
7
+ export const DOMAIN_TLS_RESULT_SCHEMA = 'enigma.domain_tls_result.v1';
8
+
9
+ const ACCEPTED_STATUS = new Set(['active', 'verified', 'observed', 'go']);
10
+ const REQUIRED_SECURITY_HEADERS = Object.freeze([
11
+ 'x-content-type-options',
12
+ 'x-frame-options',
13
+ 'referrer-policy',
14
+ 'permissions-policy',
15
+ 'content-security-policy',
16
+ ]);
17
+ 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;
18
+ const FORBIDDEN_KEY_RE = /(?:password|passwd|pwd|token|api[_-]?key|private[_-]?key|secret|raw[_-]?memory|plaintext|plain[_-]?text|prompt|completion|transcript|provider[_-]?response|cookie|session)/iu;
19
+ const SAFE_FIELD_NAMES = new Set(['token_roi_claim', 'provider_invoice_savings_claim', 'credential_claim', 'security_headers']);
20
+
21
+ function isPlainObject(value) {
22
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
23
+ }
24
+
25
+ function nonEmptyString(value) {
26
+ return typeof value === 'string' && value.trim().length > 0;
27
+ }
28
+
29
+ function isoLike(value) {
30
+ return nonEmptyString(value) && !Number.isNaN(Date.parse(value));
31
+ }
32
+
33
+ function blocker(message, path) {
34
+ return { message, path };
35
+ }
36
+
37
+ function assertNoSensitivePayload(value, path = 'domain_tls') {
38
+ if (typeof value === 'string') {
39
+ if (!/\.(claim_boundary\[\d+\]|blockers\[\d+\]\.message)$/.test(path) && SECRET_VALUE_RE.test(value)) throw new Error(`${path} contains secret-looking data`);
40
+ return;
41
+ }
42
+ if (Array.isArray(value)) {
43
+ value.forEach((item, index) => assertNoSensitivePayload(item, `${path}[${index}]`));
44
+ return;
45
+ }
46
+ if (!isPlainObject(value)) return;
47
+ for (const [key, child] of Object.entries(value)) {
48
+ const childPath = `${path}.${key}`;
49
+ if (FORBIDDEN_KEY_RE.test(key) && !SAFE_FIELD_NAMES.has(key) && !/^result\.blockers\[\d+\]\.message$/.test(childPath)) throw new Error(`${childPath} is not allowed in domain/TLS evidence`);
50
+ assertNoSensitivePayload(child, childPath);
51
+ }
52
+ }
53
+
54
+ function normalizeDomain(value) {
55
+ if (!nonEmptyString(value)) return null;
56
+ const domain = value.trim().toLowerCase().replace(/\.$/, '');
57
+ return /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/.test(domain) ? domain : null;
58
+ }
59
+
60
+ function httpsUrl(value, path, blockers) {
61
+ if (!nonEmptyString(value)) {
62
+ blockers.push(blocker(`${path} is required`, path));
63
+ return null;
64
+ }
65
+ try {
66
+ const url = new URL(value);
67
+ if (url.protocol !== 'https:') blockers.push(blocker(`${path} must use https`, path));
68
+ if (url.username || url.password) blockers.push(blocker(`${path} must not include credentials`, path));
69
+ return url;
70
+ } catch {
71
+ blockers.push(blocker(`${path} must be a valid URL`, path));
72
+ return null;
73
+ }
74
+ }
75
+
76
+ function statusOk(value) {
77
+ return typeof value === 'string' && ACCEPTED_STATUS.has(value.trim().toLowerCase());
78
+ }
79
+
80
+ function validateDns(dns, domain, blockers) {
81
+ if (!isPlainObject(dns)) {
82
+ blockers.push(blocker('dns object is required', 'dns'));
83
+ return { records: 0 };
84
+ }
85
+ for (const field of ['provider', 'zone_ref', 'propagation_ref', 'status']) {
86
+ if (!nonEmptyString(dns[field])) blockers.push(blocker(`dns.${field} is required`, `dns.${field}`));
87
+ }
88
+ if (!statusOk(dns.status)) blockers.push(blocker('dns.status must be active/verified/observed/go', 'dns.status'));
89
+ if (!Array.isArray(dns.records) || dns.records.length === 0) {
90
+ blockers.push(blocker('dns.records must be non-empty array', 'dns.records'));
91
+ return { records: 0 };
92
+ }
93
+ let coveredApexOrWww = false;
94
+ dns.records.forEach((record, index) => {
95
+ const path = `dns.records[${index}]`;
96
+ if (!isPlainObject(record)) {
97
+ blockers.push(blocker('dns record must be object', path));
98
+ return;
99
+ }
100
+ for (const field of ['type', 'name', 'value_ref', 'status']) {
101
+ if (!nonEmptyString(record[field])) blockers.push(blocker(`${path}.${field} is required`, `${path}.${field}`));
102
+ }
103
+ const type = String(record.type ?? '').toUpperCase();
104
+ if (!['A', 'AAAA', 'CNAME', 'ALIAS'].includes(type)) blockers.push(blocker(`${path}.type must be A/AAAA/CNAME/ALIAS`, `${path}.type`));
105
+ if (!statusOk(record.status)) blockers.push(blocker(`${path}.status must be active/verified/observed/go`, `${path}.status`));
106
+ const name = normalizeDomain(record.name);
107
+ if (domain && name && (name === domain || name === `www.${domain}`)) coveredApexOrWww = true;
108
+ });
109
+ if (!coveredApexOrWww) blockers.push(blocker('dns.records must cover apex domain or www domain', 'dns.records'));
110
+ return { records: dns.records.length };
111
+ }
112
+
113
+ function validateTls(tls, domain, blockers, nowMs) {
114
+ if (!isPlainObject(tls)) {
115
+ blockers.push(blocker('tls object is required', 'tls'));
116
+ return false;
117
+ }
118
+ for (const field of ['issuer', 'certificate_ref', 'expires_at', 'renewal_ref', 'alert_ref', 'status']) {
119
+ if (!nonEmptyString(tls[field])) blockers.push(blocker(`tls.${field} is required`, `tls.${field}`));
120
+ }
121
+ if (!statusOk(tls.status)) blockers.push(blocker('tls.status must be active/verified/observed/go', 'tls.status'));
122
+ if (!isoLike(tls.expires_at)) blockers.push(blocker('tls.expires_at must be ISO time', 'tls.expires_at'));
123
+ else if (Date.parse(tls.expires_at) <= nowMs) blockers.push(blocker('tls.expires_at must be in the future', 'tls.expires_at'));
124
+ const names = Array.isArray(tls.subject_alt_names) ? tls.subject_alt_names.map(normalizeDomain).filter(Boolean) : [];
125
+ if (domain && names.length > 0 && !names.includes(domain) && !names.includes(`www.${domain}`)) blockers.push(blocker('tls.subject_alt_names must include apex or www domain', 'tls.subject_alt_names'));
126
+ return true;
127
+ }
128
+
129
+ function validateEndpoint(endpoint, domain, blockers) {
130
+ if (!isPlainObject(endpoint)) {
131
+ blockers.push(blocker('endpoint object is required', 'endpoint'));
132
+ return false;
133
+ }
134
+ const url = httpsUrl(endpoint.url, 'endpoint.url', blockers);
135
+ if (url && domain && url.hostname.toLowerCase() !== domain && url.hostname.toLowerCase() !== `www.${domain}`) blockers.push(blocker('endpoint.url host must match domain or www domain', 'endpoint.url'));
136
+ if (!Number.isSafeInteger(endpoint.status_code) || endpoint.status_code < 200 || endpoint.status_code >= 400) blockers.push(blocker('endpoint.status_code must be 2xx/3xx integer', 'endpoint.status_code'));
137
+ if (!nonEmptyString(endpoint.content_type) || !/html|text\/plain|application\/json/i.test(endpoint.content_type)) blockers.push(blocker('endpoint.content_type must be html/text/json', 'endpoint.content_type'));
138
+ if (!isoLike(endpoint.observed_at)) blockers.push(blocker('endpoint.observed_at must be ISO time', 'endpoint.observed_at'));
139
+ if (!nonEmptyString(endpoint.public_site_security_ref)) blockers.push(blocker('endpoint.public_site_security_ref is required', 'endpoint.public_site_security_ref'));
140
+ const headers = endpoint.security_headers;
141
+ if (!isPlainObject(headers)) blockers.push(blocker('endpoint.security_headers object is required', 'endpoint.security_headers'));
142
+ else {
143
+ const lower = new Map(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), String(value)]));
144
+ for (const header of REQUIRED_SECURITY_HEADERS) {
145
+ if (!lower.has(header)) blockers.push(blocker(`endpoint.security_headers missing ${header}`, 'endpoint.security_headers'));
146
+ }
147
+ if (lower.get('x-content-type-options') && lower.get('x-content-type-options') !== 'nosniff') blockers.push(blocker('x-content-type-options must be nosniff', 'endpoint.security_headers.x-content-type-options'));
148
+ if (lower.get('x-frame-options') && !['DENY', 'SAMEORIGIN'].includes(lower.get('x-frame-options'))) blockers.push(blocker('x-frame-options must be DENY or SAMEORIGIN', 'endpoint.security_headers.x-frame-options'));
149
+ }
150
+ return true;
151
+ }
152
+
153
+ function validateClaimBoundary(boundary, blockers) {
154
+ if (!isPlainObject(boundary)) {
155
+ blockers.push(blocker('claim_boundary object is required', 'claim_boundary'));
156
+ return;
157
+ }
158
+ for (const field of ['public_endpoint_only', 'backend_readiness_claim', 'credential_claim', 'token_roi_claim', 'provider_invoice_savings_claim']) {
159
+ if (typeof boundary[field] !== 'boolean') blockers.push(blocker(`claim_boundary.${field} must be boolean`, `claim_boundary.${field}`));
160
+ }
161
+ if (boundary.public_endpoint_only !== true) blockers.push(blocker('claim_boundary.public_endpoint_only must be true', 'claim_boundary.public_endpoint_only'));
162
+ for (const field of ['backend_readiness_claim', 'credential_claim', 'token_roi_claim', 'provider_invoice_savings_claim']) {
163
+ if (boundary[field] !== false) blockers.push(blocker(`claim_boundary.${field} must be false`, `claim_boundary.${field}`));
164
+ }
165
+ }
166
+
167
+ export function validateDomainTlsEvidence(evidence, options = {}) {
168
+ if (!isPlainObject(evidence)) throw new Error('domain/TLS evidence must be an object');
169
+ assertNoSensitivePayload(evidence);
170
+ const blockers = [];
171
+ if (evidence.schema !== DOMAIN_TLS_EVIDENCE_SCHEMA) blockers.push(blocker('schema mismatch', 'schema'));
172
+ const domain = normalizeDomain(evidence.domain);
173
+ if (!domain) blockers.push(blocker('domain must be a valid domain name', 'domain'));
174
+ const publicUrl = httpsUrl(evidence.public_url ?? evidence.url, 'public_url', blockers);
175
+ if (publicUrl && domain && publicUrl.hostname.toLowerCase() !== domain && publicUrl.hostname.toLowerCase() !== `www.${domain}`) blockers.push(blocker('public_url host must match domain or www domain', 'public_url'));
176
+ const dns = validateDns(evidence.dns, domain, blockers);
177
+ validateTls(evidence.tls, domain, blockers, Date.parse(options.now ?? options.generated_at ?? new Date().toISOString()));
178
+ validateEndpoint(evidence.endpoint, domain, blockers);
179
+ validateClaimBoundary(evidence.claim_boundary, blockers);
180
+ const result = {
181
+ schema: DOMAIN_TLS_RESULT_SCHEMA,
182
+ generated_at: options.generated_at ?? options.generatedAt ?? new Date(0).toISOString(),
183
+ ok: blockers.length === 0,
184
+ status: blockers.length === 0 ? 'accepted' : 'blocked',
185
+ blockers,
186
+ checked: {
187
+ domain: domain ?? null,
188
+ public_url: publicUrl?.href ?? null,
189
+ dns_records: dns.records,
190
+ tls_expires_at: evidence.tls?.expires_at ?? null,
191
+ endpoint_status_code: evidence.endpoint?.status_code ?? null,
192
+ required_security_headers: REQUIRED_SECURITY_HEADERS.length,
193
+ },
194
+ claim_boundary: [
195
+ 'Domain/TLS validation checks declared public endpoint evidence only; it does not register domains, mutate DNS, deploy Cloudflare Pages, or prove backend readiness.',
196
+ 'A pass result is public-site reachability evidence and does not prove relay/gateway durable storage, KMS, SIEM, backup, operator acceptance, or hosted/BYOC readiness.',
197
+ 'Credentials, API tokens, raw memory, prompts, transcripts, provider responses, and personal contact data must remain outside domain/TLS artifacts.',
198
+ ],
199
+ };
200
+ assertNoSensitivePayload(result, 'result');
201
+ return result;
202
+ }
203
+
204
+ function parseArgs(argv = process.argv.slice(2)) {
205
+ const flags = new Map();
206
+ for (let index = 0; index < argv.length; index += 1) {
207
+ const arg = argv[index];
208
+ if (!arg.startsWith('--')) continue;
209
+ const eq = arg.indexOf('=');
210
+ if (eq !== -1) flags.set(arg.slice(2, eq), arg.slice(eq + 1));
211
+ else if (!argv[index + 1] || argv[index + 1].startsWith('--')) flags.set(arg.slice(2), true);
212
+ else {
213
+ flags.set(arg.slice(2), argv[index + 1]);
214
+ index += 1;
215
+ }
216
+ }
217
+ return flags;
218
+ }
219
+
220
+ function getFlag(flags, names) {
221
+ for (const name of names) if (flags.has(name)) return flags.get(name);
222
+ return undefined;
223
+ }
224
+
225
+ async function main() {
226
+ const flags = parseArgs();
227
+ const evidencePath = getFlag(flags, ['evidence', 'domain', 'in']);
228
+ if (typeof evidencePath !== 'string' || evidencePath.trim() === '') throw new Error('--evidence <path> is required');
229
+ const evidence = JSON.parse(await readFile(resolve(evidencePath), 'utf8'));
230
+ const result = validateDomainTlsEvidence(evidence, { generated_at: new Date().toISOString() });
231
+ const out = getFlag(flags, ['out']);
232
+ const text = `${JSON.stringify(result, null, 2)}\n`;
233
+ if (out && out !== true) {
234
+ const outPath = resolve(String(out));
235
+ await mkdir(dirname(outPath), { recursive: true });
236
+ await writeFile(outPath, text, 'utf8');
237
+ }
238
+ process.stdout.write(text);
239
+ process.exitCode = result.ok ? 0 : 1;
240
+ }
241
+
242
+ const invokedPath = process.argv[1] ? resolve(process.argv[1]) : '';
243
+ if (invokedPath === fileURLToPath(import.meta.url)) {
244
+ main().catch((error) => {
245
+ process.stderr.write(`${error.name ?? 'Error'}: ${error.message}\n`);
246
+ process.exitCode = 1;
247
+ });
248
+ }