enigma-memory 0.1.10 → 0.1.12
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 +38 -7
- package/apps/cli/bin/enigma.mjs +636 -49
- package/deploy/SIMULATION.md +152 -0
- package/deploy/docker-compose.local-production-simulation.yml +237 -0
- package/deploy/docker-compose.production.example.yml +19 -0
- package/deploy/kms-mock.mjs +64 -0
- package/deploy/nginx.local-production-simulation.conf +33 -0
- package/deploy/siem-mock.mjs +50 -0
- package/docs/benchmark-attestation-network.md +488 -0
- package/docs/benchmark-reproducibility.md +19 -2
- package/docs/blockchain-only-mechanisms.md +388 -0
- package/docs/demo-proof-network.md +275 -0
- package/docs/developer-ecosystem.md +62 -11
- package/docs/developer-proof-quickstart.md +325 -0
- package/docs/enigma-memory-ready-conformance.md +376 -0
- package/docs/enterprise-proof-control-plane.md +365 -0
- package/docs/market-category-narrative.md +398 -0
- package/docs/memory-drive-health-model.md +649 -0
- package/docs/memory-drive-strategy.md +458 -0
- package/docs/memory-passport-standard.md +445 -0
- package/docs/novelty-invention-candidates.md +161 -0
- package/docs/privacy-ledger-model.md +229 -0
- package/docs/proof-network-build-notes.md +240 -0
- package/docs/proof-network-claim-boundaries.md +318 -0
- package/docs/proof-network-dashboard-spec.md +773 -0
- package/docs/proof-network-glossary.md +27 -0
- package/docs/proof-network-launch-plan.md +421 -0
- package/docs/proof-network-operator-protocol.md +432 -0
- package/docs/proof-network-roadmap.md +431 -0
- package/docs/proof-network-test-plan.md +216 -0
- package/docs/proof-network-threat-model.md +373 -0
- package/docs/proof-network.md +257 -0
- package/docs/sdk-api.md +130 -10
- package/docs/solana-devnet-acceptance.md +226 -0
- package/docs/solana-proof-rail.md +453 -0
- package/examples/proof-network-anchor.json +37 -0
- package/examples/proof-network-attestation.json +35 -0
- package/examples/proof-network-grant.json +27 -0
- package/examples/proof-network-packet.json +71 -0
- package/package.json +40 -4
- package/packages/mcp-server/src/index.js +1 -1
- package/packages/proof-network/src/index.js +570 -0
- package/scripts/build-hosted-api-key-lifecycle.mjs +1 -1
- package/scripts/build-hosted-customer-lifecycle.mjs +1 -1
- package/scripts/build-installer-assets.mjs +1 -1
- package/scripts/build-proof-network-packet.mjs +213 -0
- package/scripts/run-standard-memory-benchmarks.mjs +1 -1
- package/scripts/simulate-production-env.mjs +210 -0
- package/scripts/wait-for-backend-ready.mjs +101 -0
- package/specs/goal-completion-audit-v1.schema.json +1 -0
- package/specs/proof-network-anchor-batch-v1.schema.json +125 -0
- package/specs/proof-network-benchmark-attestation-v1.schema.json +103 -0
- package/specs/proof-network-capability-grant-v1.schema.json +132 -0
- package/specs/proof-network-packet-v1.schema.json +171 -0
- package/scripts/install-enigma-local.mjs +0 -270
package/apps/cli/bin/enigma.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from 'node:crypto';
|
|
|
3
3
|
import { createServer as createHttpServer } from 'node:http';
|
|
4
4
|
import { realpathSync } from 'node:fs';
|
|
5
5
|
import { access, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
|
|
6
|
-
import { dirname, resolve } from 'node:path';
|
|
6
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
7
7
|
import { pathToFileURL } from 'node:url';
|
|
8
8
|
import { createVault, remember, recall, updateMemory, deleteMemory, exportBundle } from '../../../packages/vault/src/index.js';
|
|
9
9
|
import { createPassport, compileContextPack } from '../../../packages/passport/src/index.js';
|
|
@@ -30,8 +30,24 @@ import {
|
|
|
30
30
|
createSettlementBatch,
|
|
31
31
|
verifyServiceSettlementReceipt,
|
|
32
32
|
} from '../../../packages/settlement/src/index.js';
|
|
33
|
+
import {
|
|
34
|
+
assertNoPrivateProofPayload,
|
|
35
|
+
createBenchmarkAttestation,
|
|
36
|
+
createCapabilityGrant,
|
|
37
|
+
createCapabilityRevocation,
|
|
38
|
+
createProofNetworkAnchorBatch,
|
|
39
|
+
sha256Json as proofNetworkSha256Json,
|
|
40
|
+
validateBenchmarkAttestation,
|
|
41
|
+
validateCapabilityGrant,
|
|
42
|
+
validateCapabilityRevocation,
|
|
43
|
+
validateProofNetworkAnchorBatch,
|
|
44
|
+
validateProofNetworkPacket,
|
|
45
|
+
} from '../../../packages/proof-network/src/index.js';
|
|
33
46
|
|
|
34
47
|
const DEFAULT_BUNDLE = '.enigma/bundle.json';
|
|
48
|
+
const DEFAULT_TEST_DRIVE_DIR = '.enigma/test-drive';
|
|
49
|
+
const DEFAULT_TEST_DRIVE_BUNDLE_NAME = 'bundle.json';
|
|
50
|
+
const DEFAULT_TEST_DRIVE_CROSS_MODEL_REPORT_NAME = 'cross-model-report.json';
|
|
35
51
|
export const DEFAULT_RELAY_PORT = 8787;
|
|
36
52
|
export const DEFAULT_GATEWAY_PORT = 8797;
|
|
37
53
|
const DEFAULT_QUICKSTART_MEMORY = 'Enigma quickstart demo memory: local proof bundles can be created and verified without provider or cloud credentials.';
|
|
@@ -279,10 +295,10 @@ function quickstartOutputs(bundleInput, outDirInput) {
|
|
|
279
295
|
};
|
|
280
296
|
}
|
|
281
297
|
|
|
282
|
-
async function buildQuickstartArtifacts(flags, { bundleInput = DEFAULT_BUNDLE, outDirInput = dirname(bundleInput), overwrite = false, write = true } = {}) {
|
|
298
|
+
async function buildQuickstartArtifacts(flags, { bundleInput = DEFAULT_BUNDLE, outDirInput = dirname(bundleInput), overwrite = false, write = true, checkExisting = true } = {}) {
|
|
283
299
|
const paths = quickstartOutputs(bundleInput, outDirInput);
|
|
284
300
|
ensureDistinctOutputPaths(paths.outputs.map((output) => output.path));
|
|
285
|
-
await assertCanWriteQuickstartOutputs(paths.outputs, overwrite);
|
|
301
|
+
if (checkExisting) await assertCanWriteQuickstartOutputs(paths.outputs, overwrite);
|
|
286
302
|
|
|
287
303
|
const vault = createVault({
|
|
288
304
|
subjectId: String(getFlag(flags, ['subject', 'subject-id'], 'local-user')),
|
|
@@ -1133,6 +1149,39 @@ export async function quickstartCommand(flags, io) {
|
|
|
1133
1149
|
return artifacts.verifyReport.ok === true ? 0 : 1;
|
|
1134
1150
|
}
|
|
1135
1151
|
|
|
1152
|
+
function buildCrossModelProfileSummaries({ vault, passport, demoMemoryAddr, limit }) {
|
|
1153
|
+
const profiles = [];
|
|
1154
|
+
for (const profile of CROSS_MODEL_PROFILES) {
|
|
1155
|
+
const pack = compileContextPack({
|
|
1156
|
+
vault,
|
|
1157
|
+
passport,
|
|
1158
|
+
provider: profile.provider,
|
|
1159
|
+
model: profile.model,
|
|
1160
|
+
query: 'memory follows me across models',
|
|
1161
|
+
purpose: `cross_model_demo:${profile.id}`,
|
|
1162
|
+
memory_addresses: [demoMemoryAddr],
|
|
1163
|
+
limit,
|
|
1164
|
+
});
|
|
1165
|
+
const contextPack = publicContextPackSummary(pack);
|
|
1166
|
+
profiles.push({
|
|
1167
|
+
profile: profile.id,
|
|
1168
|
+
label: profile.label,
|
|
1169
|
+
provider: profile.provider,
|
|
1170
|
+
model: profile.model,
|
|
1171
|
+
context_pack_ref: contextPack.context_pack_ref,
|
|
1172
|
+
context_pack_id: contextPack.context_pack_id,
|
|
1173
|
+
context_pack_digest: contextPack.context_pack_digest,
|
|
1174
|
+
context_pack: contextPack,
|
|
1175
|
+
receipt_count: contextPack.receipt_count,
|
|
1176
|
+
memory_count: contextPack.memory_count,
|
|
1177
|
+
provider_native_memory_canonical: false,
|
|
1178
|
+
receipts: contextPack.receipts,
|
|
1179
|
+
claim_boundaries: { ...CROSS_MODEL_CLAIM_BOUNDARIES },
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
return profiles;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1136
1185
|
export async function crossModelDemoCommand(flags, io) {
|
|
1137
1186
|
const bundleFlag = getFlag(flags, ['bundle', 'file']);
|
|
1138
1187
|
if (bundleFlag === true || bundleFlag === '') throw new Error('Missing required --bundle.');
|
|
@@ -1189,35 +1238,7 @@ export async function crossModelDemoCommand(flags, io) {
|
|
|
1189
1238
|
const limit = integerFlag(flags, ['limit'], 'limit', 1);
|
|
1190
1239
|
if (limit < 1) throw new Error('--limit must be at least 1.');
|
|
1191
1240
|
const receiptCountBeforeProfiles = Array.isArray(vault.receipts) ? vault.receipts.length : 0;
|
|
1192
|
-
const profiles =
|
|
1193
|
-
for (const profile of CROSS_MODEL_PROFILES) {
|
|
1194
|
-
const pack = compileContextPack({
|
|
1195
|
-
vault,
|
|
1196
|
-
passport,
|
|
1197
|
-
provider: profile.provider,
|
|
1198
|
-
model: profile.model,
|
|
1199
|
-
query: 'memory follows me across models',
|
|
1200
|
-
purpose: `cross_model_demo:${profile.id}`,
|
|
1201
|
-
memory_addresses: [demoMemoryAddr],
|
|
1202
|
-
limit,
|
|
1203
|
-
});
|
|
1204
|
-
const contextPack = publicContextPackSummary(pack);
|
|
1205
|
-
profiles.push({
|
|
1206
|
-
profile: profile.id,
|
|
1207
|
-
label: profile.label,
|
|
1208
|
-
provider: profile.provider,
|
|
1209
|
-
model: profile.model,
|
|
1210
|
-
context_pack_ref: contextPack.context_pack_ref,
|
|
1211
|
-
context_pack_id: contextPack.context_pack_id,
|
|
1212
|
-
context_pack_digest: contextPack.context_pack_digest,
|
|
1213
|
-
context_pack: contextPack,
|
|
1214
|
-
receipt_count: contextPack.receipt_count,
|
|
1215
|
-
memory_count: contextPack.memory_count,
|
|
1216
|
-
provider_native_memory_canonical: false,
|
|
1217
|
-
receipts: contextPack.receipts,
|
|
1218
|
-
claim_boundaries: { ...CROSS_MODEL_CLAIM_BOUNDARIES },
|
|
1219
|
-
});
|
|
1220
|
-
}
|
|
1241
|
+
const profiles = buildCrossModelProfileSummaries({ vault, passport, demoMemoryAddr, limit });
|
|
1221
1242
|
|
|
1222
1243
|
const bundle = await persistState(bundlePath, vault);
|
|
1223
1244
|
const report = {
|
|
@@ -1327,20 +1348,14 @@ async function contextCommand(flags, io) {
|
|
|
1327
1348
|
}
|
|
1328
1349
|
|
|
1329
1350
|
|
|
1330
|
-
|
|
1331
|
-
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1332
|
-
const query = String(requireFlag(flags, ['query', 'q'], 'query'));
|
|
1333
|
-
const limit = integerFlag(flags, ['limit'], 'limit', 8);
|
|
1334
|
-
if (limit < 0) throw new Error('--limit must be non-negative.');
|
|
1335
|
-
const includeContent = getFlag(flags, ['include-content', 'includeContent']) === true || getFlag(flags, ['include-content', 'includeContent']) === 'true';
|
|
1336
|
-
const { vault } = await loadState(bundlePath);
|
|
1351
|
+
function memorySearchReport({ bundlePath, vault, query, limit, includeContent = false, now = '2026-01-01T00:00:00.000Z' }) {
|
|
1337
1352
|
const roots = vault.__computeRoots();
|
|
1338
1353
|
const queryTokens = searchTokensFrom(query);
|
|
1339
1354
|
const { candidates, byAddress } = searchCandidates(vault, queryTokens);
|
|
1340
1355
|
const plan = createMemoryOptimizationPlan({
|
|
1341
1356
|
candidates,
|
|
1342
1357
|
prompt: query,
|
|
1343
|
-
now
|
|
1358
|
+
now,
|
|
1344
1359
|
});
|
|
1345
1360
|
const planIndex = new Map(plan.items.map((item, index) => [item.address, index]));
|
|
1346
1361
|
const selectedItems = plan.items
|
|
@@ -1381,7 +1396,7 @@ async function searchCommand(flags, io) {
|
|
|
1381
1396
|
...(includeContent ? { content: hit.content } : {}),
|
|
1382
1397
|
};
|
|
1383
1398
|
});
|
|
1384
|
-
|
|
1399
|
+
return {
|
|
1385
1400
|
ok: true,
|
|
1386
1401
|
schema: 'enigma.memory_search.v1',
|
|
1387
1402
|
bundle: bundlePath,
|
|
@@ -1395,18 +1410,33 @@ async function searchCommand(flags, io) {
|
|
|
1395
1410
|
claim_boundary: includeContent
|
|
1396
1411
|
? 'Search ran against the selected local bundle and includes plaintext only because --include-content was explicit; this does not prove provider deletion, provider-native memory state, or model forgetting.'
|
|
1397
1412
|
: 'Search ran against the selected local bundle and redacts plaintext by default; refs, scores, tags, roots, and receipt refs are not provider deletion proof or model forgetting proof.',
|
|
1398
|
-
}
|
|
1399
|
-
return 0;
|
|
1413
|
+
};
|
|
1400
1414
|
}
|
|
1401
1415
|
|
|
1402
|
-
async function
|
|
1416
|
+
async function searchCommand(flags, io) {
|
|
1403
1417
|
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1404
|
-
const
|
|
1418
|
+
const query = String(requireFlag(flags, ['query', 'q'], 'query'));
|
|
1419
|
+
const limit = integerFlag(flags, ['limit'], 'limit', 8);
|
|
1420
|
+
if (limit < 0) throw new Error('--limit must be non-negative.');
|
|
1421
|
+
const includeContent = getFlag(flags, ['include-content', 'includeContent']) === true || getFlag(flags, ['include-content', 'includeContent']) === 'true';
|
|
1422
|
+
const { vault } = await loadState(bundlePath);
|
|
1423
|
+
print(memorySearchReport({
|
|
1424
|
+
bundlePath,
|
|
1425
|
+
vault,
|
|
1426
|
+
query,
|
|
1427
|
+
limit,
|
|
1428
|
+
includeContent,
|
|
1429
|
+
now: getFlag(flags, ['now'], '2026-01-01T00:00:00.000Z'),
|
|
1430
|
+
}), io);
|
|
1431
|
+
return 0;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
function passportStatusReport({ bundlePath, stored = {}, vault, passport }) {
|
|
1405
1435
|
const roots = vault.__computeRoots();
|
|
1406
1436
|
const activeCount = activeMemoryCount(vault);
|
|
1407
1437
|
const tombstoneCount = vault.tombstones instanceof Map ? vault.tombstones.size : 0;
|
|
1408
1438
|
const receiptCount = Array.isArray(vault.receipts) ? vault.receipts.length : 0;
|
|
1409
|
-
|
|
1439
|
+
return {
|
|
1410
1440
|
ok: true,
|
|
1411
1441
|
schema: 'enigma.passport_status.v1',
|
|
1412
1442
|
bundle: bundlePath,
|
|
@@ -1434,10 +1464,317 @@ async function statusCommand(flags, io) {
|
|
|
1434
1464
|
`enigma connect <client> --bundle "${bundlePath}"`,
|
|
1435
1465
|
],
|
|
1436
1466
|
claim_boundary: 'Status reports local bundle counters, owner display fields, connector readiness hints, and commitment roots only; it does not expose raw memory, certify compliance, prove provider deletion, or prove model forgetting.',
|
|
1437
|
-
}
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
async function statusCommand(flags, io) {
|
|
1471
|
+
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1472
|
+
const { stored, vault, passport } = await loadState(bundlePath);
|
|
1473
|
+
print(passportStatusReport({ bundlePath, stored, vault, passport }), io);
|
|
1438
1474
|
return 0;
|
|
1439
1475
|
}
|
|
1440
1476
|
|
|
1477
|
+
function testDrivePathDisplay(outDirInput, name) {
|
|
1478
|
+
return isAbsolute(outDirInput) ? join(outDirInput, name) : quickstartPathDisplay(outDirInput, name);
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
function testDriveBundleDisplay(outDirInput) {
|
|
1482
|
+
return testDrivePathDisplay(outDirInput, DEFAULT_TEST_DRIVE_BUNDLE_NAME);
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
function testDriveOutputs(outDirInput, bundleInput = testDriveBundleDisplay(outDirInput)) {
|
|
1486
|
+
const quickstart = quickstartOutputs(bundleInput, outDirInput);
|
|
1487
|
+
const contextPackDisplay = testDrivePathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.contextPack);
|
|
1488
|
+
const exportDisplay = testDrivePathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.export);
|
|
1489
|
+
const verifyReportDisplay = testDrivePathDisplay(outDirInput, QUICKSTART_ARTIFACT_NAMES.verifyReport);
|
|
1490
|
+
const crossModelReportDisplay = testDrivePathDisplay(outDirInput, DEFAULT_TEST_DRIVE_CROSS_MODEL_REPORT_NAME);
|
|
1491
|
+
const crossModelReportPath = resolve(quickstart.outDirPath, DEFAULT_TEST_DRIVE_CROSS_MODEL_REPORT_NAME);
|
|
1492
|
+
const artifacts = [
|
|
1493
|
+
{ role: 'bundle', path: quickstart.bundlePath, display: bundleInput, schema: 'enigma.bundle.v1' },
|
|
1494
|
+
{ role: 'context_pack', path: quickstart.contextPackPath, display: contextPackDisplay, schema: 'enigma.context_pack.v1' },
|
|
1495
|
+
{ role: 'export', path: quickstart.exportPath, display: exportDisplay, schema: 'enigma.bundle.v1' },
|
|
1496
|
+
{ role: 'verify_report', path: quickstart.verifyReportPath, display: verifyReportDisplay, schema: 'enigma.verify_report.v1' },
|
|
1497
|
+
{ role: 'cross_model_report', path: crossModelReportPath, display: crossModelReportDisplay, schema: 'enigma.cross_model_demo.v1' },
|
|
1498
|
+
];
|
|
1499
|
+
return {
|
|
1500
|
+
...quickstart,
|
|
1501
|
+
contextPackDisplay,
|
|
1502
|
+
exportDisplay,
|
|
1503
|
+
verifyReportDisplay,
|
|
1504
|
+
crossModelReportPath,
|
|
1505
|
+
crossModelReportDisplay,
|
|
1506
|
+
artifacts,
|
|
1507
|
+
outputs: artifacts.map((artifact) => ({ path: artifact.path, display: artifact.display })),
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
function testDriveFileSummaries(artifacts, written) {
|
|
1512
|
+
return artifacts.map((artifact) => ({
|
|
1513
|
+
role: artifact.role,
|
|
1514
|
+
path: artifact.display,
|
|
1515
|
+
schema: artifact.schema,
|
|
1516
|
+
written: Boolean(written),
|
|
1517
|
+
}));
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
function firstActiveMemoryAddress(vault) {
|
|
1521
|
+
if (!(vault.activeAddresses instanceof Set)) throw new Error('Test drive vault did not expose an active memory set.');
|
|
1522
|
+
const first = vault.activeAddresses.values().next();
|
|
1523
|
+
if (first.done) throw new Error('Test drive vault did not create a demo memory.');
|
|
1524
|
+
return first.value;
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
function testDriveNextCommands(bundleDisplay, crossModelReportDisplay) {
|
|
1528
|
+
const quotedBundle = commandPath(bundleDisplay);
|
|
1529
|
+
const quotedReport = commandPath(crossModelReportDisplay);
|
|
1530
|
+
return [
|
|
1531
|
+
`enigma status --bundle ${quotedBundle}`,
|
|
1532
|
+
`enigma search --bundle ${quotedBundle} --query "local proof bundle"`,
|
|
1533
|
+
`enigma demo cross-model --bundle ${quotedBundle} --out ${quotedReport}`,
|
|
1534
|
+
'node scripts/run-memory-benchmarks.mjs',
|
|
1535
|
+
];
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
function testDriveFlowCommands({ bundleDisplay, outDirInput, crossModelReportDisplay, overwrite }) {
|
|
1539
|
+
const overwriteSuffix = overwrite ? ' --overwrite' : '';
|
|
1540
|
+
const quotedBundle = commandPath(bundleDisplay);
|
|
1541
|
+
const quotedOutDir = commandPath(outDirInput);
|
|
1542
|
+
const quotedReport = commandPath(crossModelReportDisplay);
|
|
1543
|
+
return [
|
|
1544
|
+
`enigma quickstart --bundle ${quotedBundle} --out-dir ${quotedOutDir}${overwriteSuffix}`,
|
|
1545
|
+
`enigma status --bundle ${quotedBundle}`,
|
|
1546
|
+
`enigma search --bundle ${quotedBundle} --query "local proof bundle"`,
|
|
1547
|
+
`enigma demo cross-model --bundle ${quotedBundle} --out ${quotedReport}`,
|
|
1548
|
+
];
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
function testDriveBenchmarkPointers() {
|
|
1552
|
+
return [
|
|
1553
|
+
{
|
|
1554
|
+
command: 'node scripts/run-memory-benchmarks.mjs',
|
|
1555
|
+
public_safe: true,
|
|
1556
|
+
planned_only: true,
|
|
1557
|
+
requires_repo_checkout: true,
|
|
1558
|
+
external_provider_calls: false,
|
|
1559
|
+
raw_memory_included: false,
|
|
1560
|
+
claim_boundary: 'Runs deterministic local fixture operations only; it is not a provider comparison, hosted service proof, benchmark leadership claim, ROI claim, provider deletion proof, or model forgetting proof.',
|
|
1561
|
+
},
|
|
1562
|
+
{
|
|
1563
|
+
command: 'node scripts/download-standard-benchmarks.mjs --dry-run',
|
|
1564
|
+
public_safe: true,
|
|
1565
|
+
planned_only: true,
|
|
1566
|
+
requires_repo_checkout: true,
|
|
1567
|
+
external_provider_calls: false,
|
|
1568
|
+
raw_memory_included: false,
|
|
1569
|
+
claim_boundary: 'Plans official dataset downloads without fetching by default; raw benchmark records are not included in the public plan.',
|
|
1570
|
+
},
|
|
1571
|
+
{
|
|
1572
|
+
command: 'node scripts/run-standard-memory-benchmarks.mjs --locomo <path> --longmemeval <path>',
|
|
1573
|
+
public_safe: true,
|
|
1574
|
+
planned_only: true,
|
|
1575
|
+
requires_repo_checkout: true,
|
|
1576
|
+
external_provider_calls: false,
|
|
1577
|
+
raw_memory_included: false,
|
|
1578
|
+
claim_boundary: 'Runs local deterministic retrieval proxies against operator-supplied dataset files; it emits no provider API calls, competitor scores, benchmark leadership claim, or model-forgetting claim.',
|
|
1579
|
+
},
|
|
1580
|
+
];
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
function testDriveClaimBoundaries() {
|
|
1584
|
+
return {
|
|
1585
|
+
local_only: true,
|
|
1586
|
+
credentials_required: false,
|
|
1587
|
+
external_provider_calls: false,
|
|
1588
|
+
client_config_writes_performed: false,
|
|
1589
|
+
plaintext_memory_echoed: false,
|
|
1590
|
+
hosted_saas_live_claim: false,
|
|
1591
|
+
provider_native_memory_canonical: false,
|
|
1592
|
+
provider_deletion_proof: false,
|
|
1593
|
+
model_forgetting_proof: false,
|
|
1594
|
+
benchmark_leadership_claim: false,
|
|
1595
|
+
compliance_certification: false,
|
|
1596
|
+
};
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
function publicTestDriveStatusSummary(summary, bundleDisplay) {
|
|
1600
|
+
return {
|
|
1601
|
+
...summary,
|
|
1602
|
+
bundle: bundleDisplay,
|
|
1603
|
+
connector_readiness: {
|
|
1604
|
+
...summary.connector_readiness,
|
|
1605
|
+
bundle: bundleDisplay,
|
|
1606
|
+
},
|
|
1607
|
+
next_recommended_commands: [
|
|
1608
|
+
`enigma remember --bundle ${commandPath(bundleDisplay)} --text-file <path>`,
|
|
1609
|
+
`enigma search --bundle ${commandPath(bundleDisplay)} --query <text>`,
|
|
1610
|
+
`enigma context --bundle ${commandPath(bundleDisplay)} --query <text>`,
|
|
1611
|
+
`enigma verify --bundle ${commandPath(bundleDisplay)}`,
|
|
1612
|
+
`enigma connect <client> --bundle ${commandPath(bundleDisplay)}`,
|
|
1613
|
+
],
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
function publicTestDriveSearchSummary(summary, bundleDisplay) {
|
|
1618
|
+
return {
|
|
1619
|
+
...summary,
|
|
1620
|
+
bundle: bundleDisplay,
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
function staticSetupSelection(requestedSelection) {
|
|
1625
|
+
return {
|
|
1626
|
+
...requestedSelection,
|
|
1627
|
+
fallback_used: false,
|
|
1628
|
+
selected: requestedSelection.clients.map((clientId) => {
|
|
1629
|
+
const profile = getClientProfile(clientId);
|
|
1630
|
+
return publicSetupClientSelectionEntry({ client_id: clientId, display_name: profile.display_name }, requestedSelection.mode === 'default' ? 'default_setup_client' : 'explicit_client');
|
|
1631
|
+
}),
|
|
1632
|
+
skipped: [],
|
|
1633
|
+
connectable_client_ids: null,
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
export async function testDriveCommand(flags, io) {
|
|
1638
|
+
const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], DEFAULT_TEST_DRIVE_DIR);
|
|
1639
|
+
const bundleInput = pathFlag(flags, ['bundle', 'file'], testDriveBundleDisplay(outDirInput));
|
|
1640
|
+
const overwrite = booleanFlag(flags, ['overwrite'], false);
|
|
1641
|
+
const dryRun = booleanFlag(flags, ['dry-run', 'dryRun'], false);
|
|
1642
|
+
const outputs = testDriveOutputs(outDirInput, bundleInput);
|
|
1643
|
+
ensureDistinctOutputPaths(outputs.outputs.map((output) => output.path));
|
|
1644
|
+
if (!dryRun) await assertCanWriteQuickstartOutputs(outputs.outputs, overwrite);
|
|
1645
|
+
|
|
1646
|
+
const artifacts = await buildQuickstartArtifacts(flags, {
|
|
1647
|
+
bundleInput,
|
|
1648
|
+
outDirInput,
|
|
1649
|
+
overwrite,
|
|
1650
|
+
write: false,
|
|
1651
|
+
checkExisting: false,
|
|
1652
|
+
});
|
|
1653
|
+
const requestedSelection = setupClientIds(flags);
|
|
1654
|
+
const selection = requestedSelection.auto
|
|
1655
|
+
? await setupAutoClientSelection(flags, artifacts, DEFAULT_SETUP_CLIENTS, 'auto')
|
|
1656
|
+
: staticSetupSelection(requestedSelection);
|
|
1657
|
+
const demoMemoryAddr = firstActiveMemoryAddress(artifacts.vault);
|
|
1658
|
+
const crossModelLimit = integerFlag(flags, ['limit'], 'limit', 1);
|
|
1659
|
+
if (crossModelLimit < 1) throw new Error('--limit must be at least 1.');
|
|
1660
|
+
const receiptCountBeforeProfiles = Array.isArray(artifacts.vault.receipts) ? artifacts.vault.receipts.length : 0;
|
|
1661
|
+
const profiles = buildCrossModelProfileSummaries({
|
|
1662
|
+
vault: artifacts.vault,
|
|
1663
|
+
passport: artifacts.passport,
|
|
1664
|
+
demoMemoryAddr,
|
|
1665
|
+
limit: crossModelLimit,
|
|
1666
|
+
});
|
|
1667
|
+
const finalExport = exportBundle({ vault: artifacts.vault, includePlaintext: false });
|
|
1668
|
+
const finalBundle = finalExport.bundle ?? finalExport;
|
|
1669
|
+
const finalVerifyReport = verifyBundle(finalBundle);
|
|
1670
|
+
const crossModelReport = {
|
|
1671
|
+
ok: true,
|
|
1672
|
+
schema: 'enigma.cross_model_demo.v1',
|
|
1673
|
+
command: 'enigma demo cross-model',
|
|
1674
|
+
story: 'One local Enigma memory is packaged as public-safe context pack references and receipts for ChatGPT, Claude, Kimi, Cursor, and a local LLM. No provider is called.',
|
|
1675
|
+
bundle_ref: bundleInput,
|
|
1676
|
+
bundle_supplied: true,
|
|
1677
|
+
bundle_created: true,
|
|
1678
|
+
demo_only_vault: true,
|
|
1679
|
+
memory_source: 'test_drive_demo',
|
|
1680
|
+
demo_memory_addr: demoMemoryAddr,
|
|
1681
|
+
profile_count: profiles.length,
|
|
1682
|
+
profiles,
|
|
1683
|
+
memory_count: activeMemoryCount(artifacts.vault),
|
|
1684
|
+
receipt_count: Array.isArray(finalBundle.receipts) ? finalBundle.receipts.length : 0,
|
|
1685
|
+
generated_receipt_count: (Array.isArray(finalBundle.receipts) ? finalBundle.receipts.length : 0) - receiptCountBeforeProfiles,
|
|
1686
|
+
provider_credentials_required: false,
|
|
1687
|
+
provider_native_memory_canonical: false,
|
|
1688
|
+
out_written: !dryRun,
|
|
1689
|
+
claim_boundaries: { ...CROSS_MODEL_CLAIM_BOUNDARIES },
|
|
1690
|
+
};
|
|
1691
|
+
const rawStatusSummary = passportStatusReport({
|
|
1692
|
+
bundlePath: outputs.bundlePath,
|
|
1693
|
+
vault: artifacts.vault,
|
|
1694
|
+
passport: artifacts.passport,
|
|
1695
|
+
stored: {
|
|
1696
|
+
owner: {
|
|
1697
|
+
subject_id: artifacts.vault.subject_id,
|
|
1698
|
+
display_name: artifacts.vault.display_name,
|
|
1699
|
+
},
|
|
1700
|
+
},
|
|
1701
|
+
});
|
|
1702
|
+
const statusSummary = publicTestDriveStatusSummary(rawStatusSummary, bundleInput);
|
|
1703
|
+
const rawSearchSummary = memorySearchReport({
|
|
1704
|
+
bundlePath: outputs.bundlePath,
|
|
1705
|
+
vault: artifacts.vault,
|
|
1706
|
+
query: 'local proof bundle',
|
|
1707
|
+
limit: 3,
|
|
1708
|
+
includeContent: false,
|
|
1709
|
+
now: getFlag(flags, ['now'], '2026-01-01T00:00:00.000Z'),
|
|
1710
|
+
});
|
|
1711
|
+
const searchSummary = publicTestDriveSearchSummary(rawSearchSummary, bundleInput);
|
|
1712
|
+
|
|
1713
|
+
if (!dryRun) {
|
|
1714
|
+
await writeJson(outputs.bundlePath, finalBundle);
|
|
1715
|
+
await writeJson(outputs.contextPackPath, publicContextPackSummary(artifacts.contextPack));
|
|
1716
|
+
await writeJson(outputs.exportPath, finalBundle);
|
|
1717
|
+
await writeJson(outputs.verifyReportPath, finalVerifyReport);
|
|
1718
|
+
await writeJson(outputs.crossModelReportPath, crossModelReport);
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
const flowCommands = testDriveFlowCommands({
|
|
1722
|
+
bundleDisplay: bundleInput,
|
|
1723
|
+
outDirInput,
|
|
1724
|
+
crossModelReportDisplay: outputs.crossModelReportDisplay,
|
|
1725
|
+
overwrite,
|
|
1726
|
+
});
|
|
1727
|
+
const nextCommands = testDriveNextCommands(bundleInput, outputs.crossModelReportDisplay);
|
|
1728
|
+
const files = testDriveFileSummaries(outputs.artifacts, !dryRun);
|
|
1729
|
+
const packageJson = await readPackageJson();
|
|
1730
|
+
const ok = finalVerifyReport.ok === true && crossModelReport.ok === true && statusSummary.ok === true && searchSummary.ok === true;
|
|
1731
|
+
print({
|
|
1732
|
+
ok,
|
|
1733
|
+
schema: 'enigma.test_drive.v1',
|
|
1734
|
+
command: 'enigma test-drive',
|
|
1735
|
+
dry_run: dryRun,
|
|
1736
|
+
out_dir: outDirInput,
|
|
1737
|
+
bundle: bundleInput,
|
|
1738
|
+
install_command: `npm install -g ${packageJson.name ?? 'enigma-memory'}`,
|
|
1739
|
+
release_target: '0.1.12',
|
|
1740
|
+
artifacts_written: !dryRun,
|
|
1741
|
+
client_configs_written: false,
|
|
1742
|
+
client_config_write_required: false,
|
|
1743
|
+
memory_plaintext_echoed: false,
|
|
1744
|
+
provider_credentials_required: false,
|
|
1745
|
+
hosted_saas_live: false,
|
|
1746
|
+
files,
|
|
1747
|
+
files_written: dryRun ? [] : files.map((file) => file.path),
|
|
1748
|
+
files_planned: files.map((file) => file.path),
|
|
1749
|
+
commands_run: dryRun ? [] : flowCommands,
|
|
1750
|
+
commands_planned: dryRun ? flowCommands : [],
|
|
1751
|
+
next_commands: nextCommands,
|
|
1752
|
+
benchmark_pointers: testDriveBenchmarkPointers(),
|
|
1753
|
+
setup_summary: {
|
|
1754
|
+
schema: 'enigma.setup.v1',
|
|
1755
|
+
artifacts_written: !dryRun,
|
|
1756
|
+
bundle: bundleInput,
|
|
1757
|
+
context_pack: outputs.contextPackDisplay,
|
|
1758
|
+
export: outputs.exportDisplay,
|
|
1759
|
+
verify_report: outputs.verifyReportDisplay,
|
|
1760
|
+
selected_clients: selection.clients,
|
|
1761
|
+
client_selection: publicSetupClientSelection(selection),
|
|
1762
|
+
client_configs_written: false,
|
|
1763
|
+
provider_credentials_required: false,
|
|
1764
|
+
memory_plaintext_echoed: false,
|
|
1765
|
+
memory_count: Array.isArray(finalBundle.memory_objects) ? finalBundle.memory_objects.length : 0,
|
|
1766
|
+
receipt_count: Array.isArray(finalBundle.receipts) ? finalBundle.receipts.length : 0,
|
|
1767
|
+
context_item_count: Array.isArray(artifacts.contextPack.memories) ? artifacts.contextPack.memories.length : 0,
|
|
1768
|
+
verify_ok: finalVerifyReport.ok === true,
|
|
1769
|
+
},
|
|
1770
|
+
status_summary: statusSummary,
|
|
1771
|
+
search_summary: searchSummary,
|
|
1772
|
+
cross_model_summary: crossModelReport,
|
|
1773
|
+
claim_boundaries: testDriveClaimBoundaries(),
|
|
1774
|
+
}, io);
|
|
1775
|
+
return ok ? 0 : 1;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1441
1778
|
async function exportCommand(flags, io) {
|
|
1442
1779
|
const bundlePath = resolve(String(getFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE)));
|
|
1443
1780
|
const { vault } = await loadState(bundlePath);
|
|
@@ -1764,6 +2101,229 @@ function integerFlag(flags, names, label = names[0], fallback = undefined) {
|
|
|
1764
2101
|
return number;
|
|
1765
2102
|
}
|
|
1766
2103
|
|
|
2104
|
+
function flagValues(flags, names) {
|
|
2105
|
+
const values = [];
|
|
2106
|
+
for (const name of names) {
|
|
2107
|
+
const value = getFlag(flags, [name]);
|
|
2108
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
2109
|
+
for (const entry of entries) {
|
|
2110
|
+
if (entry === undefined || entry === true || entry === '') continue;
|
|
2111
|
+
for (const item of String(entry).split(',')) {
|
|
2112
|
+
const trimmed = item.trim();
|
|
2113
|
+
if (trimmed) values.push(trimmed);
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
return values;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
function chainWriteOrPrint(flags, io, artifact, summary) {
|
|
2121
|
+
if (flags.has('out')) {
|
|
2122
|
+
const outPath = resolve(String(requireFlag(flags, ['out'])));
|
|
2123
|
+
return writeJson(outPath, artifact).then(() => {
|
|
2124
|
+
print({
|
|
2125
|
+
ok: true,
|
|
2126
|
+
path: publicPathDisplay(String(requireFlag(flags, ['out'])), 'proof-network-artifact'),
|
|
2127
|
+
transaction_submitted: false,
|
|
2128
|
+
raw_memory_on_chain: false,
|
|
2129
|
+
...summary,
|
|
2130
|
+
}, io);
|
|
2131
|
+
return 0;
|
|
2132
|
+
});
|
|
2133
|
+
}
|
|
2134
|
+
print(artifact, io);
|
|
2135
|
+
return 0;
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
async function sha256PublicFile(path) {
|
|
2139
|
+
const bytes = await readFile(path);
|
|
2140
|
+
try {
|
|
2141
|
+
assertNoPrivateProofPayload(JSON.parse(bytes.toString('utf8')));
|
|
2142
|
+
} catch (error) {
|
|
2143
|
+
if (error instanceof SyntaxError) return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
|
|
2144
|
+
throw new Error('Report file contains private proof payload markers.');
|
|
2145
|
+
}
|
|
2146
|
+
return `sha256:${createHash('sha256').update(bytes).digest('hex')}`;
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
function scoreFlags(flags) {
|
|
2150
|
+
const scores = {};
|
|
2151
|
+
for (const value of flagValues(flags, ['score', 'scores', 'metric', 'metrics'])) {
|
|
2152
|
+
const eq = value.indexOf('=');
|
|
2153
|
+
if (eq <= 0) throw new Error('--score values must use name=value.');
|
|
2154
|
+
const key = value.slice(0, eq).trim();
|
|
2155
|
+
const raw = value.slice(eq + 1).trim();
|
|
2156
|
+
if (!key || !raw) throw new Error('--score values must use name=value.');
|
|
2157
|
+
const numeric = Number(raw);
|
|
2158
|
+
scores[key] = Number.isFinite(numeric) && raw !== '' ? numeric : raw;
|
|
2159
|
+
}
|
|
2160
|
+
return scores;
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
|
|
2164
|
+
function assertChainArtifact(validate, artifact) {
|
|
2165
|
+
const result = chainValidationResult(validate, artifact);
|
|
2166
|
+
if (!result.ok) throw new Error(result.errors?.join('; ') || 'Invalid proof-network artifact.');
|
|
2167
|
+
return artifact;
|
|
2168
|
+
}
|
|
2169
|
+
function chainValidationResult(validate, artifact) {
|
|
2170
|
+
assertNoPrivateProofPayload(artifact);
|
|
2171
|
+
const result = validate(artifact);
|
|
2172
|
+
if (result === false) return { ok: false };
|
|
2173
|
+
if (result && typeof result === 'object') return { ok: result.ok !== false, ...result };
|
|
2174
|
+
return { ok: true };
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
function chainArtifactValidator(artifact) {
|
|
2178
|
+
const schema = String(artifact?.schema ?? artifact?.type ?? artifact?.artifact_type ?? '');
|
|
2179
|
+
if (schema === 'enigma.proof_network.anchor_batch.v1') return [schema, validateProofNetworkAnchorBatch];
|
|
2180
|
+
if (schema === 'enigma.proof_network.capability_grant.v1') return [schema, validateCapabilityGrant];
|
|
2181
|
+
if (schema === 'enigma.proof_network.capability_revocation.v1') return [schema, validateCapabilityRevocation];
|
|
2182
|
+
if (schema === 'enigma.proof_network.benchmark_attestation.v1') return [schema, validateBenchmarkAttestation];
|
|
2183
|
+
if (schema === 'enigma.proof_network.packet.v1') return [schema, validateProofNetworkPacket];
|
|
2184
|
+
throw new Error(`Unsupported proof-network artifact schema: ${schema || 'missing'}.`);
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
export async function chainAnchorCommand(flags, io) {
|
|
2188
|
+
const roots = flagValues(flags, ['root', 'roots', 'memory-root', 'memoryRoot', 'receipt-root', 'receiptRoot', 'context-root', 'contextRoot', 'memory-commitment-root', 'memoryCommitmentRoot']);
|
|
2189
|
+
if (roots.length === 0) throw new Error('Missing required --root.');
|
|
2190
|
+
const refs = flagValues(flags, ['ref', 'refs', 'public-ref', 'publicRef']);
|
|
2191
|
+
const publicChainRef = getFlag(flags, ['public-chain-ref', 'publicChainRef', 'chain-ref', 'chainRef'], 'solana:local-plan');
|
|
2192
|
+
const batch = createProofNetworkAnchorBatch({
|
|
2193
|
+
roots,
|
|
2194
|
+
root_count: roots.length,
|
|
2195
|
+
commitment_count: roots.length,
|
|
2196
|
+
refs,
|
|
2197
|
+
public_chain_ref: publicChainRef,
|
|
2198
|
+
authority_ref: getFlag(flags, ['authority', 'authority-ref', 'authorityRef']),
|
|
2199
|
+
batch_ref: getFlag(flags, ['batch-ref', 'batchRef']),
|
|
2200
|
+
created_at: getFlag(flags, ['created-at', 'createdAt']),
|
|
2201
|
+
transaction_submitted: false,
|
|
2202
|
+
raw_memory_on_chain: false,
|
|
2203
|
+
});
|
|
2204
|
+
assertChainArtifact(validateProofNetworkAnchorBatch, batch);
|
|
2205
|
+
return chainWriteOrPrint(flags, io, batch, {
|
|
2206
|
+
artifact_type: batch.schema,
|
|
2207
|
+
anchor_batch_id: batch.anchor_batch_id,
|
|
2208
|
+
anchor_batch_hash: batch.anchor_batch_hash ?? proofNetworkSha256Json(batch),
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
export async function chainGrantCommand(flags, io) {
|
|
2213
|
+
const resourceRefs = flagValues(flags, ['resource-root', 'resource-roots', 'resourceRoot', 'resourceRoots', 'resource-ref', 'resource-refs', 'resourceRef', 'resourceRefs', 'ref', 'refs']);
|
|
2214
|
+
const capability = requireFlag(flags, ['capability', 'capability-id', 'capabilityId'], 'capability');
|
|
2215
|
+
const scope = requireFlag(flags, ['scope', 'scope-ref', 'scopeRef', 'capability-scope', 'capabilityScope'], 'scope');
|
|
2216
|
+
const policyHash = getFlag(flags, ['policy-hash', 'policyHash'], proofNetworkSha256Json({ capability, scope, resource_refs: resourceRefs }));
|
|
2217
|
+
const grant = createCapabilityGrant({
|
|
2218
|
+
issuer_ref: getFlag(flags, ['issuer', 'issuer-ref', 'issuerRef'], 'issuer:local-cli'),
|
|
2219
|
+
subject_ref: requireFlag(flags, ['subject', 'subject-ref', 'subjectRef'], 'subject'),
|
|
2220
|
+
capability,
|
|
2221
|
+
scope,
|
|
2222
|
+
scopes: scope,
|
|
2223
|
+
capability_scope: scope,
|
|
2224
|
+
resource_roots: resourceRefs.length ? resourceRefs : [policyHash],
|
|
2225
|
+
policy_hash: policyHash,
|
|
2226
|
+
expires_at: requireFlag(flags, ['expires-at', 'expiresAt'], 'expires-at'),
|
|
2227
|
+
grant_ref: getFlag(flags, ['grant-ref', 'grantRef']),
|
|
2228
|
+
issued_at: getFlag(flags, ['issued-at', 'issuedAt', 'created-at', 'createdAt']),
|
|
2229
|
+
transaction_submitted: false,
|
|
2230
|
+
raw_memory_on_chain: false,
|
|
2231
|
+
});
|
|
2232
|
+
assertChainArtifact(validateCapabilityGrant, grant);
|
|
2233
|
+
return chainWriteOrPrint(flags, io, grant, {
|
|
2234
|
+
artifact_type: grant.schema,
|
|
2235
|
+
capability_grant_id: grant.capability_grant_id,
|
|
2236
|
+
capability_grant_hash: grant.capability_grant_hash ?? proofNetworkSha256Json(grant),
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
|
|
2240
|
+
export async function chainRevokeCommand(flags, io) {
|
|
2241
|
+
const grantValue = getFlag(flags, ['grant']);
|
|
2242
|
+
let grantHash = getFlag(flags, ['grant-hash', 'grantHash']);
|
|
2243
|
+
let grantId = getFlag(flags, ['grant-id', 'grantId']);
|
|
2244
|
+
if (grantValue !== undefined && grantValue !== true && grantValue !== '') {
|
|
2245
|
+
const grantString = String(grantValue);
|
|
2246
|
+
if (grantString.startsWith('sha256:')) {
|
|
2247
|
+
grantHash = grantHash ?? grantString;
|
|
2248
|
+
} else {
|
|
2249
|
+
const grantArtifact = await readJson(resolve(grantString));
|
|
2250
|
+
const grantValidation = validateCapabilityGrant(grantArtifact);
|
|
2251
|
+
if (!grantValidation.ok) throw new Error(`Grant artifact is invalid: ${grantValidation.errors.join('; ')}`);
|
|
2252
|
+
grantHash = grantHash ?? grantArtifact.capability_grant_hash;
|
|
2253
|
+
grantId = grantId ?? grantArtifact.capability_grant_id;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
const nullifierValue = getFlag(flags, ['nullifier-root', 'nullifierRoot', 'nullifier-ref', 'nullifierRef', 'nullifier']);
|
|
2257
|
+
const revocation = createCapabilityRevocation({
|
|
2258
|
+
grant_id: grantId,
|
|
2259
|
+
grant_hash: grantHash ?? requireFlag(flags, ['grant-hash', 'grantHash'], 'grant-hash'),
|
|
2260
|
+
reason_ref: requireFlag(flags, ['reason', 'revocation-reason', 'revocationReason'], 'reason'),
|
|
2261
|
+
revocation_reason: getFlag(flags, ['reason', 'revocation-reason', 'revocationReason']),
|
|
2262
|
+
revocation_ref: getFlag(flags, ['revocation-ref', 'revocationRef']),
|
|
2263
|
+
nullifier_root: nullifierValue && String(nullifierValue).startsWith('sha256:') ? nullifierValue : undefined,
|
|
2264
|
+
nullifier_ref: nullifierValue && !String(nullifierValue).startsWith('sha256:') ? nullifierValue : undefined,
|
|
2265
|
+
revoked_at: getFlag(flags, ['revoked-at', 'revokedAt']),
|
|
2266
|
+
transaction_submitted: false,
|
|
2267
|
+
raw_memory_on_chain: false,
|
|
2268
|
+
});
|
|
2269
|
+
assertChainArtifact(validateCapabilityRevocation, revocation);
|
|
2270
|
+
return chainWriteOrPrint(flags, io, revocation, {
|
|
2271
|
+
artifact_type: revocation.schema,
|
|
2272
|
+
capability_revocation_id: revocation.capability_revocation_id,
|
|
2273
|
+
capability_revocation_hash: revocation.capability_revocation_hash ?? proofNetworkSha256Json(revocation),
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
export async function chainAttestCommand(flags, io) {
|
|
2278
|
+
const reportHash = getFlag(flags, ['report-hash', 'reportHash']);
|
|
2279
|
+
const reportFile = getFlag(flags, ['report-file', 'reportFile']);
|
|
2280
|
+
const resolvedReportHash = reportHash || (reportFile ? await sha256PublicFile(resolve(String(reportFile))) : undefined);
|
|
2281
|
+
if (!resolvedReportHash) throw new Error('Missing required --report-hash or --report-file.');
|
|
2282
|
+
const scores = scoreFlags(flags);
|
|
2283
|
+
const metricsHash = getFlag(flags, ['metrics-hash', 'metricsHash'], proofNetworkSha256Json({ scores }));
|
|
2284
|
+
const attestation = createBenchmarkAttestation({
|
|
2285
|
+
report_hash: resolvedReportHash,
|
|
2286
|
+
report_file_hash: resolvedReportHash,
|
|
2287
|
+
dataset_ref: requireFlag(flags, ['dataset-ref', 'datasetRef', 'dataset-manifest', 'datasetManifest'], 'dataset-ref'),
|
|
2288
|
+
runner_ref: requireFlag(flags, ['runner-ref', 'runnerRef'], 'runner-ref'),
|
|
2289
|
+
package_ref: requireFlag(flags, ['package-ref', 'packageRef'], 'package-ref'),
|
|
2290
|
+
metrics: scores,
|
|
2291
|
+
metrics_hash: metricsHash,
|
|
2292
|
+
attestation_ref: getFlag(flags, ['attestation-ref', 'attestationRef']),
|
|
2293
|
+
created_at: getFlag(flags, ['created-at', 'createdAt']),
|
|
2294
|
+
transaction_submitted: false,
|
|
2295
|
+
raw_memory_on_chain: false,
|
|
2296
|
+
});
|
|
2297
|
+
assertChainArtifact(validateBenchmarkAttestation, attestation);
|
|
2298
|
+
return chainWriteOrPrint(flags, io, attestation, {
|
|
2299
|
+
artifact_type: attestation.schema,
|
|
2300
|
+
benchmark_attestation_id: attestation.benchmark_attestation_id,
|
|
2301
|
+
benchmark_attestation_hash: attestation.benchmark_attestation_hash ?? proofNetworkSha256Json(attestation),
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
export async function chainVerifyCommand(flags, io, positionalFile = undefined) {
|
|
2306
|
+
const inPath = resolve(String(requireFileArg(flags, ['file', 'in'], positionalFile, 'file')));
|
|
2307
|
+
const artifact = await readJson(inPath);
|
|
2308
|
+
const [schema, validate] = chainArtifactValidator(artifact);
|
|
2309
|
+
let result;
|
|
2310
|
+
try {
|
|
2311
|
+
result = chainValidationResult(validate, artifact);
|
|
2312
|
+
} catch (error) {
|
|
2313
|
+
result = { ok: false, error: { code: 'PROOF_NETWORK_INVALID', message: error.message } };
|
|
2314
|
+
}
|
|
2315
|
+
print({
|
|
2316
|
+
ok: result.ok === true,
|
|
2317
|
+
artifact_type: schema,
|
|
2318
|
+
artifact_hash: proofNetworkSha256Json(artifact),
|
|
2319
|
+
transaction_submitted: false,
|
|
2320
|
+
raw_memory_on_chain: false,
|
|
2321
|
+
validation: result,
|
|
2322
|
+
}, io);
|
|
2323
|
+
return result.ok === true ? 0 : 1;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
|
|
1767
2327
|
export async function meterEventCommand(flags, io) {
|
|
1768
2328
|
const event = createUsageEvent({
|
|
1769
2329
|
tenant_id: requireFlag(flags, ['tenant', 'tenant-id', 'tenantId'], 'tenant'),
|
|
@@ -1945,6 +2505,7 @@ function usage() {
|
|
|
1945
2505
|
'init',
|
|
1946
2506
|
'setup',
|
|
1947
2507
|
'quickstart',
|
|
2508
|
+
'test-drive',
|
|
1948
2509
|
'demo cross-model',
|
|
1949
2510
|
'doctor',
|
|
1950
2511
|
'install',
|
|
@@ -1981,6 +2542,11 @@ function usage() {
|
|
|
1981
2542
|
'settlement receipt',
|
|
1982
2543
|
'settlement verify',
|
|
1983
2544
|
'settlement batch',
|
|
2545
|
+
'chain anchor',
|
|
2546
|
+
'chain grant',
|
|
2547
|
+
'chain revoke',
|
|
2548
|
+
'chain attest',
|
|
2549
|
+
'chain verify',
|
|
1984
2550
|
],
|
|
1985
2551
|
connector_options: {
|
|
1986
2552
|
'--bundle <path>': 'Absolute local Enigma vault bundle path rendered as ENIGMA_BUNDLE.',
|
|
@@ -2024,6 +2590,13 @@ function usage() {
|
|
|
2024
2590
|
'--memory-text <text>': 'Inline demo memory text for non-private demos only.',
|
|
2025
2591
|
'--overwrite': 'Replace existing quickstart output files.',
|
|
2026
2592
|
},
|
|
2593
|
+
test_drive_options: {
|
|
2594
|
+
'--out-dir <path>': `Isolated demo directory. Defaults to ${DEFAULT_TEST_DRIVE_DIR}.`,
|
|
2595
|
+
'--bundle <path>': `Bundle JSON to create. Defaults to ${DEFAULT_TEST_DRIVE_DIR}/${DEFAULT_TEST_DRIVE_BUNDLE_NAME}.`,
|
|
2596
|
+
'--client <id|auto>': 'Client setup planning passthrough. No client config files are written by test-drive.',
|
|
2597
|
+
'--overwrite': 'Replace existing test-drive artifact files.',
|
|
2598
|
+
'--dry-run': 'Plan the local test drive without writing artifacts.',
|
|
2599
|
+
},
|
|
2027
2600
|
cross_model_demo_options: {
|
|
2028
2601
|
'--bundle <path>': `Reuse a local Enigma bundle. If omitted, ${DEFAULT_CROSS_MODEL_DEMO_BUNDLE} is recreated as a demo-only local vault.`,
|
|
2029
2602
|
'--memory-file <path>': 'Seed the demo from a local file without echoing plaintext. Alias: --text-file.',
|
|
@@ -2069,6 +2642,14 @@ function usage() {
|
|
|
2069
2642
|
batch: 'enigma settlement batch --receipts <receipts.json> --batch-ref <ref> [--asset <asset>] [--out <file>]',
|
|
2070
2643
|
boundary: 'Settlement artifacts contain commitment roots, capacity profiles, hashes, refs, prices, and claim boundaries only; no raw memory, prompts, provider responses, credentials, token ROI/profit, decentralization, or provider-invoice savings claim.',
|
|
2071
2644
|
},
|
|
2645
|
+
chain: {
|
|
2646
|
+
anchor: 'enigma chain anchor --root <sha256:...> [--root <sha256:...>] [--ref <public-ref>] [--authority <public-authority-ref>] [--batch-ref <ref>] [--out <file>]',
|
|
2647
|
+
grant: 'enigma chain grant --subject <public-subject-ref> --capability <capability-id> --scope <scope-id> [--resource-ref <sha256:...>] [--policy-hash <sha256:...>] --expires-at <iso> [--grant-ref <public-ref>] [--out <file>]',
|
|
2648
|
+
revoke: 'enigma chain revoke --grant-hash <sha256:...> --reason <public-reason-code> [--revocation-ref <public-ref>] [--out <file>]',
|
|
2649
|
+
attest: 'enigma chain attest (--report-hash <sha256:...> | --report-file <report.json>) --dataset-ref <sha256:...> --runner-ref <public-runner-ref> --package-ref <public-package-ref> [--score name=value] [--out <file>]',
|
|
2650
|
+
verify: 'enigma chain verify --file <proof-artifact.json>',
|
|
2651
|
+
boundary: 'Proof Network chain commands are local planning commands only. They write public-safe hashes, roots, refs, counts, signatures, and booleans; they do not submit Solana transactions or put raw memory on chain.',
|
|
2652
|
+
},
|
|
2072
2653
|
relay_gateway_options: {
|
|
2073
2654
|
'--host <host>': 'Bind host. Defaults to 127.0.0.1.',
|
|
2074
2655
|
'--port <port>': `Bind port. Defaults to ${DEFAULT_RELAY_PORT} for relay and ${DEFAULT_GATEWAY_PORT} for gateway.`,
|
|
@@ -2095,10 +2676,10 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2095
2676
|
print(usage(), io);
|
|
2096
2677
|
return 0;
|
|
2097
2678
|
}
|
|
2098
|
-
const twoPartCommands = ['boundary', 'mcp', 'mesh', 'enterprise', 'capsule', 'relay', 'gateway', 'connect', 'disconnect', 'import', 'native-host', 'meter', 'settlement', 'demo', 'passport'];
|
|
2679
|
+
const twoPartCommands = ['boundary', 'mcp', 'mesh', 'enterprise', 'capsule', 'relay', 'gateway', 'connect', 'disconnect', 'import', 'native-host', 'meter', 'settlement', 'chain', 'demo', 'passport'];
|
|
2099
2680
|
const flags = parseArgs(twoPartCommands.includes(command) ? argv.slice(2) : argv.slice(1));
|
|
2100
2681
|
const positionalFile = optionalPositional(argv[2]);
|
|
2101
|
-
if ((flags.has('help') || argv.includes('-h')) && (command === 'setup' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model'))) {
|
|
2682
|
+
if ((command === 'chain' && (!subcommand || subcommand === '--help' || subcommand === '-h' || flags.has('help'))) || ((flags.has('help') || argv.includes('-h')) && (command === 'setup' || command === 'test-drive' || command === 'search' || command === 'status' || (command === 'passport' && subcommand === 'status') || ((command === 'relay' || command === 'gateway') && (subcommand === 'serve' || subcommand === 'demo')) || (command === 'native-host' && (subcommand === 'manifest' || subcommand === 'install-plan')) || (command === 'demo' && subcommand === 'cross-model')))) {
|
|
2102
2683
|
print(usage(), io);
|
|
2103
2684
|
return 0;
|
|
2104
2685
|
}
|
|
@@ -2106,6 +2687,7 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2106
2687
|
if (command === 'init') return await initCommand(flags, io);
|
|
2107
2688
|
if (command === 'setup') return await setupCommand(flags, io);
|
|
2108
2689
|
if (command === 'quickstart') return await quickstartCommand(flags, io);
|
|
2690
|
+
if (command === 'test-drive') return await testDriveCommand(flags, io);
|
|
2109
2691
|
if (command === 'demo' && subcommand === 'cross-model') return await crossModelDemoCommand(flags, io);
|
|
2110
2692
|
if (command === 'doctor') return await doctorCommand(flags, io);
|
|
2111
2693
|
if (command === 'install') return await installCommand(flags, io);
|
|
@@ -2139,6 +2721,11 @@ export async function main(argv = process.argv.slice(2), io = { stdout: process.
|
|
|
2139
2721
|
if (command === 'settlement' && subcommand === 'receipt') return await settlementReceiptCommand(flags, io);
|
|
2140
2722
|
if (command === 'settlement' && subcommand === 'verify') return await settlementVerifyCommand(flags, io);
|
|
2141
2723
|
if (command === 'settlement' && subcommand === 'batch') return await settlementBatchCommand(flags, io, positionalFile);
|
|
2724
|
+
if (command === 'chain' && subcommand === 'anchor') return await chainAnchorCommand(flags, io);
|
|
2725
|
+
if (command === 'chain' && subcommand === 'grant') return await chainGrantCommand(flags, io);
|
|
2726
|
+
if (command === 'chain' && subcommand === 'revoke') return await chainRevokeCommand(flags, io);
|
|
2727
|
+
if (command === 'chain' && subcommand === 'attest') return await chainAttestCommand(flags, io);
|
|
2728
|
+
if (command === 'chain' && subcommand === 'verify') return await chainVerifyCommand(flags, io, positionalFile);
|
|
2142
2729
|
if (command === 'native-host' && subcommand === 'install-plan') return await nativeHostInstallPlanCommand(flags, io);
|
|
2143
2730
|
if (command === 'mesh' && subcommand === 'demo') return await meshDemoCommand(flags, io);
|
|
2144
2731
|
if (command === 'enterprise' && subcommand === 'demo') return await enterpriseDemoCommand(flags, io);
|