enigma-memory 0.1.11 → 0.1.13

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 (58) hide show
  1. package/README.md +8 -0
  2. package/apps/cli/bin/enigma.mjs +362 -10
  3. package/deploy/SIMULATION.md +152 -0
  4. package/deploy/docker-compose.local-production-simulation.yml +237 -0
  5. package/deploy/docker-compose.production.example.yml +19 -0
  6. package/deploy/kms-mock.mjs +64 -0
  7. package/deploy/nginx.local-production-simulation.conf +33 -0
  8. package/deploy/siem-mock.mjs +50 -0
  9. package/docs/benchmark-attestation-network.md +488 -0
  10. package/docs/benchmark-reproducibility.md +19 -2
  11. package/docs/blockchain-only-mechanisms.md +388 -0
  12. package/docs/client-connectors.md +512 -0
  13. package/docs/demo-proof-network.md +275 -0
  14. package/docs/developer-ecosystem.md +47 -4
  15. package/docs/developer-proof-quickstart.md +325 -0
  16. package/docs/enigma-memory-ready-conformance.md +376 -0
  17. package/docs/enterprise-proof-control-plane.md +365 -0
  18. package/docs/install-anywhere.md +517 -0
  19. package/docs/market-category-narrative.md +398 -0
  20. package/docs/memory-drive-health-model.md +649 -0
  21. package/docs/memory-drive-strategy.md +458 -0
  22. package/docs/memory-passport-standard.md +445 -0
  23. package/docs/novelty-invention-candidates.md +161 -0
  24. package/docs/privacy-ledger-model.md +229 -0
  25. package/docs/proof-network-build-notes.md +240 -0
  26. package/docs/proof-network-claim-boundaries.md +318 -0
  27. package/docs/proof-network-dashboard-spec.md +773 -0
  28. package/docs/proof-network-glossary.md +27 -0
  29. package/docs/proof-network-launch-plan.md +421 -0
  30. package/docs/proof-network-operator-protocol.md +432 -0
  31. package/docs/proof-network-roadmap.md +431 -0
  32. package/docs/proof-network-test-plan.md +216 -0
  33. package/docs/proof-network-threat-model.md +373 -0
  34. package/docs/proof-network.md +257 -0
  35. package/docs/sdk-api.md +132 -10
  36. package/docs/solana-devnet-acceptance.md +226 -0
  37. package/docs/solana-proof-rail.md +453 -0
  38. package/examples/ci/github-actions.yml +6 -3
  39. package/examples/proof-network-anchor.json +37 -0
  40. package/examples/proof-network-attestation.json +35 -0
  41. package/examples/proof-network-grant.json +27 -0
  42. package/examples/proof-network-packet.json +71 -0
  43. package/package.json +42 -3
  44. package/packages/mcp-server/src/index.js +1 -1
  45. package/packages/proof-network/src/index.js +570 -0
  46. package/scripts/build-hosted-api-key-lifecycle.mjs +1 -1
  47. package/scripts/build-hosted-customer-lifecycle.mjs +1 -1
  48. package/scripts/build-installer-assets.mjs +1 -1
  49. package/scripts/build-proof-network-packet.mjs +213 -0
  50. package/scripts/run-standard-memory-benchmarks.mjs +1 -1
  51. package/scripts/simulate-production-env.mjs +210 -0
  52. package/scripts/verify-registry-install.mjs +1 -0
  53. package/scripts/wait-for-backend-ready.mjs +101 -0
  54. package/specs/goal-completion-audit-v1.schema.json +1 -0
  55. package/specs/proof-network-anchor-batch-v1.schema.json +125 -0
  56. package/specs/proof-network-benchmark-attestation-v1.schema.json +103 -0
  57. package/specs/proof-network-capability-grant-v1.schema.json +132 -0
  58. package/specs/proof-network-packet-v1.schema.json +171 -0
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from 'node:crypto';
3
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
4
+ import { dirname, isAbsolute, resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ import {
8
+ assertNoPrivateProofPayload,
9
+ createBenchmarkAttestation,
10
+ createProofNetworkAnchorBatch,
11
+ createProofNetworkPacket,
12
+ sha256Json,
13
+ validateBenchmarkAttestation,
14
+ validateProofNetworkAnchorBatch,
15
+ validateProofNetworkPacket,
16
+ } from '../packages/proof-network/src/index.js';
17
+
18
+ export const PROOF_NETWORK_PACKET_RELEASE_TARGET = '0.1.13';
19
+
20
+ const HASH_RE = /^(?:sha256:)?[a-f0-9]{64}$/iu;
21
+ 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}|\b(?:raw[\s_-]*memory|plaintext[\s_-]*prompts?|plain[\s_-]*text[\s_-]*prompts?|private[\s_-]*prompts?|provider[\s_-]*responses?|full[\s_-]*transcript|decrypted[\s_-]*memory|credentials?|secrets?|passwords?|private[\s_-]*keys?|api[\s_-]*key[\s_-]*(?:secret|material|value)|api[\s_-]*secrets?|access[\s_-]*tokens?|refresh[\s_-]*tokens?|token[\s_-]*values?|credential[\s_-]*material|tenant[\s_-]*names?)\b)/iu;
22
+ const ABSOLUTE_LOCAL_PATH_RE = /^(?:[A-Za-z]:[\\/]|\\\\|\/(?:Users|home|tmp|var|etc|mnt|Volumes)\b)/u;
23
+
24
+ class UsageError extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ this.name = 'UsageError';
28
+ }
29
+ }
30
+
31
+ function readRequiredValue(argv, index, flag) {
32
+ const value = argv[index + 1];
33
+ if (value === undefined || value.startsWith('--')) throw new UsageError(`${flag} requires a value`);
34
+ return value;
35
+ }
36
+
37
+ function assertPublicSafeString(value, label) {
38
+ if (typeof value !== 'string' || value.trim() === '') throw new UsageError(`${label} must be a non-empty public ref or hash`);
39
+ const normalized = value.trim();
40
+ if (SECRET_VALUE_RE.test(normalized)) throw new UsageError(`${label} contains private or secret material`);
41
+ return normalized;
42
+ }
43
+
44
+ function assertPublicHash(value, label) {
45
+ const normalized = assertPublicSafeString(value, label);
46
+ if (!HASH_RE.test(normalized)) throw new UsageError(`${label} must be a sha256 hash as 64 hex characters or sha256:<64 hex>`);
47
+ return normalized.toLowerCase().startsWith('sha256:') ? normalized.toLowerCase() : `sha256:${normalized.toLowerCase()}`;
48
+ }
49
+
50
+ function assertRelativeOutFile(value) {
51
+ const normalized = assertPublicSafeString(value, 'output file');
52
+ if (isAbsolute(normalized) || ABSOLUTE_LOCAL_PATH_RE.test(normalized)) throw new UsageError('output file must be a relative path');
53
+ return normalized;
54
+ }
55
+
56
+ export function parseArgs(argv = process.argv.slice(2)) {
57
+ const args = {
58
+ activeRoot: undefined,
59
+ receiptRoot: undefined,
60
+ benchmarkReport: undefined,
61
+ datasetHash: undefined,
62
+ runnerHash: undefined,
63
+ operatorRef: undefined,
64
+ out: undefined,
65
+ help: false,
66
+ };
67
+
68
+ for (let index = 0; index < argv.length; index += 1) {
69
+ const raw = argv[index];
70
+ const equalsIndex = raw.indexOf('=');
71
+ const flag = equalsIndex > 0 ? raw.slice(0, equalsIndex) : raw;
72
+ const inlineValue = equalsIndex > 0 ? raw.slice(equalsIndex + 1) : undefined;
73
+ const value = () => {
74
+ if (inlineValue !== undefined) return inlineValue;
75
+ const next = readRequiredValue(argv, index, flag);
76
+ index += 1;
77
+ return next;
78
+ };
79
+
80
+ if (flag === '--help' || flag === '-h') args.help = true;
81
+ else if (flag === '--active-root') args.activeRoot = assertPublicHash(value(), 'active root');
82
+ else if (flag === '--receipt-root') args.receiptRoot = assertPublicHash(value(), 'receipt root');
83
+ else if (flag === '--benchmark-report') args.benchmarkReport = value();
84
+ else if (flag === '--dataset-hash') args.datasetHash = assertPublicHash(value(), 'dataset hash');
85
+ else if (flag === '--runner-hash') args.runnerHash = assertPublicHash(value(), 'runner hash');
86
+ else if (flag === '--operator-ref') args.operatorRef = assertPublicSafeString(value(), 'operator ref');
87
+ else if (flag === '--out') args.out = assertRelativeOutFile(value());
88
+ else throw new UsageError(`unknown option ${raw}; use --help`);
89
+ }
90
+ return args;
91
+ }
92
+
93
+ export function usage() {
94
+ return `Usage: node scripts/build-proof-network-packet.mjs --active-root <sha256> --receipt-root <sha256> --benchmark-report <file> --dataset-hash <sha256> --runner-hash <sha256> --operator-ref <ref> [--out <file>]
95
+
96
+ Builds a public-safe proof-network packet from local refs and hashes. The benchmark report file is hashed only; its body and path are never copied into the packet. This script does not call a network, deploy contracts, create accounts, sign transactions, or write raw memory, prompts, transcripts, completions, embeddings, ACL bodies, tenant names, private keys, API keys, seed phrases, or provider responses.
97
+ `;
98
+ }
99
+
100
+ function requireArgs(args) {
101
+ const required = [
102
+ ['--active-root', args.activeRoot],
103
+ ['--receipt-root', args.receiptRoot],
104
+ ['--benchmark-report', args.benchmarkReport],
105
+ ['--dataset-hash', args.datasetHash],
106
+ ['--runner-hash', args.runnerHash],
107
+ ['--operator-ref', args.operatorRef],
108
+ ];
109
+ const missing = required.filter(([, value]) => value === undefined).map(([name]) => name);
110
+ if (missing.length > 0) throw new UsageError(`missing required option(s): ${missing.join(', ')}`);
111
+ }
112
+
113
+ function sha256Buffer(buffer) {
114
+ return `sha256:${createHash('sha256').update(buffer).digest('hex')}`;
115
+ }
116
+
117
+ function withBoundaryFlags(packet) {
118
+ return {
119
+ transaction_submitted: false,
120
+ raw_memory_on_chain: false,
121
+ ...packet,
122
+ transaction_submitted: false,
123
+ raw_memory_on_chain: false,
124
+ };
125
+ }
126
+
127
+ function assertValidation(validation, label) {
128
+ if (validation?.ok !== true) throw new Error(`${label} validation failed: ${(validation?.errors ?? ['unknown error']).join('; ')}`);
129
+ }
130
+
131
+ export async function buildProofNetworkPacket(args, options = {}) {
132
+ requireArgs(args);
133
+ const generatedAt = options.generated_at ?? options.generatedAt ?? new Date().toISOString();
134
+ const reportBytes = await readFile(args.benchmarkReport);
135
+ const reportHash = sha256Buffer(reportBytes);
136
+ const packageRef = `npm:enigma-memory@${PROOF_NETWORK_PACKET_RELEASE_TARGET}`;
137
+
138
+ const publicInputs = {
139
+ active_root: args.activeRoot,
140
+ receipt_root: args.receiptRoot,
141
+ report_hash: reportHash,
142
+ dataset_ref: args.datasetHash,
143
+ runner_ref: args.runnerHash,
144
+ operator_ref: args.operatorRef,
145
+ package_ref: packageRef,
146
+ transaction_submitted: false,
147
+ raw_memory_on_chain: false,
148
+ };
149
+ assertNoPrivateProofPayload(publicInputs);
150
+
151
+ const operatorSignatureRef = `signature:${sha256Json(args.operatorRef).slice('sha256:'.length)}`;
152
+ const benchmarkAttestation = createBenchmarkAttestation({
153
+ report_hash: reportHash,
154
+ dataset_ref: args.datasetHash,
155
+ runner_ref: args.runnerHash,
156
+ package_ref: packageRef,
157
+ benchmark_ref: `benchmark-report:${reportHash}`,
158
+ signature_ref: operatorSignatureRef,
159
+ attested_at: generatedAt,
160
+ });
161
+ assertValidation(validateBenchmarkAttestation(benchmarkAttestation), 'benchmark attestation');
162
+
163
+ const anchorBatch = createProofNetworkAnchorBatch({
164
+ chain: 'solana',
165
+ generated_at: generatedAt,
166
+ anchor_ref: `anchor:${sha256Json([args.activeRoot, args.receiptRoot, reportHash]).slice('sha256:'.length, 'sha256:'.length + 32)}`,
167
+ commitments: [
168
+ { kind: 'active_root', root: args.activeRoot, ref: 'active-root' },
169
+ { kind: 'receipt_root', root: args.receiptRoot, ref: 'receipt-root' },
170
+ { kind: 'benchmark_report', root: reportHash, ref: 'benchmark-report' },
171
+ { kind: 'benchmark_attestation', root: benchmarkAttestation.benchmark_attestation_hash, ref: 'benchmark-attestation' },
172
+ { kind: 'operator_ref', root: sha256Json(args.operatorRef), ref: args.operatorRef },
173
+ ],
174
+ });
175
+ assertValidation(validateProofNetworkAnchorBatch(anchorBatch), 'anchor batch');
176
+
177
+ const packet = withBoundaryFlags(createProofNetworkPacket({
178
+ anchor_batches: [anchorBatch],
179
+ attestations: [benchmarkAttestation],
180
+ packet_ref: `proof-network-packet:${sha256Json([anchorBatch.anchor_batch_hash, benchmarkAttestation.benchmark_attestation_hash]).slice('sha256:'.length, 'sha256:'.length + 32)}`,
181
+ created_at: generatedAt,
182
+ }));
183
+ assertNoPrivateProofPayload(packet);
184
+ assertValidation(validateProofNetworkPacket(packet), 'proof-network packet');
185
+ return packet;
186
+ }
187
+
188
+ export async function main(argv = process.argv.slice(2)) {
189
+ const args = parseArgs(argv);
190
+ if (args.help) {
191
+ process.stdout.write(usage());
192
+ return 0;
193
+ }
194
+ const packet = await buildProofNetworkPacket(args);
195
+ const json = `${JSON.stringify(packet, null, 2)}\n`;
196
+ if (args.out) {
197
+ try {
198
+ await mkdir(dirname(args.out), { recursive: true });
199
+ await writeFile(args.out, json, 'utf8');
200
+ } catch {
201
+ throw new Error('failed to write proof-network packet output');
202
+ }
203
+ }
204
+ process.stdout.write(json);
205
+ return 0;
206
+ }
207
+
208
+ if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
209
+ main().catch((error) => {
210
+ process.stderr.write(`${error.name ?? 'Error'}: ${error.message ?? 'failed to build proof-network packet'}\n`);
211
+ process.exitCode = 1;
212
+ });
213
+ }
@@ -995,7 +995,7 @@ function buildSuiteReport(datasetRows, topK, options) {
995
995
  generated_at: options.generated_at ?? new Date().toISOString(),
996
996
  package: {
997
997
  name: 'enigma-memory',
998
- version: '0.1.11',
998
+ version: '0.1.13',
999
999
  },
1000
1000
  public_safe: true,
1001
1001
  top_k: topK,
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env node
2
+ // Enigma Memory — generate local-simulation secrets and TLS material.
3
+ // CLAIM BOUNDARY: local-simulation only. The files created by this script are
4
+ // bind-mounted by deploy/docker-compose.local-production-simulation.yml. They
5
+ // are not production secrets, HSM custody, or real operator evidence.
6
+
7
+ import { spawnSync } from 'node:child_process'
8
+ import { generateKeyPairSync, randomUUID } from 'node:crypto'
9
+ import fs from 'node:fs'
10
+ import path from 'node:path'
11
+ import { fileURLToPath } from 'node:url'
12
+
13
+ const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
14
+ const DEFAULT_SECRETS_DIR = path.join(ROOT, 'deploy', 'secrets-simulation')
15
+
16
+ const REQUIRED_SECRET_FILES = [
17
+ 'relay-signing-key',
18
+ 'gateway-signing-key',
19
+ 'external-storage-dsn',
20
+ 'kms-key-ref',
21
+ 'backup-target-uri',
22
+ 'siem-export-endpoint',
23
+ 'operator-acceptance-evidence-uri',
24
+ 'gateway-admin-auth-bearer',
25
+ 'gateway-data-plane-auth-bearer',
26
+ 'tls.crt',
27
+ 'tls.key',
28
+ ]
29
+
30
+ function parseArgs(argv) {
31
+ const flags = { check: false, secretsDir: DEFAULT_SECRETS_DIR }
32
+ for (let i = 0; i < argv.length; i += 1) {
33
+ const arg = argv[i]
34
+ if (arg === '--check') {
35
+ flags.check = true
36
+ } else if (arg === '--secrets-dir') {
37
+ i += 1
38
+ if (i >= argv.length) throw new Error('--secrets-dir requires a path')
39
+ flags.secretsDir = path.resolve(argv[i])
40
+ } else if (arg === '--help' || arg === '-h') {
41
+ process.stdout.write(
42
+ 'Usage: node scripts/simulate-production-env.mjs [--check] [--secrets-dir <dir>]\n' +
43
+ '\n' +
44
+ 'Generates local-simulation secret files and a self-signed TLS certificate\n' +
45
+ `under ${DEFAULT_SECRETS_DIR} (customizable with --secrets-dir).\n` +
46
+ 'Run with --check to verify required files exist and are non-empty.\n'
47
+ )
48
+ process.exit(0)
49
+ }
50
+ }
51
+ return flags
52
+ }
53
+
54
+ function generateKmsKeyRef() {
55
+ const pair = generateKeyPairSync('ed25519', {
56
+ privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
57
+ publicKeyEncoding: { type: 'spki', format: 'pem' },
58
+ })
59
+ return (
60
+ JSON.stringify(
61
+ {
62
+ schema: 'enigma.local_simulation_kms_key_ref.v1',
63
+ key_id: `local-simulation-kms-key-${randomUUID()}`,
64
+ alg: 'Ed25519',
65
+ public_key: pair.publicKey,
66
+ private_key: pair.privateKey,
67
+ claim_boundary: 'local-simulation only. This is not HSM-grade key custody.',
68
+ },
69
+ null,
70
+ 2
71
+ ) + '\n'
72
+ )
73
+ }
74
+
75
+ const SECRET_GENERATORS = {
76
+ 'relay-signing-key': () => 'local-simulation-relay-signing-key-ref\n',
77
+ 'gateway-signing-key': () => 'local-simulation-gateway-signing-key-ref\n',
78
+ 'external-storage-dsn': () => 'postgres://enigma:enigma@postgres:5432/enigma?sslmode=disable\n',
79
+ 'kms-key-ref': generateKmsKeyRef,
80
+ 'backup-target-uri': () => 'file:///tmp/enigma-backups\n',
81
+ 'siem-export-endpoint': () => 'http://siem-mock:3000/events\n',
82
+ 'operator-acceptance-evidence-uri': () => 'file:///run/secrets/operator-acceptance-evidence-uri\n',
83
+ 'gateway-admin-auth-bearer': () => 'local-simulation-admin-token\n',
84
+ 'gateway-data-plane-auth-bearer': () => 'local-simulation-data-plane-token\n',
85
+ }
86
+
87
+ function ensureDir(dir) {
88
+ fs.mkdirSync(dir, { recursive: true })
89
+ }
90
+
91
+ function isMissingOrEmpty(filePath) {
92
+ try {
93
+ const stat = fs.statSync(filePath)
94
+ return !stat.isFile() || stat.size === 0
95
+ } catch {
96
+ return true
97
+ }
98
+ }
99
+
100
+ function generateTlsCerts(secretsDir) {
101
+ const key = path.join(secretsDir, 'tls.key')
102
+ const cert = path.join(secretsDir, 'tls.crt')
103
+ const config = path.join(secretsDir, '.openssl-tmp.cnf')
104
+ const configText =
105
+ '[req]\n' +
106
+ 'distinguished_name = req_distinguished_name\n' +
107
+ 'x509_extensions = v3_req\n' +
108
+ 'prompt = no\n' +
109
+ '\n' +
110
+ '[req_distinguished_name]\n' +
111
+ 'CN = sim.enigmamemory.com\n' +
112
+ '\n' +
113
+ '[v3_req]\n' +
114
+ 'subjectAltName = @alt_names\n' +
115
+ '\n' +
116
+ '[alt_names]\n' +
117
+ 'DNS.1 = localhost\n' +
118
+ 'DNS.2 = sim.enigmamemory.com\n' +
119
+ 'DNS.3 = relay.sim.enigmamemory.com\n' +
120
+ 'DNS.4 = gateway.sim.enigmamemory.com\n' +
121
+ 'DNS.5 = *.sim.enigmamemory.com\n' +
122
+ 'IP.1 = 127.0.0.1\n'
123
+ fs.writeFileSync(config, configText)
124
+ try {
125
+ const result = spawnSync(
126
+ 'openssl',
127
+ [
128
+ 'req', '-x509', '-nodes', '-newkey', 'rsa:2048',
129
+ '-keyout', key,
130
+ '-out', cert,
131
+ '-days', '365',
132
+ '-config', config,
133
+ ],
134
+ { stdio: 'pipe' }
135
+ )
136
+ if (result.status !== 0) {
137
+ throw new Error(
138
+ `Failed to generate self-signed TLS certificate: ${result.stderr?.toString() || 'openssl exited non-zero'}`
139
+ )
140
+ }
141
+ } finally {
142
+ try {
143
+ fs.unlinkSync(config)
144
+ } catch {
145
+ // ignore cleanup failure
146
+ }
147
+ }
148
+ }
149
+
150
+ function generateSecrets(secretsDir) {
151
+ ensureDir(secretsDir)
152
+ for (const name of REQUIRED_SECRET_FILES) {
153
+ if (name === 'tls.crt' || name === 'tls.key') continue
154
+ const filePath = path.join(secretsDir, name)
155
+ if (isMissingOrEmpty(filePath)) {
156
+ fs.writeFileSync(filePath, SECRET_GENERATORS[name](), { mode: 0o600 })
157
+ }
158
+ }
159
+ const keyPath = path.join(secretsDir, 'tls.key')
160
+ const certPath = path.join(secretsDir, 'tls.crt')
161
+ if (isMissingOrEmpty(keyPath) || isMissingOrEmpty(certPath)) {
162
+ generateTlsCerts(secretsDir)
163
+ }
164
+ }
165
+
166
+ function check(secretsDir) {
167
+ const missing = []
168
+ for (const name of REQUIRED_SECRET_FILES) {
169
+ if (isMissingOrEmpty(path.join(secretsDir, name))) missing.push(name)
170
+ }
171
+ if (missing.length > 0) {
172
+ process.stderr.write(`Missing or empty simulation secrets: ${missing.join(', ')}\n`)
173
+ process.exit(1)
174
+ }
175
+ process.stdout.write(
176
+ `All ${REQUIRED_SECRET_FILES.length} required simulation secret files exist and are non-empty in ${secretsDir}\n`
177
+ )
178
+ }
179
+
180
+ function printStartInstructions() {
181
+ process.stdout.write('\n')
182
+ process.stdout.write('To start the local production simulation, run:\n')
183
+ process.stdout.write(' docker compose -f deploy/docker-compose.local-production-simulation.yml up --build -d\n')
184
+ process.stdout.write('\n')
185
+ process.stdout.write('To make the public-looking domain resolve locally, add this line to /etc/hosts\n')
186
+ process.stdout.write('(or C:\\Windows\\System32\\drivers\\etc\\hosts on Windows):\n')
187
+ process.stdout.write(' 127.0.0.1 sim.enigmamemory.com relay.sim.enigmamemory.com gateway.sim.enigmamemory.com\n')
188
+ process.stdout.write('\n')
189
+ process.stdout.write('To wait for the backend to be ready:\n')
190
+ process.stdout.write(' node scripts/wait-for-backend-ready.mjs\n')
191
+ process.stdout.write('\n')
192
+ process.stdout.write('To inspect public HTTPS readiness (self-signed cert, use -k with curl):\n')
193
+ process.stdout.write(' curl -k https://localhost:8443/readyz\n')
194
+ process.stdout.write(' curl -k https://localhost:9443/readyz\n')
195
+ process.stdout.write(' curl -k https://sim.enigmamemory.com:8443/readyz\n')
196
+ process.stdout.write(' curl -k https://sim.enigmamemory.com:9443/readyz\n')
197
+ }
198
+
199
+ function main() {
200
+ const flags = parseArgs(process.argv.slice(2))
201
+ if (flags.check) {
202
+ check(flags.secretsDir)
203
+ return
204
+ }
205
+ generateSecrets(flags.secretsDir)
206
+ check(flags.secretsDir)
207
+ printStartInstructions()
208
+ }
209
+
210
+ main()
@@ -24,6 +24,7 @@ export const DEFAULT_REGISTRY_VERSION = PACKAGE_JSON.version;
24
24
  export const REGISTRY_INSTALL_CHECKS = Object.freeze([
25
25
  Object.freeze({ step: 'check_enigma_help', bin: 'enigma', args: Object.freeze(['--help']) }),
26
26
  Object.freeze({ step: 'check_enigma_doctor', bin: 'enigma', args: Object.freeze(['doctor']) }),
27
+ Object.freeze({ step: 'check_enigma_test_drive_dry_run', bin: 'enigma', args: Object.freeze(['test-drive', '--dry-run']) }),
27
28
  Object.freeze({ step: 'check_enigma_relay_demo', bin: 'enigma-relay', args: Object.freeze(['demo']) }),
28
29
  Object.freeze({ step: 'check_enigma_gateway_demo', bin: 'enigma-gateway', args: Object.freeze(['demo']) }),
29
30
  ]);
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ // Enigma Memory — poll local simulated backend /readyz endpoints.
3
+ // CLAIM BOUNDARY: local-simulation only. Accepts self-signed TLS certificates.
4
+
5
+ import https from 'node:https'
6
+ import { parseArgs } from 'node:util'
7
+
8
+ const ENDPOINTS = [
9
+ { name: 'relay', url: 'https://localhost:8443/readyz' },
10
+ { name: 'gateway', url: 'https://localhost:9443/readyz' },
11
+ ]
12
+
13
+ function parseCliArgs(argv) {
14
+ const { values } = parseArgs({
15
+ args: argv,
16
+ options: {
17
+ timeout: { type: 'string', short: 't', default: '120' },
18
+ interval: { type: 'string', short: 'i', default: '2' },
19
+ help: { type: 'boolean', short: 'h', default: false },
20
+ },
21
+ })
22
+ if (values.help) {
23
+ process.stdout.write(
24
+ 'Usage: node scripts/wait-for-backend-ready.mjs [--timeout <seconds>] [--interval <seconds>]\n' +
25
+ '\n' +
26
+ 'Polls the local simulated backend /readyz endpoints until they return 200.\n' +
27
+ 'Self-signed TLS certificates are accepted because this is local simulation only.\n'
28
+ )
29
+ process.exit(0)
30
+ }
31
+ const timeoutMs = Number(values.timeout) * 1000
32
+ const intervalMs = Number(values.interval) * 1000
33
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
34
+ throw new Error('--timeout must be a positive number')
35
+ }
36
+ if (!Number.isFinite(intervalMs) || intervalMs <= 0) {
37
+ throw new Error('--interval must be a positive number')
38
+ }
39
+ return { timeoutMs, intervalMs }
40
+ }
41
+
42
+ function fetchStatus(url) {
43
+ return new Promise((resolve) => {
44
+ const req = https.get(url, { rejectUnauthorized: false }, (res) => {
45
+ let body = ''
46
+ res.setEncoding('utf8')
47
+ res.on('data', (chunk) => {
48
+ body += chunk
49
+ })
50
+ res.on('end', () => {
51
+ resolve({ statusCode: res.statusCode, body })
52
+ })
53
+ })
54
+ req.on('error', (error) => {
55
+ resolve({ statusCode: 0, error: error.message })
56
+ })
57
+ req.setTimeout(5000, () => {
58
+ req.destroy()
59
+ resolve({ statusCode: 0, error: 'request timeout' })
60
+ })
61
+ })
62
+ }
63
+
64
+ function sleep(ms) {
65
+ return new Promise((resolve) => setTimeout(resolve, ms))
66
+ }
67
+
68
+ async function main() {
69
+ const { timeoutMs, intervalMs } = parseCliArgs(process.argv.slice(2))
70
+ const deadline = Date.now() + timeoutMs
71
+ const pending = new Map(ENDPOINTS.map((ep) => [ep.name, ep]))
72
+
73
+ while (pending.size > 0 && Date.now() < deadline) {
74
+ for (const [name, ep] of pending) {
75
+ const result = await fetchStatus(ep.url)
76
+ if (result.statusCode === 200) {
77
+ process.stdout.write(`${name} ready at ${ep.url}\n`)
78
+ pending.delete(name)
79
+ } else {
80
+ process.stdout.write(
81
+ `${name} not ready (${result.statusCode || 'no response'}${result.error ? ` - ${result.error}` : ''})\n`
82
+ )
83
+ }
84
+ }
85
+ if (pending.size > 0) {
86
+ const waitMs = Math.min(intervalMs, deadline - Date.now())
87
+ if (waitMs > 0) await sleep(waitMs)
88
+ }
89
+ }
90
+
91
+ if (pending.size > 0) {
92
+ process.stderr.write(`Timed out waiting for: ${[...pending.keys()].join(', ')}\n`)
93
+ process.exit(1)
94
+ }
95
+ process.stdout.write('All backend services are ready.\n')
96
+ }
97
+
98
+ main().catch((error) => {
99
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`)
100
+ process.exit(1)
101
+ })
@@ -22,6 +22,7 @@
22
22
  "schema": { "const": "enigma.goal_completion_audit.v1" },
23
23
  "generated_at": { "type": "string", "format": "date-time" },
24
24
  "objective": { "type": "string", "minLength": 1 },
25
+ "environment": { "type": "string", "minLength": 1 },
25
26
  "complete": { "type": "boolean" },
26
27
  "release_posture": { "type": "string", "minLength": 1 },
27
28
  "go_live_ready": { "type": "boolean" },
@@ -0,0 +1,125 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.enigma.ai/proof-network-anchor-batch-v1.schema.json",
4
+ "title": "Enigma Proof Network Anchor Batch v1",
5
+ "type": "object",
6
+ "required": [
7
+ "schema",
8
+ "anchor_batch_id",
9
+ "anchor_batch_hash",
10
+ "generated_at",
11
+ "anchor_ref",
12
+ "chain",
13
+ "cluster_ref",
14
+ "commitment_count",
15
+ "root_count",
16
+ "commitment_root",
17
+ "commitments",
18
+ "solana_ready_anchor",
19
+ "transaction_submitted",
20
+ "raw_memory_on_chain",
21
+ "raw_data_included"
22
+ ],
23
+ "additionalProperties": false,
24
+ "properties": {
25
+ "schema": { "const": "enigma.proof_network.anchor_batch.v1" },
26
+ "anchor_batch_id": { "type": "string", "minLength": 8 },
27
+ "anchor_batch_hash": { "$ref": "#/$defs/sha256Digest" },
28
+ "generated_at": { "type": "string", "format": "date-time" },
29
+ "package_version": { "type": "string", "minLength": 1 },
30
+ "anchor_ref": { "$ref": "#/$defs/publicRef" },
31
+ "chain": { "const": "solana" },
32
+ "cluster_ref": { "$ref": "#/$defs/publicRef" },
33
+ "commitment_count": { "type": "integer", "minimum": 1 },
34
+ "root_count": { "type": "integer", "minimum": 1 },
35
+ "commitment_root": { "$ref": "#/$defs/sha256Digest" },
36
+ "commitments": {
37
+ "type": "array",
38
+ "minItems": 1,
39
+ "items": { "$ref": "#/$defs/commitment" }
40
+ },
41
+ "solana_ready_anchor": { "$ref": "#/$defs/solanaReadyAnchor" },
42
+ "leakage_scan": { "$ref": "#/$defs/leakageScan" },
43
+ "transaction_submitted": { "const": false },
44
+ "raw_memory_on_chain": { "const": false },
45
+ "raw_data_included": { "const": false },
46
+ "private_payload_included": { "const": false },
47
+ "signer": { "$ref": "#/$defs/signer" },
48
+ "signature": { "$ref": "#/$defs/signature" }
49
+ },
50
+ "$defs": {
51
+ "sha256Digest": { "type": "string", "pattern": "^sha256:[a-f0-9]{64}$" },
52
+ "publicRef": { "type": "string", "minLength": 1 },
53
+ "commitment": {
54
+ "type": "object",
55
+ "required": ["kind", "root"],
56
+ "additionalProperties": false,
57
+ "properties": {
58
+ "kind": {
59
+ "type": "string",
60
+ "enum": [
61
+ "active_set_root",
62
+ "receipt_log_root",
63
+ "capability_grant_root",
64
+ "capability_revocation_root",
65
+ "benchmark_attestation_root",
66
+ "proof_packet_root",
67
+ "custom_root"
68
+ ]
69
+ },
70
+ "root": { "$ref": "#/$defs/sha256Digest" },
71
+ "ref": { "$ref": "#/$defs/publicRef" },
72
+ "count": { "type": "integer", "minimum": 0 }
73
+ }
74
+ },
75
+ "solanaReadyAnchor": {
76
+ "type": "object",
77
+ "required": ["payload_hash", "account_seed", "instruction_ref", "opaque_payload_only"],
78
+ "additionalProperties": false,
79
+ "properties": {
80
+ "payload_hash": { "$ref": "#/$defs/sha256Digest" },
81
+ "account_seed": { "$ref": "#/$defs/publicRef" },
82
+ "instruction_ref": { "$ref": "#/$defs/publicRef" },
83
+ "opaque_payload_only": { "const": true },
84
+ "transaction_submitted": { "const": false }
85
+ }
86
+ },
87
+ "leakageScan": {
88
+ "type": "object",
89
+ "required": ["scanned", "passed", "policy", "raw_data_detected", "private_payload_detected", "forbidden_field_names"],
90
+ "additionalProperties": false,
91
+ "properties": {
92
+ "scanned": { "const": true },
93
+ "passed": { "const": true },
94
+ "policy": { "const": "public_hashes_roots_refs_counts_only" },
95
+ "raw_data_detected": { "const": false },
96
+ "private_payload_detected": { "const": false },
97
+ "forbidden_field_names": {
98
+ "type": "array",
99
+ "maxItems": 0,
100
+ "items": { "type": "string" }
101
+ },
102
+ "scanner_ref": { "$ref": "#/$defs/publicRef" },
103
+ "scanned_at": { "type": "string", "format": "date-time" }
104
+ }
105
+ },
106
+ "signer": {
107
+ "type": "object",
108
+ "required": ["alg", "key_id"],
109
+ "additionalProperties": false,
110
+ "properties": {
111
+ "alg": { "const": "Ed25519" },
112
+ "key_id": { "$ref": "#/$defs/publicRef" }
113
+ }
114
+ },
115
+ "signature": {
116
+ "type": "object",
117
+ "required": ["alg", "value"],
118
+ "additionalProperties": false,
119
+ "properties": {
120
+ "alg": { "const": "Ed25519" },
121
+ "value": { "type": "string", "minLength": 64 }
122
+ }
123
+ }
124
+ }
125
+ }