enigma-memory 0.1.14 → 0.1.16
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.
- package/README.md +64 -84
- package/apps/cli/bin/enigma.mjs +3151 -3126
- package/apps/native-host/README.md +20 -0
- package/deploy/SIMULATION.md +34 -38
- package/deploy/docker-compose.local-production-simulation.yml +5 -2
- package/docs/benchmark-attestation-network.md +2 -2
- package/docs/benchmark-reproducibility.md +240 -228
- package/docs/browser-extension-install.md +9 -6
- package/docs/client-connectors.md +22 -52
- package/docs/demo-proof-network.md +3 -3
- package/docs/developer-ecosystem.md +205 -223
- package/docs/developer-proof-quickstart.md +3 -3
- package/docs/enigma-memory-ready-conformance.md +1 -1
- package/docs/hosted-cloud-product.md +2 -0
- package/docs/install-anywhere.md +61 -66
- package/docs/memory-benchmarks.md +6 -3
- package/docs/proof-network-build-notes.md +2 -2
- package/docs/proof-network.md +32 -7
- package/docs/sdk-api.md +1 -1
- package/docs/solana-devnet-acceptance.md +1 -1
- package/docs/solana-proof-rail.md +1 -1
- package/package.json +278 -272
- package/packages/connectors/src/index.js +13 -0
- package/packages/mcp-server/README.md +22 -0
- package/packages/mcp-server/src/index.js +1185 -1185
- package/scripts/build-benchmark-proof-release.mjs +106 -5
- package/scripts/build-cloudflare-token-policy.mjs +6 -2
- package/scripts/build-hosted-api-key-lifecycle.mjs +274 -274
- package/scripts/build-hosted-customer-lifecycle.mjs +456 -456
- package/scripts/build-installer-assets.mjs +389 -389
- package/scripts/build-production-handoff-packet.mjs +1 -1
- package/scripts/build-production-unblocker.mjs +409 -409
- package/scripts/build-production-workplan.mjs +3 -1
- package/scripts/build-proof-network-packet.mjs +213 -213
- package/scripts/check.mjs +3 -1
- package/scripts/cloudflare-ops.mjs +35 -0
- package/scripts/collect-hosted-backend-live-evidence.mjs +44 -2
- package/scripts/run-memory-benchmarks.mjs +5 -0
- package/scripts/run-standard-memory-benchmarks.mjs +1194 -1070
- package/scripts/stage-cloudflare-pages-artifact.mjs +145 -0
|
@@ -234,6 +234,8 @@ export function buildProductionWorkplan(inputs = {}, options = {}) {
|
|
|
234
234
|
const endpointRefs = missingHostedEndpointRefs(hosted);
|
|
235
235
|
const stateBlockers = hostedStateBlockers(hosted);
|
|
236
236
|
|
|
237
|
+
const finalDependencyCommand = 'npm run production:dependencies -- --goal-audit .enigma/goal-audit-current.json --release-audit .enigma/release-audit-current.json --worker-inspect .enigma/worker-inspect-result-current.json --whitepaper .enigma/whitepaper-claims-current.json --cloudflare-credentials .enigma/cloudflare-credentials-current.json --edge-deploy .enigma/edge-backend-deployment-current.json --edge-live .enigma/edge-backend-bootstrap-live-current.json --storage-bootstrap .enigma/cloudflare-storage-bootstrap-current.json';
|
|
238
|
+
|
|
237
239
|
const phases = [
|
|
238
240
|
makePhase({
|
|
239
241
|
id: 'cloudflare_credentials',
|
|
@@ -309,7 +311,7 @@ export function buildProductionWorkplan(inputs = {}, options = {}) {
|
|
|
309
311
|
owner: 'operator-or-reviewer',
|
|
310
312
|
prerequisites: ['cloudflare_credentials', 'cloudflare_worker_permission', 'hosted_backend_refs', 'operator_acceptance', 'release_gates'],
|
|
311
313
|
blockers: dependencyReport.launch_ready === true ? [] : ['launch_ready is false'],
|
|
312
|
-
commands: [release.next_command, staticSite.next_command, whitepaper.next_command, 'npm run production:goal-audit -- --site <public-site-dir> --domain enigmamemory.com --release-audit .enigma/release-audit-current.json',
|
|
314
|
+
commands: [release.next_command, staticSite.next_command, whitepaper.next_command, 'npm run production:goal-audit -- --site <public-site-dir> --domain enigmamemory.com --release-audit .enigma/release-audit-current.json', finalDependencyCommand],
|
|
313
315
|
evidence: [...release.evidence, ...staticSite.evidence, ...whitepaper.evidence],
|
|
314
316
|
details: { goal_complete: dependencyReport.goal_complete === true, launch_ready: dependencyReport.launch_ready === true },
|
|
315
317
|
}),
|
|
@@ -1,213 +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.
|
|
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
|
-
}
|
|
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.16';
|
|
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
|
+
}
|
package/scripts/check.mjs
CHANGED
|
@@ -3,7 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
4
4
|
|
|
5
5
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
6
|
-
const packageJsonPath =
|
|
6
|
+
const packageJsonPath = process.env.ENIGMA_CHECK_PACKAGE_JSON_OVERRIDE
|
|
7
|
+
? path.resolve(process.env.ENIGMA_CHECK_PACKAGE_JSON_OVERRIDE)
|
|
8
|
+
: path.join(root, 'package.json');
|
|
7
9
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
8
10
|
const productionRoots = [
|
|
9
11
|
'packages/adapters/src/',
|
|
@@ -6,6 +6,7 @@ import { dirname, join } from 'node:path';
|
|
|
6
6
|
import { pathToFileURL } from 'node:url';
|
|
7
7
|
import { promisify } from 'node:util';
|
|
8
8
|
import { applyCloudflareSecretEnvFileFromArgv, CloudflareSecretEnvError } from './cloudflare-secret-env.mjs';
|
|
9
|
+
import { PUBLIC_SITE_SECURITY_RESULT_SCHEMA, validatePublicSiteSecurity } from './validate-public-site-security.mjs';
|
|
9
10
|
|
|
10
11
|
const execFile = promisify(execFileCallback);
|
|
11
12
|
|
|
@@ -46,6 +47,8 @@ Commands:
|
|
|
46
47
|
|
|
47
48
|
pages deploy --site <dir> --project-name <name> [--execute]
|
|
48
49
|
Without --execute, prints the exact Wrangler deploy plan only.
|
|
50
|
+
Dry-run output includes local public-site security validation.
|
|
51
|
+
--execute refuses artifacts with local security blockers before invoking Wrangler.
|
|
49
52
|
With --execute, runs Wrangler through npm exec/npx without printing the token.
|
|
50
53
|
|
|
51
54
|
pages verify --url <https-url> --project-name <name> [--domain <host>] \\
|
|
@@ -264,6 +267,35 @@ function redactPlanOutput(plan) {
|
|
|
264
267
|
return redactOperationalPayload(plan);
|
|
265
268
|
}
|
|
266
269
|
|
|
270
|
+
function redactPublicSiteSecurityBlocker(entry) {
|
|
271
|
+
return {
|
|
272
|
+
message: redactOperationalText(entry?.message ?? ''),
|
|
273
|
+
...(entry?.path === undefined ? {} : { path: redactOperationalText(String(entry.path)) }),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function publicSiteSecurityDeploySummary(result) {
|
|
278
|
+
return {
|
|
279
|
+
schema: PUBLIC_SITE_SECURITY_RESULT_SCHEMA,
|
|
280
|
+
ok: result?.ok === true,
|
|
281
|
+
status: result?.status ?? 'blocked',
|
|
282
|
+
blocker_count: Array.isArray(result?.blockers) ? result.blockers.length : 0,
|
|
283
|
+
blockers: Array.isArray(result?.blockers) ? result.blockers.map(redactPublicSiteSecurityBlocker) : [],
|
|
284
|
+
checked: redactOperationalPayload(result?.checked ?? {}),
|
|
285
|
+
claimBoundary: result?.claim_boundary ?? [],
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function publicSiteSecurityErrorMessage(summary) {
|
|
290
|
+
const blockerText = summary.blockers
|
|
291
|
+
.slice(0, 5)
|
|
292
|
+
.map((entry) => (entry.path ? `${entry.path}: ${entry.message}` : entry.message))
|
|
293
|
+
.join('; ');
|
|
294
|
+
return blockerText.length > 0
|
|
295
|
+
? `public site security validation blocked Pages deploy: ${blockerText}`
|
|
296
|
+
: 'public site security validation blocked Pages deploy';
|
|
297
|
+
}
|
|
298
|
+
|
|
267
299
|
function parsePositiveInteger(value, name) {
|
|
268
300
|
const text = requireNonEmptyString(name, value);
|
|
269
301
|
if (!/^\d+$/.test(text)) throw new UsageError(`${name} must be a positive integer`);
|
|
@@ -1518,6 +1550,7 @@ export async function runCloudflareOpsCommand(command, {
|
|
|
1518
1550
|
|
|
1519
1551
|
if (command.kind === 'pages.deploy') {
|
|
1520
1552
|
const plan = buildWranglerPagesDeployPlan(command);
|
|
1553
|
+
const siteSecurity = publicSiteSecurityDeploySummary(await validatePublicSiteSecurity({ site: command.site }));
|
|
1521
1554
|
if (!command.execute) {
|
|
1522
1555
|
return {
|
|
1523
1556
|
json: {
|
|
@@ -1526,10 +1559,12 @@ export async function runCloudflareOpsCommand(command, {
|
|
|
1526
1559
|
dryRun: true,
|
|
1527
1560
|
execute: false,
|
|
1528
1561
|
plan: redactPlanOutput(plan),
|
|
1562
|
+
siteSecurity,
|
|
1529
1563
|
claimBoundary: 'Plan only; no Cloudflare Pages deployment was executed.',
|
|
1530
1564
|
},
|
|
1531
1565
|
};
|
|
1532
1566
|
}
|
|
1567
|
+
if (!siteSecurity.ok) throw new UsageError(publicSiteSecurityErrorMessage(siteSecurity));
|
|
1533
1568
|
const result = await execFileImpl(plan.command, plan.args, { shell: plan.usesShell === true, windowsHide: true, maxBuffer: 10 * 1024 * 1024, env });
|
|
1534
1569
|
return {
|
|
1535
1570
|
json: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import https from 'node:https';
|
|
2
3
|
import { createHash } from 'node:crypto';
|
|
3
4
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
5
|
import { dirname, resolve } from 'node:path';
|
|
@@ -81,6 +82,42 @@ function redactProbeBody(value, path = 'probe.body') {
|
|
|
81
82
|
return value;
|
|
82
83
|
}
|
|
83
84
|
|
|
85
|
+
export function localSimulationLoopbackFetch(url, init = {}) {
|
|
86
|
+
const parsed = new URL(url);
|
|
87
|
+
const host = parsed.hostname.toLowerCase();
|
|
88
|
+
if (parsed.protocol !== 'https:' || (host !== 'sim.enigmamemory.com' && !host.endsWith('.sim.enigmamemory.com'))) {
|
|
89
|
+
throw new Error('--local-simulation-loopback only supports https://*.sim.enigmamemory.com simulation probes');
|
|
90
|
+
}
|
|
91
|
+
const request = {
|
|
92
|
+
hostname: '127.0.0.1',
|
|
93
|
+
port: parsed.port || 443,
|
|
94
|
+
path: `${parsed.pathname}${parsed.search}`,
|
|
95
|
+
method: init.method || 'GET',
|
|
96
|
+
headers: init.headers,
|
|
97
|
+
rejectUnauthorized: false,
|
|
98
|
+
servername: parsed.hostname,
|
|
99
|
+
};
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
const req = https.request(request, (res) => {
|
|
102
|
+
const chunks = [];
|
|
103
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
104
|
+
res.on('end', () => {
|
|
105
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
106
|
+
resolve({
|
|
107
|
+
ok: res.statusCode >= 200 && res.statusCode < 300,
|
|
108
|
+
status: res.statusCode,
|
|
109
|
+
statusText: res.statusMessage || '',
|
|
110
|
+
url,
|
|
111
|
+
redirected: false,
|
|
112
|
+
text: async () => text,
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
req.on('error', reject);
|
|
117
|
+
req.end();
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
84
121
|
async function fetchProbe(url, { fetchImpl = globalThis.fetch, observedAt }) {
|
|
85
122
|
if (typeof fetchImpl !== 'function') throw new Error('global fetch is not available in this Node runtime');
|
|
86
123
|
const response = await fetchImpl(url, {
|
|
@@ -189,6 +226,10 @@ function parseArgs(argv) {
|
|
|
189
226
|
}
|
|
190
227
|
if (!arg.startsWith('--')) throw new Error(`Unexpected argument: ${arg}`);
|
|
191
228
|
const name = arg.slice(2);
|
|
229
|
+
if (name === 'local-simulation-loopback') {
|
|
230
|
+
flags.set(name, true);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
192
233
|
const value = argv[index + 1];
|
|
193
234
|
if (!value || value.startsWith('--')) throw new Error(`${arg} requires a value`);
|
|
194
235
|
flags.set(name, value);
|
|
@@ -198,7 +239,7 @@ function parseArgs(argv) {
|
|
|
198
239
|
}
|
|
199
240
|
|
|
200
241
|
function usage() {
|
|
201
|
-
return `Usage: node scripts/collect-hosted-backend-live-evidence.mjs --relay-url <https-base> --gateway-url <https-base> --refs-json <refs.json> --domain <domain> --environment-id <id> --cloud-provider <provider> --region <region> --owner <owner> --operator-decision go --operator-packet-ref <ref> --operator-approved-at <iso> --operator-approved-by <name> [--out <collection.json>] [--evidence-out <evidence.json>]\n\nCollects public HTTPS /livez and /readyz evidence for relay and gateway, then validates it with validate-hosted-backend-live. It never sends credentials and does not deploy infrastructure.\n`;
|
|
242
|
+
return `Usage: node scripts/collect-hosted-backend-live-evidence.mjs --relay-url <https-base> --gateway-url <https-base> --refs-json <refs.json> --domain <domain> --environment-id <id> --cloud-provider <provider> --region <region> --owner <owner> --operator-decision go --operator-packet-ref <ref> --operator-approved-at <iso> --operator-approved-by <name> [--out <collection.json>] [--evidence-out <evidence.json>] [--local-simulation-loopback]\n\nCollects public HTTPS /livez and /readyz evidence for relay and gateway, then validates it with validate-hosted-backend-live. It never sends credentials and does not deploy infrastructure. The --local-simulation-loopback flag is restricted to https://*.sim.enigmamemory.com local simulation probes with self-signed TLS and must not be used as production evidence.\n`;
|
|
202
243
|
}
|
|
203
244
|
|
|
204
245
|
async function runCli(argv = process.argv.slice(2), { fetchImpl = globalThis.fetch } = {}) {
|
|
@@ -212,6 +253,7 @@ async function runCli(argv = process.argv.slice(2), { fetchImpl = globalThis.fet
|
|
|
212
253
|
const refs = await readJsonFile(refsPath);
|
|
213
254
|
const environment = await maybeReadJsonFile(readFlag(flags, 'environment-json'));
|
|
214
255
|
const operatorAcceptance = await maybeReadJsonFile(readFlag(flags, 'operator-acceptance-json'));
|
|
256
|
+
const selectedFetchImpl = flags.get('local-simulation-loopback') === true ? localSimulationLoopbackFetch : fetchImpl;
|
|
215
257
|
const collection = await collectHostedBackendLiveEvidence({
|
|
216
258
|
relayBaseUrl: readFlag(flags, 'relay-url'),
|
|
217
259
|
gatewayBaseUrl: readFlag(flags, 'gateway-url'),
|
|
@@ -233,7 +275,7 @@ async function runCli(argv = process.argv.slice(2), { fetchImpl = globalThis.fet
|
|
|
233
275
|
operatorApprovedAt: readFlag(flags, 'operator-approved-at'),
|
|
234
276
|
operatorApprovedBy: readFlag(flags, 'operator-approved-by'),
|
|
235
277
|
observed_at: readFlag(flags, 'observed-at') ?? new Date().toISOString(),
|
|
236
|
-
fetchImpl,
|
|
278
|
+
fetchImpl: selectedFetchImpl,
|
|
237
279
|
});
|
|
238
280
|
const collectionJson = `${JSON.stringify(collection, null, 2)}\n`;
|
|
239
281
|
const evidenceJson = `${JSON.stringify(collection.evidence, null, 2)}\n`;
|
|
@@ -832,6 +832,11 @@ export function runMemoryBenchmarkSuite(options = {}) {
|
|
|
832
832
|
credentials_required: false,
|
|
833
833
|
external_downloads_required: false,
|
|
834
834
|
external_provider_calls: false,
|
|
835
|
+
llm_answer_accuracy_scored: false,
|
|
836
|
+
provider_api_calls_made: false,
|
|
837
|
+
api_spend_possible: false,
|
|
838
|
+
mem0_adapter_run: false,
|
|
839
|
+
external_competitor_adapters_run: false,
|
|
835
840
|
raw_private_memory_plaintext_included: false,
|
|
836
841
|
provider_deletion_claim: false,
|
|
837
842
|
model_forgetting_claim: false,
|