enigma-memory 0.1.16 → 0.1.17
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 +14 -10
- package/apps/cli/bin/enigma.mjs +123 -11
- package/docs/benchmark-attestation-network.md +2 -2
- package/docs/benchmark-reproducibility.md +53 -4
- package/docs/blockchain-only-mechanisms.md +12 -0
- package/docs/client-connectors.md +9 -5
- package/docs/demo-proof-network.md +3 -3
- package/docs/developer-ecosystem.md +7 -5
- package/docs/developer-proof-quickstart.md +3 -3
- package/docs/enigma-memory-ready-conformance.md +1 -1
- package/docs/hosted-cloud-product.md +29 -0
- package/docs/install-anywhere.md +13 -10
- package/docs/memory-benchmarks.md +15 -0
- package/docs/memory-drive-health-model.md +41 -0
- package/docs/proof-network-build-notes.md +2 -2
- package/docs/proof-network.md +63 -6
- package/docs/sdk-api.md +1 -1
- package/docs/solana-proof-rail.md +1 -1
- package/package.json +1 -1
- package/packages/hosted-cloud/src/index.js +470 -2
- package/packages/mcp-server/src/index.js +1 -1
- package/packages/passport/src/index.js +730 -0
- package/packages/proof-network/src/index.js +139 -0
- package/scripts/build-benchmark-proof-release.mjs +15 -3
- package/scripts/build-hosted-api-key-lifecycle.mjs +1 -1
- package/scripts/build-hosted-customer-lifecycle.mjs +23 -3
- package/scripts/build-installer-assets.mjs +1 -1
- package/scripts/build-production-unblocker.mjs +409 -409
- package/scripts/build-proof-network-packet.mjs +1 -1
- package/scripts/run-standard-memory-benchmarks.mjs +166 -8
|
@@ -5,12 +5,16 @@ export const PROOF_NETWORK_CAPABILITY_GRANT_SCHEMA = 'enigma.proof_network.capab
|
|
|
5
5
|
export const PROOF_NETWORK_CAPABILITY_REVOCATION_SCHEMA = 'enigma.proof_network.capability_revocation.v1';
|
|
6
6
|
export const PROOF_NETWORK_BENCHMARK_ATTESTATION_SCHEMA = 'enigma.proof_network.benchmark_attestation.v1';
|
|
7
7
|
export const PROOF_NETWORK_PACKET_SCHEMA = 'enigma.proof_network.packet.v1';
|
|
8
|
+
export const PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA = 'enigma.proof_network.registry_entry.v1';
|
|
9
|
+
export const PROOF_NETWORK_REGISTRY_BATCH_SCHEMA = 'enigma.proof_network.registry_batch.v1';
|
|
8
10
|
|
|
9
11
|
export const ANCHOR_BATCH_SCHEMA = PROOF_NETWORK_ANCHOR_BATCH_SCHEMA;
|
|
10
12
|
export const CAPABILITY_GRANT_SCHEMA = PROOF_NETWORK_CAPABILITY_GRANT_SCHEMA;
|
|
11
13
|
export const CAPABILITY_REVOCATION_SCHEMA = PROOF_NETWORK_CAPABILITY_REVOCATION_SCHEMA;
|
|
12
14
|
export const BENCHMARK_ATTESTATION_SCHEMA = PROOF_NETWORK_BENCHMARK_ATTESTATION_SCHEMA;
|
|
13
15
|
export const PACKET_SCHEMA = PROOF_NETWORK_PACKET_SCHEMA;
|
|
16
|
+
export const REGISTRY_ENTRY_SCHEMA = PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA;
|
|
17
|
+
export const REGISTRY_BATCH_SCHEMA = PROOF_NETWORK_REGISTRY_BATCH_SCHEMA;
|
|
14
18
|
|
|
15
19
|
export const PROOF_NETWORK_SCHEMAS = Object.freeze({
|
|
16
20
|
anchor_batch: PROOF_NETWORK_ANCHOR_BATCH_SCHEMA,
|
|
@@ -18,6 +22,8 @@ export const PROOF_NETWORK_SCHEMAS = Object.freeze({
|
|
|
18
22
|
capability_revocation: PROOF_NETWORK_CAPABILITY_REVOCATION_SCHEMA,
|
|
19
23
|
benchmark_attestation: PROOF_NETWORK_BENCHMARK_ATTESTATION_SCHEMA,
|
|
20
24
|
packet: PROOF_NETWORK_PACKET_SCHEMA,
|
|
25
|
+
registry_entry: PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA,
|
|
26
|
+
registry_batch: PROOF_NETWORK_REGISTRY_BATCH_SCHEMA,
|
|
21
27
|
});
|
|
22
28
|
|
|
23
29
|
const SHA256_PREFIX = 'sha256:';
|
|
@@ -36,6 +42,14 @@ const SAFE_FIELD_NAMES = new Set(Object.keys(SAFE_BOOLEAN_BOUNDARIES));
|
|
|
36
42
|
const FORBIDDEN_KEY_RE = /(?:^|_)(?:raw|plaintext|plain_text|prompt|prompts|message|messages|text|content|document|documents|transcript|transcripts|completion|completions|embedding|embeddings|acl|acl_body|access_control_list|provider_response|provider_responses|response_body|credential|credentials|api_key|secret|password|private_key|seed|seed_phrase|mnemonic|tenant_name|customer_name|organization_name|org_name)(?:$|_)/iu;
|
|
37
43
|
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}|(?:seed phrase|mnemonic phrase|raw memory|private prompt|full transcript|provider response|embedding vector))/iu;
|
|
38
44
|
const SUPPORTED_ARTIFACT_SCHEMAS = new Set(Object.values(PROOF_NETWORK_SCHEMAS));
|
|
45
|
+
const REGISTRY_ENTRY_TYPES = Object.freeze(new Set([
|
|
46
|
+
'anchor_batch',
|
|
47
|
+
'benchmark_attestation',
|
|
48
|
+
'connector_conformance',
|
|
49
|
+
'health_report',
|
|
50
|
+
'operator_receipt',
|
|
51
|
+
'settlement_job',
|
|
52
|
+
]));
|
|
39
53
|
|
|
40
54
|
function isPlainObject(value) {
|
|
41
55
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
@@ -296,6 +310,10 @@ function artifactHash(artifact, index) {
|
|
|
296
310
|
return requiredString(artifact.benchmark_attestation_hash, `artifacts[${index}].benchmark_attestation_hash`);
|
|
297
311
|
case PROOF_NETWORK_PACKET_SCHEMA:
|
|
298
312
|
return requiredString(artifact.proof_network_packet_hash, `artifacts[${index}].proof_network_packet_hash`);
|
|
313
|
+
case PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA:
|
|
314
|
+
return requiredString(artifact.registry_entry_hash, `artifacts[${index}].registry_entry_hash`);
|
|
315
|
+
case PROOF_NETWORK_REGISTRY_BATCH_SCHEMA:
|
|
316
|
+
return requiredString(artifact.registry_batch_hash, `artifacts[${index}].registry_batch_hash`);
|
|
299
317
|
default:
|
|
300
318
|
throw new TypeError(`artifacts[${index}] has unsupported schema`);
|
|
301
319
|
}
|
|
@@ -313,6 +331,10 @@ function validateSupportedArtifact(artifact) {
|
|
|
313
331
|
return validateBenchmarkAttestation(artifact);
|
|
314
332
|
case PROOF_NETWORK_PACKET_SCHEMA:
|
|
315
333
|
return validateProofNetworkPacket(artifact);
|
|
334
|
+
case PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA:
|
|
335
|
+
return validateRegistryEntry(artifact);
|
|
336
|
+
case PROOF_NETWORK_REGISTRY_BATCH_SCHEMA:
|
|
337
|
+
return validateRegistryBatch(artifact);
|
|
316
338
|
default:
|
|
317
339
|
return Object.freeze({ ok: false, valid: false, errors: Object.freeze(['unsupported artifact schema']) });
|
|
318
340
|
}
|
|
@@ -568,3 +590,120 @@ export function validateProofNetworkPacket(packet) {
|
|
|
568
590
|
validateIdentity(packet, errors, 'proof_network_packet_id', 'proof_network_packet_hash', 'pnp');
|
|
569
591
|
});
|
|
570
592
|
}
|
|
593
|
+
|
|
594
|
+
function registryEntryType(value, field = 'entry_type') {
|
|
595
|
+
const type = optionalString(value, undefined, field);
|
|
596
|
+
if (type === undefined || !REGISTRY_ENTRY_TYPES.has(type)) {
|
|
597
|
+
throw new TypeError(`${field} must be one of ${[...REGISTRY_ENTRY_TYPES].join(', ')}`);
|
|
598
|
+
}
|
|
599
|
+
return type;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
export function createRegistryEntry(input = {}) {
|
|
603
|
+
requiredObject(input, 'input');
|
|
604
|
+
assertNoPrivateProofPayload(input, 'input');
|
|
605
|
+
const entryType = registryEntryType(input.entry_type ?? input.entryType ?? input.type, 'entry_type');
|
|
606
|
+
const artifactHash = digestRef(input.artifact_hash ?? input.artifactHash ?? input.digest_ref ?? input.digestRef, 'artifact_hash');
|
|
607
|
+
const artifactSchemaRef = publicRef(input.artifact_schema_ref ?? input.artifactSchemaRef ?? input.schema_ref ?? input.schemaRef, 'artifact_schema_ref');
|
|
608
|
+
const digestRefs = digestArray(input.digest_refs ?? input.digestRefs ?? input.digest_roots ?? input.digestRoots ?? input.roots ?? artifactHash, 'digest_refs', { min: 1, max: 64 });
|
|
609
|
+
const signerRefs = publicRefArray(input.signer_refs ?? input.signerRefs ?? input.signer_ref ?? input.signerRef, 'signer_refs', { min: 0, max: 64 });
|
|
610
|
+
const entryRef = optionalPublicRef(input.entry_ref ?? input.entryRef, refFromDigest('registry-entry', artifactHash), 'entry_ref');
|
|
611
|
+
const body = {
|
|
612
|
+
schema: PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA,
|
|
613
|
+
registered_at: isoTimestamp(input.registered_at ?? input.registeredAt ?? input.created_at ?? input.createdAt ?? input.generated_at ?? input.generatedAt, 'registered_at'),
|
|
614
|
+
entry_type: entryType,
|
|
615
|
+
entry_ref: entryRef,
|
|
616
|
+
registry_ref: optionalPublicRef(input.registry_ref ?? input.registryRef ?? input.marketplace_ref ?? input.marketplaceRef, 'registry:memory-drive-marketplace', 'registry_ref'),
|
|
617
|
+
artifact_schema_ref: artifactSchemaRef,
|
|
618
|
+
artifact_hash: artifactHash,
|
|
619
|
+
digest_root: sha256Json(digestRefs),
|
|
620
|
+
digest_refs: digestRefs,
|
|
621
|
+
signer_refs: signerRefs,
|
|
622
|
+
entry_count: nonNegativeInteger(input.entry_count ?? input.entryCount ?? input.count, 'entry_count', 1),
|
|
623
|
+
...((input.signature_ref ?? input.signatureRef) ? { signature_ref: signatureRef(input.signature_ref ?? input.signatureRef, 'signature_ref') } : {}),
|
|
624
|
+
...SAFE_BOOLEAN_BOUNDARIES,
|
|
625
|
+
};
|
|
626
|
+
return freezeArtifact(body, 'registry_entry_id', 'registry_entry_hash', 'pnrg');
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
export function validateRegistryEntry(entry) {
|
|
630
|
+
return collectValidation((errors) => {
|
|
631
|
+
requiredObject(entry, 'entry');
|
|
632
|
+
assertNoPrivateProofPayload(entry, 'entry');
|
|
633
|
+
if (entry.schema !== PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA) errors.push(`schema must be ${PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA}`);
|
|
634
|
+
requireSafeBoundaries(entry, errors, 'entry');
|
|
635
|
+
isoTimestamp(entry.registered_at, 'registered_at');
|
|
636
|
+
if (!REGISTRY_ENTRY_TYPES.has(entry.entry_type)) errors.push(`entry_type must be one of ${[...REGISTRY_ENTRY_TYPES].join(', ')}`);
|
|
637
|
+
publicRef(entry.entry_ref, 'entry_ref');
|
|
638
|
+
publicRef(entry.registry_ref, 'registry_ref');
|
|
639
|
+
publicRef(entry.artifact_schema_ref, 'artifact_schema_ref');
|
|
640
|
+
digestRef(entry.artifact_hash, 'artifact_hash');
|
|
641
|
+
const digestRefs = digestArray(entry.digest_refs, 'digest_refs', { min: 1, max: 64 });
|
|
642
|
+
if (entry.digest_root !== sha256Json(digestRefs)) errors.push('digest_root mismatch');
|
|
643
|
+
publicRefArray(entry.signer_refs, 'signer_refs', { min: 0, max: 64 });
|
|
644
|
+
nonNegativeInteger(entry.entry_count, 'entry_count');
|
|
645
|
+
if (entry.signature_ref !== undefined) signatureRef(entry.signature_ref, 'signature_ref');
|
|
646
|
+
validateIdentity(entry, errors, 'registry_entry_id', 'registry_entry_hash', 'pnrg');
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
export function createRegistryBatch(input = {}) {
|
|
651
|
+
requiredObject(input, 'input');
|
|
652
|
+
assertNoPrivateProofPayload(input, 'input');
|
|
653
|
+
const entries = Object.freeze(arrayInput(input.entries ?? input.registry_entries ?? input.registryEntries).map((entry, index) => {
|
|
654
|
+
requiredObject(entry, `entries[${index}]`);
|
|
655
|
+
if (entry.schema !== PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA) throw new TypeError(`entries[${index}] must be a ${PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA}`);
|
|
656
|
+
const validation = validateRegistryEntry(entry);
|
|
657
|
+
if (!validation.ok) throw new TypeError(`entries[${index}] is invalid: ${validation.errors.join('; ')}`);
|
|
658
|
+
return Object.freeze(entry);
|
|
659
|
+
}));
|
|
660
|
+
if (entries.length === 0) throw new TypeError('entries must be non-empty');
|
|
661
|
+
if (entries.length > 128) throw new TypeError('entries must contain at most 128 entries');
|
|
662
|
+
const entryHashes = Object.freeze(entries.map((entry) => requiredString(entry.registry_entry_hash, 'entries.registry_entry_hash')).sort());
|
|
663
|
+
const registryRoot = sha256Json(entryHashes);
|
|
664
|
+
const body = {
|
|
665
|
+
schema: PROOF_NETWORK_REGISTRY_BATCH_SCHEMA,
|
|
666
|
+
created_at: isoTimestamp(input.created_at ?? input.createdAt ?? input.generated_at ?? input.generatedAt, 'created_at'),
|
|
667
|
+
registry_ref: optionalPublicRef(input.registry_ref ?? input.registryRef ?? input.marketplace_ref ?? input.marketplaceRef, refFromDigest('registry-batch', registryRoot), 'registry_ref'),
|
|
668
|
+
entry_count: entries.length,
|
|
669
|
+
registry_root: registryRoot,
|
|
670
|
+
entry_hashes: entryHashes,
|
|
671
|
+
entries,
|
|
672
|
+
...SAFE_BOOLEAN_BOUNDARIES,
|
|
673
|
+
};
|
|
674
|
+
return freezeArtifact(body, 'registry_batch_id', 'registry_batch_hash', 'pnrb');
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export function validateRegistryBatch(batch) {
|
|
678
|
+
return collectValidation((errors) => {
|
|
679
|
+
requiredObject(batch, 'batch');
|
|
680
|
+
assertNoPrivateProofPayload(batch, 'batch');
|
|
681
|
+
if (batch.schema !== PROOF_NETWORK_REGISTRY_BATCH_SCHEMA) errors.push(`schema must be ${PROOF_NETWORK_REGISTRY_BATCH_SCHEMA}`);
|
|
682
|
+
requireSafeBoundaries(batch, errors, 'batch');
|
|
683
|
+
isoTimestamp(batch.created_at, 'created_at');
|
|
684
|
+
publicRef(batch.registry_ref, 'registry_ref');
|
|
685
|
+
const entries = Array.isArray(batch.entries) ? batch.entries : [];
|
|
686
|
+
if (entries.length === 0 || entries.length > 128) errors.push('entries must contain 1-128 entries');
|
|
687
|
+
const entryHashes = [];
|
|
688
|
+
for (const [index, entry] of entries.entries()) {
|
|
689
|
+
requiredObject(entry, `entries[${index}]`);
|
|
690
|
+
if (entry.schema !== PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA) {
|
|
691
|
+
errors.push(`entries[${index}] must be a ${PROOF_NETWORK_REGISTRY_ENTRY_SCHEMA}`);
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
const validation = validateRegistryEntry(entry);
|
|
695
|
+
if (!validation.ok) errors.push(`entries[${index}] is invalid: ${validation.errors.join('; ')}`);
|
|
696
|
+
entryHashes.push(requiredString(entry.registry_entry_hash, `entries[${index}].registry_entry_hash`));
|
|
697
|
+
}
|
|
698
|
+
entryHashes.sort();
|
|
699
|
+
if (batch.entry_count !== entries.length) errors.push('entry_count mismatch');
|
|
700
|
+
if (batch.registry_root !== sha256Json(entryHashes)) errors.push('registry_root mismatch');
|
|
701
|
+
if (JSON.stringify(batch.entry_hashes) !== JSON.stringify(entryHashes)) errors.push('entry_hashes mismatch');
|
|
702
|
+
validateIdentity(batch, errors, 'registry_batch_id', 'registry_batch_hash', 'pnrb');
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export const createProofRegistryEntry = createRegistryEntry;
|
|
707
|
+
export const validateProofRegistryEntry = validateRegistryEntry;
|
|
708
|
+
export const createProofRegistryBatch = createRegistryBatch;
|
|
709
|
+
export const validateProofRegistryBatch = validateRegistryBatch;
|
|
@@ -23,6 +23,7 @@ const SHA256_PREFIX = 'sha256:';
|
|
|
23
23
|
const PUBLIC_REF_RE = /^[a-z0-9][a-z0-9._:/@+-]{2,191}$/u;
|
|
24
24
|
const SCORE_KEY_RE = /^[a-z][a-z0-9_.:-]{1,63}$/u;
|
|
25
25
|
const PRIVATE_REPORT_KEY_RE = /(?:^|_)(?:raw_memory|memory_plaintext|plaintext|plain_text|prompt|prompts|conversation|conversations|message|messages|content|body|payload|payloads|document|documents|transcript|transcripts|completion|completions|embedding|embeddings|provider_response|provider_responses|response_body|credential|credentials|api_key|secret|password|private_key|seed|seed_phrase|mnemonic|tenant_name|customer_name|organization_name|org_name|account_id)(?:$|_)/iu;
|
|
26
|
+
const RAW_ANSWER_REPORT_KEY_RE = /(?:^|_)(?:raw_answer|raw_answers|answer_text|answer_texts|answer_body|answer_content|generated_answer|generated_answers|final_answer|final_answers|model_answer|model_answers|llm_answer|llm_answers|provider_answer|provider_answers)(?:$|_)/iu;
|
|
26
27
|
const ALLOWED_FALSE_REPORT_KEYS = new Set([
|
|
27
28
|
'raw_private_memory_plaintext_included',
|
|
28
29
|
'raw_question_text_included',
|
|
@@ -55,6 +56,9 @@ const ALLOWED_PUBLIC_REPORT_KEYS = new Set([
|
|
|
55
56
|
'estimated_prompt_tokens',
|
|
56
57
|
'baseline_prompt_tokens',
|
|
57
58
|
'optimized_prompt_tokens',
|
|
59
|
+
'prompt_refs',
|
|
60
|
+
'same_prompts_for_all_rows',
|
|
61
|
+
'prompts_fixed',
|
|
58
62
|
]);
|
|
59
63
|
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}|(?:seed phrase|mnemonic phrase|raw memory|private prompt|full transcript|provider response|embedding vector))/iu;
|
|
60
64
|
const ABSOLUTE_LOCAL_PATH_RE = /^(?:[A-Za-z]:[\\/]|\\\\|\/(?:Users|home|tmp|var|etc|mnt|Volumes)\b)/u;
|
|
@@ -62,6 +66,7 @@ const CLAIM_SCORE_KEY_RE = /(?:provider|competitor|roi|profit|savings|solana|tra
|
|
|
62
66
|
const PROOF_COMPATIBLE_REPORT_SCHEMAS = new Set([
|
|
63
67
|
'enigma.memory_benchmark_suite.v1',
|
|
64
68
|
'enigma.standard_memory_benchmark_suite.v1',
|
|
69
|
+
'enigma.standard_memory_benchmark_protocol_plan.v1',
|
|
65
70
|
]);
|
|
66
71
|
const REQUIRED_FALSE_BOUNDARY_KEYS = Object.freeze([
|
|
67
72
|
'external_provider_calls',
|
|
@@ -172,7 +177,7 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
172
177
|
export function usage() {
|
|
173
178
|
return `Usage: node scripts/build-benchmark-proof-release.mjs --report <path> --dataset-ref <ref> --runner-ref <ref> --package-ref <ref> [--score key=value ...] [--out-dir <dir>]
|
|
174
179
|
|
|
175
|
-
Builds a dependency-free, local benchmark proof release from an existing public-safe benchmark report. The report must use a compatible benchmark schema and explicit offline benchmark boundaries. The report file is parsed for public-safety checks and hashed, but its body and local path are never copied into the attestation or proof packet. The generated artifacts are local benchmark attestation/proof only: no API calls, provider answer-accuracy claims, Mem0 or competitor performance claims, Solana submissions, hosted SaaS claims, ROI/profit/savings claims, raw memory, prompts, transcripts, embeddings, credentials, account ids, private keys, or provider responses are written.
|
|
180
|
+
Builds a dependency-free, local benchmark proof release from an existing public-safe benchmark report. The report must use a compatible benchmark schema (a scored retrieval proxy report such as enigma.standard_memory_benchmark_suite.v1, or a full-answer protocol plan such as enigma.standard_memory_benchmark_protocol_plan.v1) and explicit offline benchmark boundaries. The report file is parsed for public-safety checks and hashed, but its body and local path are never copied into the attestation or proof packet. The generated artifacts are local benchmark attestation/proof only: no API calls, provider answer-accuracy claims, Mem0 or competitor performance claims, Solana submissions, hosted SaaS claims, ROI/profit/savings claims, raw memory, prompts, transcripts, embeddings, credentials, account ids, private keys, or provider responses are written. A protocol-plan report is accepted as protocol-readiness evidence only and is rejected if it contains raw answers, prompts, provider responses, or competitor scores.
|
|
176
181
|
`;
|
|
177
182
|
}
|
|
178
183
|
|
|
@@ -205,7 +210,7 @@ function assertPublicReportPayload(value, path = 'report') {
|
|
|
205
210
|
}
|
|
206
211
|
if (!isPlainObject(value)) return;
|
|
207
212
|
for (const [key, child] of Object.entries(value)) {
|
|
208
|
-
if (PRIVATE_REPORT_KEY_RE.test(key) && !ALLOWED_PUBLIC_REPORT_KEYS.has(key)) {
|
|
213
|
+
if ((PRIVATE_REPORT_KEY_RE.test(key) || RAW_ANSWER_REPORT_KEY_RE.test(key)) && !ALLOWED_PUBLIC_REPORT_KEYS.has(key)) {
|
|
209
214
|
if (!ALLOWED_FALSE_REPORT_KEYS.has(key) || child !== false) throw new UsageError(`${path}.${key} is not allowed in public benchmark proof artifacts`);
|
|
210
215
|
}
|
|
211
216
|
assertPublicReportPayload(child, `${path}.${key}`);
|
|
@@ -275,6 +280,13 @@ function assertProofCompatibleBenchmarkBoundaries(report) {
|
|
|
275
280
|
if (report.schema === 'enigma.memory_benchmark_suite.v1') {
|
|
276
281
|
if (boundaries.local_only !== true) throw new UsageError('local memory benchmark report must set benchmark_boundaries.local_only true');
|
|
277
282
|
}
|
|
283
|
+
if (report.schema === 'enigma.standard_memory_benchmark_protocol_plan.v1') {
|
|
284
|
+
const protocolBoundaries = report.protocol_boundaries;
|
|
285
|
+
if (!isPlainObject(protocolBoundaries)) throw new UsageError('protocol plan report must include protocol_boundaries');
|
|
286
|
+
for (const key of ['network_required', 'provider_calls_made', 'answers_generated', 'judged']) {
|
|
287
|
+
requireFalseField(protocolBoundaries, key, 'report.protocol_boundaries');
|
|
288
|
+
}
|
|
289
|
+
}
|
|
278
290
|
assertCommandBoundaries(report);
|
|
279
291
|
assertExternalAdaptersUnscored(report);
|
|
280
292
|
}
|
|
@@ -404,7 +416,7 @@ export async function buildBenchmarkProofRelease(args, options = {}) {
|
|
|
404
416
|
const schema = reportSchema(report);
|
|
405
417
|
const sampleCount = sampleCountFromReport(report);
|
|
406
418
|
const datasetCount = Array.isArray(report.datasets) ? report.datasets.length : 0;
|
|
407
|
-
const commitments = scoreCommitments(args.scores, reportHash);
|
|
419
|
+
const commitments = scoreCommitments(Array.isArray(args.scores) ? args.scores : [], reportHash);
|
|
408
420
|
const metricRoots = commitments.map((score) => score.score_hash);
|
|
409
421
|
|
|
410
422
|
const attestation = createBenchmarkAttestation({
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from '../packages/hosted-cloud/src/index.js';
|
|
14
14
|
|
|
15
15
|
export const HOSTED_API_KEY_LIFECYCLE_PACKET_SCHEMA = HOSTED_CLOUD_API_KEY_LIFECYCLE_PACKET_SCHEMA;
|
|
16
|
-
export const HOSTED_API_KEY_LIFECYCLE_RELEASE_TARGET = '0.1.
|
|
16
|
+
export const HOSTED_API_KEY_LIFECYCLE_RELEASE_TARGET = '0.1.17';
|
|
17
17
|
|
|
18
18
|
const PROVIDED = 'provided';
|
|
19
19
|
const BLOCKED = 'blocked_external_dependency';
|
|
@@ -25,10 +25,13 @@ import {
|
|
|
25
25
|
buildUserAccountContract,
|
|
26
26
|
buildCustomerLifecyclePacket,
|
|
27
27
|
validateCustomerLifecyclePacket,
|
|
28
|
+
buildHostedCloudReadinessPacket,
|
|
29
|
+
HOSTED_CLOUD_READINESS_PACKET_SCHEMA,
|
|
28
30
|
} from 'enigma-memory/hosted-cloud';
|
|
29
31
|
|
|
30
32
|
export const HOSTED_CUSTOMER_LIFECYCLE_PACKET_SCHEMA = HOSTED_CLOUD_CUSTOMER_LIFECYCLE_PACKET_SCHEMA;
|
|
31
|
-
export const HOSTED_CUSTOMER_LIFECYCLE_RELEASE_TARGET = '0.1.
|
|
33
|
+
export const HOSTED_CUSTOMER_LIFECYCLE_RELEASE_TARGET = '0.1.17';
|
|
34
|
+
export const HOSTED_CLOUD_READINESS_RELEASE_SCHEMA = HOSTED_CLOUD_READINESS_PACKET_SCHEMA;
|
|
32
35
|
|
|
33
36
|
const PROVIDED = 'provided';
|
|
34
37
|
const BLOCKED_MISSING = 'blocked_missing_evidence';
|
|
@@ -379,6 +382,16 @@ export function buildHostedCustomerLifecyclePacket(options = {}) {
|
|
|
379
382
|
};
|
|
380
383
|
}
|
|
381
384
|
|
|
385
|
+
export function buildHostedCloudReadinessPacketFromArgs(options = {}) {
|
|
386
|
+
const generatedAt = options.generatedAt ?? new Date().toISOString();
|
|
387
|
+
const lifecyclePacket = buildHostedCustomerLifecyclePacket({ ...options, generatedAt });
|
|
388
|
+
return buildHostedCloudReadinessPacket({
|
|
389
|
+
generated_at: generatedAt,
|
|
390
|
+
customer_lifecycle_packet: lifecyclePacket,
|
|
391
|
+
operator_go_live_ref: options.operatorGoLiveRef ?? null,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
382
395
|
export function parseArgs(argv) {
|
|
383
396
|
const args = {
|
|
384
397
|
tenant: undefined,
|
|
@@ -386,6 +399,7 @@ export function parseArgs(argv) {
|
|
|
386
399
|
environment: undefined,
|
|
387
400
|
operatorGoLiveRef: undefined,
|
|
388
401
|
evidenceRefs: [],
|
|
402
|
+
readiness: false,
|
|
389
403
|
out: undefined,
|
|
390
404
|
help: false,
|
|
391
405
|
};
|
|
@@ -395,6 +409,7 @@ export function parseArgs(argv) {
|
|
|
395
409
|
args.help = true;
|
|
396
410
|
continue;
|
|
397
411
|
}
|
|
412
|
+
if (arg === '--readiness') { args.readiness = true; continue; }
|
|
398
413
|
const readValue = (name) => {
|
|
399
414
|
index += 1;
|
|
400
415
|
if (index >= argv.length || argv[index].startsWith('--')) throw new Error(`${name} requires a value`);
|
|
@@ -414,7 +429,7 @@ export function parseArgs(argv) {
|
|
|
414
429
|
export function usage() {
|
|
415
430
|
return `Usage: node scripts/build-hosted-customer-lifecycle.mjs [options]
|
|
416
431
|
|
|
417
|
-
Build a public-safe hosted customer lifecycle packet. This script validates local contract fragments only; it does not deploy, create accounts, call providers, or write secrets.
|
|
432
|
+
Build a public-safe hosted customer lifecycle packet, or with --readiness a hosted cloud readiness aggregator packet. This script validates local contract fragments only; it does not deploy, create accounts, call providers, or write secrets.
|
|
418
433
|
|
|
419
434
|
Options:
|
|
420
435
|
--tenant <id> Tenant id. Defaults to blocked:tenant.
|
|
@@ -424,6 +439,9 @@ Options:
|
|
|
424
439
|
--evidence-ref <key=status:ref> Repeatable evidence ref. key=<ref> implies provided.
|
|
425
440
|
Status: provided, blocked_missing_evidence, blocked_external_dependency.
|
|
426
441
|
Keys: ${HOSTED_CUSTOMER_LIFECYCLE_EVIDENCE_KEYS.join(', ')}
|
|
442
|
+
--readiness Emit a hosted cloud readiness aggregator packet (enigma.hosted_cloud.readiness_packet.v1)
|
|
443
|
+
that wraps the lifecycle packet and rolls all readiness surfaces plus
|
|
444
|
+
propagated lifecycle blockers into one public-safe readiness assessment.
|
|
427
445
|
--out <file> Also write the packet JSON to a file.
|
|
428
446
|
--help Show this help.
|
|
429
447
|
`;
|
|
@@ -435,7 +453,9 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
435
453
|
process.stdout.write(usage());
|
|
436
454
|
return 0;
|
|
437
455
|
}
|
|
438
|
-
const packet =
|
|
456
|
+
const packet = args.readiness
|
|
457
|
+
? buildHostedCloudReadinessPacketFromArgs(args)
|
|
458
|
+
: buildHostedCustomerLifecyclePacket(args);
|
|
439
459
|
const json = `${JSON.stringify(packet, null, 2)}\n`;
|
|
440
460
|
if (args.out) {
|
|
441
461
|
try {
|
|
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
6
6
|
|
|
7
7
|
export const INSTALLER_ASSET_SCHEMA = 'enigma.installer_assets.v1';
|
|
8
8
|
export const INSTALLER_ASSET_PACKAGE = 'enigma-memory';
|
|
9
|
-
export const INSTALLER_ASSET_VERSION = '0.1.
|
|
9
|
+
export const INSTALLER_ASSET_VERSION = '0.1.17';
|
|
10
10
|
export const INSTALLER_ASSET_GENERATED_AT = '1970-01-01T00:00:00.000Z';
|
|
11
11
|
|
|
12
12
|
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|