enigma-memory 0.1.13 → 0.1.15
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 +36 -17
- package/apps/cli/bin/enigma.mjs +3126 -2848
- package/deploy/docker-compose.local-production-simulation.yml +12 -10
- package/docs/benchmark-attestation-network.md +487 -487
- package/docs/benchmark-reproducibility.md +228 -227
- package/docs/demo-proof-network.md +275 -275
- package/docs/developer-ecosystem.md +223 -223
- package/docs/developer-proof-quickstart.md +325 -325
- package/docs/enigma-memory-ready-conformance.md +376 -376
- package/docs/hosted-cloud-product.md +10 -0
- package/docs/install-anywhere.md +34 -17
- package/docs/installers-and-desktop.md +9 -7
- package/docs/proof-network-build-notes.md +240 -240
- package/docs/proof-network.md +257 -257
- package/docs/sdk-api.md +324 -324
- package/docs/solana-devnet-acceptance.md +48 -0
- package/docs/solana-proof-rail.md +453 -453
- package/examples/ci/github-actions.yml +6 -8
- package/package.json +272 -265
- package/packages/mcp-server/src/index.js +1185 -1185
- package/packages/passport/src/index.js +9 -5
- package/scripts/build-benchmark-proof-release.mjs +391 -0
- package/scripts/build-goal-completion-audit.mjs +11 -5
- 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 -273
- package/scripts/build-production-handoff-packet.mjs +7 -6
- package/scripts/build-production-unblocker.mjs +409 -0
- package/scripts/build-proof-network-packet.mjs +213 -213
- package/scripts/release-audit.mjs +71 -2
- package/scripts/run-standard-memory-benchmarks.mjs +1070 -1070
- package/scripts/wait-for-backend-ready.mjs +4 -2
|
@@ -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.15';
|
|
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
|
+
}
|
|
@@ -136,6 +136,10 @@ const KUBERNETES_BACKEND_MANIFEST = resolve(PROJECT_ROOT, 'deploy', 'kubernetes'
|
|
|
136
136
|
const ENIGMA_INFRASTRUCTURE_READINESS_MANIFEST = 'ENIGMA_INFRASTRUCTURE_READINESS_MANIFEST';
|
|
137
137
|
const ENIGMA_INFRASTRUCTURE_READINESS_LIVE = 'ENIGMA_INFRASTRUCTURE_READINESS_LIVE';
|
|
138
138
|
const SECRET_LOOKING_OUTPUT = /(?:Authorization:\s*Bearer\s+[A-Za-z0-9._~+/=-]{8,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|["']?(?:api[_-]?key|access[_-]?token|refresh[_-]?token|secret|password|private[_-]?key)["']?\s*[:=]\s*["']?[A-Za-z0-9._~+/=-]{16,})/i;
|
|
139
|
+
const TEST_FAILURE_SUMMARY_LIMIT = 8;
|
|
140
|
+
const TEST_OUTPUT_TAIL_LINE_LIMIT = 18;
|
|
141
|
+
const TEST_OUTPUT_TAIL_CHAR_LIMIT = 280;
|
|
142
|
+
const REDACTED_DIAGNOSTIC_LINE = '<redacted secret-looking output>';
|
|
139
143
|
|
|
140
144
|
function npmInvocation(args) {
|
|
141
145
|
const label = commandLabel('npm', args);
|
|
@@ -235,6 +239,68 @@ function tapCounts(output) {
|
|
|
235
239
|
return counts;
|
|
236
240
|
}
|
|
237
241
|
|
|
242
|
+
function sanitizeDiagnosticLine(value) {
|
|
243
|
+
const scrubbed = scrubLocalPathText(value)
|
|
244
|
+
.replace(/file:\/\/(?=<(?:project-root|public-site-package|temp|user-home|home)>)/g, '')
|
|
245
|
+
.replace(/[A-Za-z]:\/[^\s'"`),]+/g, '<path>')
|
|
246
|
+
.replace(/(?:file:\/\/)?\/(?:Users|home|tmp|private\/var|var\/folders)\/[^\s'"`),]+/g, '<path>')
|
|
247
|
+
.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '<email>')
|
|
248
|
+
.replace(/\s+/g, ' ')
|
|
249
|
+
.trim();
|
|
250
|
+
if (!scrubbed) return '';
|
|
251
|
+
if (
|
|
252
|
+
SECRET_LOOKING_OUTPUT.test(scrubbed)
|
|
253
|
+
|| RAW_MEMORY_EXAMPLE_FIELD.test(scrubbed)
|
|
254
|
+
|| scrubbed.includes(RAW_MEMORY_SENTINEL)
|
|
255
|
+
) return REDACTED_DIAGNOSTIC_LINE;
|
|
256
|
+
return scrubbed.length > TEST_OUTPUT_TAIL_CHAR_LIMIT
|
|
257
|
+
? `${scrubbed.slice(0, TEST_OUTPUT_TAIL_CHAR_LIMIT - 1)}…`
|
|
258
|
+
: scrubbed;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function diagnosticLines(value) {
|
|
262
|
+
return String(value).split(/\r?\n/).map(sanitizeDiagnosticLine).filter(Boolean);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function diagnosticMessage(value) {
|
|
266
|
+
return diagnosticLines(value)[0] ?? 'Command failed.';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function failingTestNames(output) {
|
|
270
|
+
const names = [];
|
|
271
|
+
for (const line of diagnosticLines(output)) {
|
|
272
|
+
const tapMatch = line.match(/^not ok \d+ - (.+)$/);
|
|
273
|
+
const prettyMatch = line.match(/^✖\s+(.+?)(?:\s+\(\d+(?:\.\d+)?ms\))?$/u);
|
|
274
|
+
const name = tapMatch?.[1] ?? prettyMatch?.[1] ?? null;
|
|
275
|
+
if (!name || names.includes(name)) continue;
|
|
276
|
+
names.push(name);
|
|
277
|
+
if (names.length >= TEST_FAILURE_SUMMARY_LIMIT) break;
|
|
278
|
+
}
|
|
279
|
+
return names;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function diagnosticTail(stdout, stderr) {
|
|
283
|
+
const stdoutLines = diagnosticLines(stdout);
|
|
284
|
+
if (stdoutLines.length > 0) {
|
|
285
|
+
return { key: 'stdout_tail', lines: stdoutLines.slice(-TEST_OUTPUT_TAIL_LINE_LIMIT) };
|
|
286
|
+
}
|
|
287
|
+
const stderrLines = diagnosticLines(stderr);
|
|
288
|
+
if (stderrLines.length > 0) {
|
|
289
|
+
return { key: 'stderr_tail', lines: stderrLines.slice(-TEST_OUTPUT_TAIL_LINE_LIMIT) };
|
|
290
|
+
}
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function summarizeNpmTestFailure(stdout, stderr) {
|
|
295
|
+
const combined = `${stdout}\n${stderr}`;
|
|
296
|
+
const summary = { tap: tapCounts(combined) };
|
|
297
|
+
const failed = failingTestNames(combined);
|
|
298
|
+
const tail = diagnosticTail(stdout, stderr);
|
|
299
|
+
if (failed.length > 0) summary.failing_tests = failed;
|
|
300
|
+
if (tail) summary[tail.key] = tail.lines;
|
|
301
|
+
return summary;
|
|
302
|
+
}
|
|
303
|
+
|
|
238
304
|
function summarizeCheck(stdout) {
|
|
239
305
|
const line = lines(stdout).find((item) => item.includes('enigma check ok')) ?? lines(stdout).at(-1) ?? '';
|
|
240
306
|
return { message: line };
|
|
@@ -490,9 +556,12 @@ async function runCommandGate(name, command, args, options = {}) {
|
|
|
490
556
|
gate.signal = error.signal ?? null;
|
|
491
557
|
gate.stderr_bytes = Buffer.byteLength(error.stderr ?? '');
|
|
492
558
|
gate.stdout_bytes = Buffer.byteLength(error.stdout ?? '');
|
|
559
|
+
if (options.summarizeFailure) {
|
|
560
|
+
gate.evidence = await options.summarizeFailure(error.stdout ?? '', error.stderr ?? '');
|
|
561
|
+
}
|
|
493
562
|
gate.error = {
|
|
494
563
|
code: error.killed ? 'COMMAND_TIMEOUT' : (error.code ?? 'COMMAND_FAILED'),
|
|
495
|
-
message: error.message,
|
|
564
|
+
message: options.summarizeFailure ? diagnosticMessage(error.message) : error.message,
|
|
496
565
|
};
|
|
497
566
|
if (gate.status === 0) {
|
|
498
567
|
gate.error.code = 'OUTPUT_VALIDATION_FAILED';
|
|
@@ -5484,7 +5553,7 @@ export async function runReleaseAudit() {
|
|
|
5484
5553
|
const test = await nodeTestInvocation();
|
|
5485
5554
|
const pack = npmInvocation(['pack', '--dry-run']);
|
|
5486
5555
|
gates.push(await runCommandGate('npm-check', check.command, check.args, { label: check.label, summarize: summarizeCheck }));
|
|
5487
|
-
gates.push(await runCommandGate('npm-test', test.command, test.args, { label: test.label, timeoutMs: TEST_TIMEOUT_MS, summarize: summarizeTests }));
|
|
5556
|
+
gates.push(await runCommandGate('npm-test', test.command, test.args, { label: test.label, timeoutMs: TEST_TIMEOUT_MS, summarize: summarizeTests, summarizeFailure: summarizeNpmTestFailure }));
|
|
5488
5557
|
gates.push(await runCommandGate('npm-pack-dry-run', pack.command, pack.args, { label: pack.label, summarize: summarizePack }));
|
|
5489
5558
|
gates.push(await runDirectBinSmokes());
|
|
5490
5559
|
gates.push(await runNativeHostInstallPlanGate());
|