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
|
@@ -10,6 +10,7 @@ export const HOSTED_CLOUD_BACKUP_DRILL_SCHEMA = 'enigma.hosted_cloud.backup_dril
|
|
|
10
10
|
export const HOSTED_CLOUD_INCIDENT_SLA_SCHEMA = 'enigma.hosted_cloud.incident_sla_refs.v1';
|
|
11
11
|
export const HOSTED_CLOUD_CUSTOMER_LIFECYCLE_PACKET_SCHEMA = 'enigma.hosted_cloud.customer_lifecycle_packet.v1';
|
|
12
12
|
export const HOSTED_CLOUD_API_KEY_LIFECYCLE_PACKET_SCHEMA = 'enigma.hosted_cloud.api_key_lifecycle_packet.v1';
|
|
13
|
+
export const HOSTED_CLOUD_READINESS_PACKET_SCHEMA = 'enigma.hosted_cloud.readiness_packet.v1';
|
|
13
14
|
|
|
14
15
|
export const HOSTED_CLOUD_EXTERNAL_BLOCKERS = Object.freeze([
|
|
15
16
|
'auth_provider',
|
|
@@ -106,9 +107,40 @@ const API_KEY_LIFECYCLE_BLOCKER_LABELS = Object.freeze({
|
|
|
106
107
|
audit_log: 'Hosted API key lifecycle audit evidence is not provided.',
|
|
107
108
|
operator_approval: 'Explicit public-safe operator API key lifecycle approval is not provided.',
|
|
108
109
|
});
|
|
110
|
+
export const HOSTED_CLOUD_READINESS_SURFACES = Object.freeze([
|
|
111
|
+
'auth',
|
|
112
|
+
'billing',
|
|
113
|
+
'legal_dpa',
|
|
114
|
+
'support',
|
|
115
|
+
'security_review',
|
|
116
|
+
'monitoring',
|
|
117
|
+
'backup',
|
|
118
|
+
'kms_byok',
|
|
119
|
+
]);
|
|
120
|
+
const READINESS_BLOCKER_LABELS = Object.freeze({
|
|
121
|
+
auth: 'Auth provider readiness evidence is not provided.',
|
|
122
|
+
billing: 'Billing provider readiness evidence is not provided.',
|
|
123
|
+
legal_dpa: 'Legal and data-processing terms readiness evidence is not provided.',
|
|
124
|
+
support: 'Support ownership readiness evidence is not provided.',
|
|
125
|
+
security_review: 'External security review readiness evidence is not provided.',
|
|
126
|
+
monitoring: 'Monitoring readiness evidence is not provided.',
|
|
127
|
+
backup: 'Backup and disaster recovery readiness evidence is not provided.',
|
|
128
|
+
kms_byok: 'KMS / bring-your-own-key readiness evidence is not provided.',
|
|
129
|
+
operator_go_live: 'Explicit operator go-live approval is not provided.',
|
|
130
|
+
});
|
|
131
|
+
const READINESS_SURFACE_LIFECYCLE_PHASE = Object.freeze({
|
|
132
|
+
auth: 'account',
|
|
133
|
+
billing: 'billing',
|
|
134
|
+
legal_dpa: 'legal',
|
|
135
|
+
support: 'support',
|
|
136
|
+
security_review: 'security_review',
|
|
137
|
+
monitoring: 'monitoring',
|
|
138
|
+
backup: 'backup',
|
|
139
|
+
kms_byok: 'vault',
|
|
140
|
+
});
|
|
109
141
|
const API_KEY_SECRET_MATERIAL_KEY_RE = /(?:^|_)(?:raw_?api_?key|raw_?key|plaintext_?api_?key|plain_text_?api_?key|plaintext_?key|plain_text_?key|api_?key_?value|key_?value|key_?material|secret_?key|key_?secret|value)(?:$|_)/iu;
|
|
110
|
-
const FORBIDDEN_KEY_RE = /(?:^|_)(?:raw_?memory|plaintext|plain_text|prompt|prompts|completion|completions|message_body|transcript|conversation|provider_?response|response_?body|credential|credentials|secret|password|private_?key|bearer|access_token|refresh_token|token_value|api_key_value|api_secret|token_?roi|token_?profit|roi_claim|profit_claim|provider_?deletion|provider_?erasure|model_?forgetting|model_?erasure)(?:$|_)/iu;
|
|
111
|
-
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 memory|plaintext prompts?|plain text prompts?|private prompts?|provider responses?|full transcript|decrypted memory|credentials?|secrets?|passwords?|private keys?|api key secret|api secrets?|access tokens?|refresh tokens?|token values?|credential material)\b)/iu;
|
|
142
|
+
const FORBIDDEN_KEY_RE = /(?:^|_)(?:raw_?memory|raw_?key|raw_?api_?key|raw_?token|plaintext|plain_text|prompt|prompts|completion|completions|message_body|transcript|conversation|provider_?response|response_?body|credential|credentials|secret|password|private_?key|bearer|access_token|refresh_token|token_value|api_key_value|api_secret|token_?roi|token_?profit|roi_claim|profit_claim|provider_?deletion|provider_?erasure|model_?forgetting|model_?erasure)(?:$|_)/iu;
|
|
143
|
+
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}|eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}|\b(?:raw memory|plaintext prompts?|plain text prompts?|private prompts?|provider responses?|full transcript|decrypted memory|credentials?|secrets?|passwords?|private keys?|api key secret|api secrets?|access tokens?|refresh tokens?|token values?|credential material)\b)/iu;
|
|
112
144
|
const FORBIDDEN_CLAIM_RE = /(?:token\s+(?:roi|profit|return|investment|price)|(?:roi|profit|return)\s+(?:from|on)\s+token|guaranteed\s+(?:savings|profit|return)|provider(?:-side|\s+side)?\s+(?:deletion|erasure)|model\s+(?:forgetting|forgot|erasure)|makes?\s+models?\s+forget|deleted\s+from\s+every\s+provider)/iu;
|
|
113
145
|
|
|
114
146
|
function isPlainObject(value) {
|
|
@@ -959,6 +991,67 @@ function validateCustomerLifecycleReadiness(readiness, expected) {
|
|
|
959
991
|
assertSameLifecycleArray(readiness.external_blockers, expected.external_blockers, 'readiness.external_blockers');
|
|
960
992
|
assertSameLifecycleArray(readiness.missing_evidence_refs, expected.missing_evidence_refs, 'readiness.missing_evidence_refs');
|
|
961
993
|
}
|
|
994
|
+
function lifecycleNextActions(readiness, operatorGoLiveRef) {
|
|
995
|
+
const actions = [];
|
|
996
|
+
for (const missing of readiness.missing_evidence_refs) {
|
|
997
|
+
actions.push({
|
|
998
|
+
action: `provide_${missing.key}_evidence`,
|
|
999
|
+
surface: missing.key,
|
|
1000
|
+
ref: missing.ref,
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
if (operatorGoLiveRef === null) {
|
|
1004
|
+
actions.push({
|
|
1005
|
+
action: 'obtain_operator_go_live_approval',
|
|
1006
|
+
surface: 'operator_go_live',
|
|
1007
|
+
ref: 'blocked:operator_go_live',
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
if (actions.length === 0) {
|
|
1011
|
+
actions.push({
|
|
1012
|
+
action: 'lifecycle_complete_review_before_selling',
|
|
1013
|
+
surface: 'operator_go_live',
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
return actions;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
function customerLifecycleDashboard(contracts, requiredEvidenceRefs, readiness, operatorGoLiveRef) {
|
|
1020
|
+
const dashboardContract = isPlainObject(contracts.dashboard) ? contracts.dashboard : null;
|
|
1021
|
+
const providedEvidenceCount = CUSTOMER_LIFECYCLE_REQUIRED_EVIDENCE_PHASES
|
|
1022
|
+
.filter((phase) => requiredEvidenceRefs[phase].status === PROVIDED).length;
|
|
1023
|
+
return {
|
|
1024
|
+
counts: {
|
|
1025
|
+
account_count: dashboardContract ? dashboardContract.account_count : 0,
|
|
1026
|
+
active_api_key_count: dashboardContract ? dashboardContract.active_api_key_count : 0,
|
|
1027
|
+
hosted_vault_count: dashboardContract ? dashboardContract.hosted_vault_count : 0,
|
|
1028
|
+
open_incident_count: dashboardContract ? dashboardContract.open_incident_count : 0,
|
|
1029
|
+
lifecycle_phase_count: HOSTED_CLOUD_CUSTOMER_LIFECYCLE_PHASES.length,
|
|
1030
|
+
provided_evidence_count: providedEvidenceCount,
|
|
1031
|
+
missing_evidence_count: readiness.missing_evidence_refs.length,
|
|
1032
|
+
external_blocker_count: readiness.external_blockers.length,
|
|
1033
|
+
},
|
|
1034
|
+
status_refs: {
|
|
1035
|
+
billing_period_ref: isPlainObject(contracts.billing) ? contracts.billing.billing_record_id : 'blocked:billing',
|
|
1036
|
+
backup_drill_ref: isPlainObject(contracts.backup) ? contracts.backup.backup_drill_id : 'blocked:backup',
|
|
1037
|
+
incident_sla_ref: isPlainObject(contracts.incident_sla) ? contracts.incident_sla.incident_sla_id : 'blocked:incident_sla',
|
|
1038
|
+
operator_go_live_ref: operatorGoLiveRef,
|
|
1039
|
+
},
|
|
1040
|
+
blocker_refs: readiness.external_blockers.map((blocker) => ({
|
|
1041
|
+
surface: blocker.key,
|
|
1042
|
+
ref: blocker.ref,
|
|
1043
|
+
blocker: blocker.blocker,
|
|
1044
|
+
})),
|
|
1045
|
+
next_actions: lifecycleNextActions(readiness, operatorGoLiveRef),
|
|
1046
|
+
safety_summary: {
|
|
1047
|
+
evidence_validation_only: true,
|
|
1048
|
+
key_material_absent: true,
|
|
1049
|
+
token_material_absent: true,
|
|
1050
|
+
auth_material_absent: true,
|
|
1051
|
+
customer_content_absent: true,
|
|
1052
|
+
},
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
962
1055
|
|
|
963
1056
|
export function buildCustomerLifecyclePacket(input = {}) {
|
|
964
1057
|
if (!isPlainObject(input)) throw new TypeError('buildCustomerLifecyclePacket requires an options object');
|
|
@@ -980,6 +1073,7 @@ export function buildCustomerLifecyclePacket(input = {}) {
|
|
|
980
1073
|
missing_evidence_refs: readiness.missing_evidence_refs,
|
|
981
1074
|
operator_go_live_ref: operatorGoLiveRef,
|
|
982
1075
|
readiness,
|
|
1076
|
+
dashboard: customerLifecycleDashboard(contracts, requiredEvidenceRefs, readiness, operatorGoLiveRef),
|
|
983
1077
|
hosted_cloud_sellable: readiness.hosted_cloud_sellable,
|
|
984
1078
|
guarantees: customerLifecycleSafetyGuarantees(),
|
|
985
1079
|
public_safety_guarantees: customerLifecycleSafetyGuarantees(),
|
|
@@ -1008,6 +1102,7 @@ export function validateCustomerLifecyclePacket(packet) {
|
|
|
1008
1102
|
assertSameLifecycleArray(packet.missing_evidence_refs, expectedReadiness.missing_evidence_refs, 'missing_evidence_refs');
|
|
1009
1103
|
validateCustomerLifecycleReadiness(packet.readiness, expectedReadiness);
|
|
1010
1104
|
if (packet.hosted_cloud_sellable !== expectedReadiness.hosted_cloud_sellable) throw new TypeError('hosted_cloud_sellable must match readiness.hosted_cloud_sellable');
|
|
1105
|
+
assertSameLifecycleObject(packet.dashboard, customerLifecycleDashboard(packet.contracts, requiredEvidenceRefs, expectedReadiness, operatorGoLiveRef), 'dashboard');
|
|
1011
1106
|
validateCustomerLifecycleSafetyGuarantees(packet.guarantees ?? packet.public_safety_guarantees);
|
|
1012
1107
|
return true;
|
|
1013
1108
|
}
|
|
@@ -1400,3 +1495,376 @@ export function validateApiKeyLifecyclePacket(packet) {
|
|
|
1400
1495
|
validateApiKeyLifecycleSafetyGuarantees(packet.public_safety_guarantees ?? packet.guarantees);
|
|
1401
1496
|
return true;
|
|
1402
1497
|
}
|
|
1498
|
+
|
|
1499
|
+
function readinessEvidenceRefFor(surface, value, lifecyclePhaseEvidence) {
|
|
1500
|
+
const fallback = { ref: `blocked:${surface}`, status: BLOCKED, blocker: READINESS_BLOCKER_LABELS[surface] };
|
|
1501
|
+
if (value === undefined || value === null) {
|
|
1502
|
+
if (lifecyclePhaseEvidence && lifecyclePhaseEvidence.status === PROVIDED) {
|
|
1503
|
+
return { ref: lifecyclePhaseEvidence.ref, status: PROVIDED };
|
|
1504
|
+
}
|
|
1505
|
+
return fallback;
|
|
1506
|
+
}
|
|
1507
|
+
if (typeof value === 'string') {
|
|
1508
|
+
return { ref: requirePublicSafeLifecycleRef(value, `required_evidence_refs.${surface}`), status: PROVIDED };
|
|
1509
|
+
}
|
|
1510
|
+
if (!isPlainObject(value)) throw new TypeError(`required_evidence_refs.${surface} must be a string or object`);
|
|
1511
|
+
const status = stringOrDefault(value.status, PROVIDED);
|
|
1512
|
+
if (!EVIDENCE_STATUSES.has(status)) throw new TypeError(`required_evidence_refs.${surface}.status is invalid`);
|
|
1513
|
+
const ref = status === PROVIDED
|
|
1514
|
+
? requirePublicSafeLifecycleRef(value.ref, `required_evidence_refs.${surface}.ref`)
|
|
1515
|
+
: requiredString(value.ref, `required_evidence_refs.${surface}.ref`);
|
|
1516
|
+
assertNoForbiddenPayload(ref, `required_evidence_refs.${surface}.ref`);
|
|
1517
|
+
const evidence = { ref, status };
|
|
1518
|
+
const blocker = optionalString(value.blocker, `required_evidence_refs.${surface}.blocker`);
|
|
1519
|
+
if (status === BLOCKED) evidence.blocker = blocker ?? READINESS_BLOCKER_LABELS[surface];
|
|
1520
|
+
return evidence;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
function readinessEvidenceRefsFrom(input, lifecycleEvidenceRefs) {
|
|
1524
|
+
const explicitRefs = input.required_evidence_refs ?? input.requiredEvidenceRefs
|
|
1525
|
+
?? input.readiness_evidence_refs ?? input.readinessEvidenceRefs;
|
|
1526
|
+
const refs = isPlainObject(explicitRefs) ? explicitRefs : {};
|
|
1527
|
+
const evidenceRefs = {};
|
|
1528
|
+
for (const surface of HOSTED_CLOUD_READINESS_SURFACES) {
|
|
1529
|
+
const lifecyclePhase = READINESS_SURFACE_LIFECYCLE_PHASE[surface];
|
|
1530
|
+
const lifecycleEvidence = lifecycleEvidenceRefs ? lifecycleEvidenceRefs[lifecyclePhase] : undefined;
|
|
1531
|
+
evidenceRefs[surface] = readinessEvidenceRefFor(surface, refs[surface], lifecycleEvidence);
|
|
1532
|
+
}
|
|
1533
|
+
return evidenceRefs;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
function propagatedCustomerLifecycleBlockersFrom(lifecycleSellable, lifecycleExternalBlockers) {
|
|
1537
|
+
if (lifecycleSellable === null) {
|
|
1538
|
+
return [{
|
|
1539
|
+
key: 'customer_lifecycle_packet',
|
|
1540
|
+
ref: 'blocked:customer_lifecycle:missing',
|
|
1541
|
+
blocker: 'No customer lifecycle packet is embedded; readiness cannot confirm lifecycle sellability.',
|
|
1542
|
+
}];
|
|
1543
|
+
}
|
|
1544
|
+
if (lifecycleSellable) return [];
|
|
1545
|
+
const blockers = [{
|
|
1546
|
+
key: 'customer_lifecycle_packet',
|
|
1547
|
+
ref: 'blocked:customer_lifecycle:not_sellable',
|
|
1548
|
+
blocker: 'Embedded customer lifecycle packet is not sellable.',
|
|
1549
|
+
}];
|
|
1550
|
+
for (const blocker of lifecycleExternalBlockers) {
|
|
1551
|
+
blockers.push({
|
|
1552
|
+
key: `customer_lifecycle.${blocker.key}`,
|
|
1553
|
+
ref: blocker.ref,
|
|
1554
|
+
blocker: blocker.blocker,
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
return blockers;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
function propagatedApiKeyLifecycleBlockersFrom(operatorApprovalRef, apiKeyExternalBlockers) {
|
|
1561
|
+
if (operatorApprovalRef === undefined) {
|
|
1562
|
+
return [{
|
|
1563
|
+
key: 'api_key_lifecycle_packet',
|
|
1564
|
+
ref: 'blocked:api_key_lifecycle:missing',
|
|
1565
|
+
blocker: 'No API key lifecycle packet is embedded; readiness cannot confirm API key lifecycle operator approval evidence.',
|
|
1566
|
+
}];
|
|
1567
|
+
}
|
|
1568
|
+
return apiKeyExternalBlockers.map((blocker) => ({
|
|
1569
|
+
key: `api_key_lifecycle.${blocker.key}`,
|
|
1570
|
+
ref: blocker.ref,
|
|
1571
|
+
blocker: blocker.blocker,
|
|
1572
|
+
}));
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
function cloudReadinessAssessment(requiredEvidenceRefs, operatorGoLiveRef, lifecycleSellable, apiKeyOperatorApprovalRef, propagatedBlockers) {
|
|
1576
|
+
const missingEvidenceRefs = HOSTED_CLOUD_READINESS_SURFACES
|
|
1577
|
+
.filter((surface) => requiredEvidenceRefs[surface].status !== PROVIDED)
|
|
1578
|
+
.map((surface) => ({
|
|
1579
|
+
key: surface,
|
|
1580
|
+
ref: requiredEvidenceRefs[surface].ref,
|
|
1581
|
+
blocker: requiredEvidenceRefs[surface].blocker ?? READINESS_BLOCKER_LABELS[surface],
|
|
1582
|
+
}));
|
|
1583
|
+
const externalBlockers = [...missingEvidenceRefs, ...propagatedBlockers];
|
|
1584
|
+
if (operatorGoLiveRef === null) {
|
|
1585
|
+
externalBlockers.push({
|
|
1586
|
+
key: 'operator_go_live',
|
|
1587
|
+
ref: 'blocked:operator_go_live',
|
|
1588
|
+
blocker: READINESS_BLOCKER_LABELS.operator_go_live,
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
const sellable = missingEvidenceRefs.length === 0
|
|
1592
|
+
&& propagatedBlockers.length === 0
|
|
1593
|
+
&& operatorGoLiveRef !== null;
|
|
1594
|
+
return {
|
|
1595
|
+
...HOSTED_CLOUD_CONTRACT_READY,
|
|
1596
|
+
status: sellable ? 'operator_approved_readiness_packet' : 'blocked_readiness_evidence_or_operator_go_live',
|
|
1597
|
+
evidence_validation_only: true,
|
|
1598
|
+
lifecycle_evidence_complete: missingEvidenceRefs.length === 0,
|
|
1599
|
+
lifecycle_packet_sellable: lifecycleSellable === true,
|
|
1600
|
+
lifecycle_packet_embedded: lifecycleSellable !== null,
|
|
1601
|
+
api_key_lifecycle_operator_approved: apiKeyOperatorApprovalRef !== undefined && apiKeyOperatorApprovalRef !== null,
|
|
1602
|
+
api_key_lifecycle_packet_embedded: apiKeyOperatorApprovalRef !== undefined,
|
|
1603
|
+
operator_go_live_approved: operatorGoLiveRef !== null,
|
|
1604
|
+
external_wiring_ready: externalBlockers.length === 0,
|
|
1605
|
+
hosted_cloud_sellable: sellable,
|
|
1606
|
+
selling_gate: sellable
|
|
1607
|
+
? 'evidence_complete_operator_go_live_approved'
|
|
1608
|
+
: 'blocked_until_readiness_evidence_and_operator_go_live',
|
|
1609
|
+
propagated_lifecycle_blockers: propagatedBlockers,
|
|
1610
|
+
external_blockers: externalBlockers,
|
|
1611
|
+
missing_evidence_refs: missingEvidenceRefs,
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
function readinessSurfaceRows(requiredEvidenceRefs, operatorGoLiveRef) {
|
|
1616
|
+
const rows = HOSTED_CLOUD_READINESS_SURFACES.map((surface) => {
|
|
1617
|
+
const evidence = requiredEvidenceRefs[surface];
|
|
1618
|
+
const row = {
|
|
1619
|
+
surface,
|
|
1620
|
+
evidence_ref: evidence.ref,
|
|
1621
|
+
evidence_status: evidence.status,
|
|
1622
|
+
ready: evidence.status === PROVIDED,
|
|
1623
|
+
};
|
|
1624
|
+
if (evidence.status === BLOCKED) row.blocker = evidence.blocker ?? READINESS_BLOCKER_LABELS[surface];
|
|
1625
|
+
return row;
|
|
1626
|
+
});
|
|
1627
|
+
const goLiveRow = {
|
|
1628
|
+
surface: 'operator_go_live',
|
|
1629
|
+
evidence_ref: operatorGoLiveRef ?? 'blocked:operator_go_live',
|
|
1630
|
+
evidence_status: operatorGoLiveRef === null ? BLOCKED : PROVIDED,
|
|
1631
|
+
ready: operatorGoLiveRef !== null,
|
|
1632
|
+
};
|
|
1633
|
+
if (operatorGoLiveRef === null) goLiveRow.blocker = READINESS_BLOCKER_LABELS.operator_go_live;
|
|
1634
|
+
rows.push(goLiveRow);
|
|
1635
|
+
return rows;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
function readinessNextActions(readiness, operatorGoLiveRef) {
|
|
1639
|
+
const actions = [];
|
|
1640
|
+
for (const missing of readiness.missing_evidence_refs) {
|
|
1641
|
+
actions.push({
|
|
1642
|
+
action: `provide_${missing.key}_evidence`,
|
|
1643
|
+
surface: missing.key,
|
|
1644
|
+
ref: missing.ref,
|
|
1645
|
+
});
|
|
1646
|
+
}
|
|
1647
|
+
if (readiness.propagated_lifecycle_blockers && readiness.propagated_lifecycle_blockers.length > 0) {
|
|
1648
|
+
actions.push({
|
|
1649
|
+
action: 'resolve_customer_lifecycle_blockers',
|
|
1650
|
+
surface: 'customer_lifecycle_packet',
|
|
1651
|
+
ref: readiness.propagated_lifecycle_blockers[0].ref,
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
if (operatorGoLiveRef === null) {
|
|
1655
|
+
actions.push({
|
|
1656
|
+
action: 'obtain_operator_go_live_approval',
|
|
1657
|
+
surface: 'operator_go_live',
|
|
1658
|
+
ref: 'blocked:operator_go_live',
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
if (actions.length === 0) {
|
|
1662
|
+
actions.push({
|
|
1663
|
+
action: 'readiness_complete_review_before_selling',
|
|
1664
|
+
surface: 'operator_go_live',
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
return actions;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
function cloudReadinessDashboard(requiredEvidenceRefs, readiness, operatorGoLiveRef, lifecycleRef) {
|
|
1671
|
+
const providedCount = HOSTED_CLOUD_READINESS_SURFACES
|
|
1672
|
+
.filter((surface) => requiredEvidenceRefs[surface].status === PROVIDED).length;
|
|
1673
|
+
return {
|
|
1674
|
+
counts: {
|
|
1675
|
+
readiness_surface_count: HOSTED_CLOUD_READINESS_SURFACES.length + 1,
|
|
1676
|
+
provided_evidence_count: providedCount,
|
|
1677
|
+
missing_evidence_count: readiness.missing_evidence_refs.length,
|
|
1678
|
+
external_blocker_count: readiness.external_blockers.length,
|
|
1679
|
+
},
|
|
1680
|
+
status_refs: {
|
|
1681
|
+
customer_lifecycle_packet_ref: lifecycleRef,
|
|
1682
|
+
operator_go_live_ref: operatorGoLiveRef,
|
|
1683
|
+
},
|
|
1684
|
+
blocker_refs: readiness.external_blockers.map((blocker) => ({
|
|
1685
|
+
surface: blocker.key,
|
|
1686
|
+
ref: blocker.ref,
|
|
1687
|
+
blocker: blocker.blocker,
|
|
1688
|
+
})),
|
|
1689
|
+
next_actions: readinessNextActions(readiness, operatorGoLiveRef),
|
|
1690
|
+
safety_summary: {
|
|
1691
|
+
evidence_validation_only: true,
|
|
1692
|
+
key_material_absent: true,
|
|
1693
|
+
token_material_absent: true,
|
|
1694
|
+
auth_material_absent: true,
|
|
1695
|
+
customer_content_absent: true,
|
|
1696
|
+
},
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
function cloudReadinessSafetyGuarantees() {
|
|
1701
|
+
return {
|
|
1702
|
+
opaque_reference_only: true,
|
|
1703
|
+
customer_content_absent: true,
|
|
1704
|
+
sensitive_text_absent: true,
|
|
1705
|
+
auth_material_absent: true,
|
|
1706
|
+
provider_payloads_absent: true,
|
|
1707
|
+
evidence_validation_only: true,
|
|
1708
|
+
financial_outcome_claim_absent: true,
|
|
1709
|
+
remote_erasure_claim_absent: true,
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
function validateCloudReadinessSafetyGuarantees(guarantees) {
|
|
1714
|
+
if (!isPlainObject(guarantees)) throw new TypeError('public_safety_guarantees must be present');
|
|
1715
|
+
requiredTrue(guarantees.opaque_reference_only, 'public_safety_guarantees.opaque_reference_only');
|
|
1716
|
+
requiredTrue(guarantees.customer_content_absent, 'public_safety_guarantees.customer_content_absent');
|
|
1717
|
+
requiredTrue(guarantees.sensitive_text_absent, 'public_safety_guarantees.sensitive_text_absent');
|
|
1718
|
+
requiredTrue(guarantees.auth_material_absent, 'public_safety_guarantees.auth_material_absent');
|
|
1719
|
+
requiredTrue(guarantees.provider_payloads_absent, 'public_safety_guarantees.provider_payloads_absent');
|
|
1720
|
+
requiredTrue(guarantees.evidence_validation_only, 'public_safety_guarantees.evidence_validation_only');
|
|
1721
|
+
requiredTrue(guarantees.financial_outcome_claim_absent, 'public_safety_guarantees.financial_outcome_claim_absent');
|
|
1722
|
+
requiredTrue(guarantees.remote_erasure_claim_absent, 'public_safety_guarantees.remote_erasure_claim_absent');
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
function validateCloudReadinessReadiness(readiness, expected) {
|
|
1726
|
+
if (!isPlainObject(readiness)) throw new TypeError('readiness must be present');
|
|
1727
|
+
requiredTrue(readiness.contract_ready, 'readiness.contract_ready');
|
|
1728
|
+
if (readiness.integration_kind !== HOSTED_CLOUD_CONTRACT_READY.integration_kind) throw new TypeError('readiness.integration_kind must remain contract_validator_only');
|
|
1729
|
+
requiredTrue(readiness.no_external_provider_calls, 'readiness.no_external_provider_calls');
|
|
1730
|
+
requiredTrue(readiness.evidence_validation_only, 'readiness.evidence_validation_only');
|
|
1731
|
+
if (readiness.status !== expected.status) throw new TypeError('readiness.status must match readiness evidence and operator go-live approval');
|
|
1732
|
+
if (readiness.lifecycle_evidence_complete !== expected.lifecycle_evidence_complete) throw new TypeError('readiness.lifecycle_evidence_complete must match required_evidence_refs');
|
|
1733
|
+
if (readiness.lifecycle_packet_sellable !== expected.lifecycle_packet_sellable) throw new TypeError('readiness.lifecycle_packet_sellable must match embedded lifecycle packet');
|
|
1734
|
+
if (readiness.lifecycle_packet_embedded !== expected.lifecycle_packet_embedded) throw new TypeError('readiness.lifecycle_packet_embedded must match embedded lifecycle packet');
|
|
1735
|
+
if (readiness.api_key_lifecycle_operator_approved !== expected.api_key_lifecycle_operator_approved) throw new TypeError('readiness.api_key_lifecycle_operator_approved must match embedded API key lifecycle operator approval evidence');
|
|
1736
|
+
if (readiness.api_key_lifecycle_packet_embedded !== expected.api_key_lifecycle_packet_embedded) throw new TypeError('readiness.api_key_lifecycle_packet_embedded must match embedded API key lifecycle packet');
|
|
1737
|
+
if (readiness.operator_go_live_approved !== expected.operator_go_live_approved) throw new TypeError('readiness.operator_go_live_approved must match operator_go_live_ref');
|
|
1738
|
+
if (readiness.external_wiring_ready !== expected.external_wiring_ready) throw new TypeError('readiness.external_wiring_ready must match blockers');
|
|
1739
|
+
if (readiness.hosted_cloud_sellable !== expected.hosted_cloud_sellable) throw new TypeError('readiness.hosted_cloud_sellable must match readiness evidence and operator go-live approval');
|
|
1740
|
+
if (readiness.selling_gate !== expected.selling_gate) throw new TypeError('readiness.selling_gate must match readiness evidence and operator go-live approval');
|
|
1741
|
+
assertSameLifecycleArray(readiness.propagated_lifecycle_blockers, expected.propagated_lifecycle_blockers, 'readiness.propagated_lifecycle_blockers');
|
|
1742
|
+
assertSameLifecycleArray(readiness.external_blockers, expected.external_blockers, 'readiness.external_blockers');
|
|
1743
|
+
assertSameLifecycleArray(readiness.missing_evidence_refs, expected.missing_evidence_refs, 'readiness.missing_evidence_refs');
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
function validateReadinessEvidenceRefs(packet) {
|
|
1747
|
+
if (!isPlainObject(packet.required_evidence_refs)) throw new TypeError('required_evidence_refs must be present');
|
|
1748
|
+
for (const key of Object.keys(packet.required_evidence_refs)) {
|
|
1749
|
+
if (!HOSTED_CLOUD_READINESS_SURFACES.includes(key)) throw new TypeError(`required_evidence_refs.${key} is not a readiness surface`);
|
|
1750
|
+
}
|
|
1751
|
+
const requiredEvidenceRefs = {};
|
|
1752
|
+
for (const surface of HOSTED_CLOUD_READINESS_SURFACES) {
|
|
1753
|
+
if (!Object.prototype.hasOwnProperty.call(packet.required_evidence_refs, surface)) throw new TypeError(`required_evidence_refs.${surface} must be present`);
|
|
1754
|
+
requiredEvidenceRefs[surface] = readinessEvidenceRefFor(surface, packet.required_evidence_refs[surface], null);
|
|
1755
|
+
}
|
|
1756
|
+
return requiredEvidenceRefs;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
export function buildHostedCloudReadinessPacket(input = {}) {
|
|
1760
|
+
if (!isPlainObject(input)) throw new TypeError('buildHostedCloudReadinessPacket requires an options object');
|
|
1761
|
+
assertNoForbiddenPayload(input, 'input');
|
|
1762
|
+
const generatedAt = isoTimestamp(input.generated_at ?? input.generatedAt, 'generated_at');
|
|
1763
|
+
const operatorGoLiveRef = operatorGoLiveRefFromInput(input);
|
|
1764
|
+
let lifecycleSellable = null;
|
|
1765
|
+
let lifecycleEvidenceRefs = null;
|
|
1766
|
+
let lifecycleRef = null;
|
|
1767
|
+
let apiKeyOperatorApprovalRef = undefined;
|
|
1768
|
+
let apiKeyLifecycleRef = null;
|
|
1769
|
+
const providedLifecyclePacket = input.customer_lifecycle_packet ?? input.customerLifecyclePacket;
|
|
1770
|
+
if (providedLifecyclePacket !== undefined && providedLifecyclePacket !== null) {
|
|
1771
|
+
if (!isPlainObject(providedLifecyclePacket)) throw new TypeError('customer_lifecycle_packet must be an object');
|
|
1772
|
+
validateCustomerLifecyclePacket(providedLifecyclePacket);
|
|
1773
|
+
lifecycleSellable = providedLifecyclePacket.hosted_cloud_sellable;
|
|
1774
|
+
lifecycleEvidenceRefs = providedLifecyclePacket.required_evidence_refs;
|
|
1775
|
+
lifecycleRef = {
|
|
1776
|
+
schema: providedLifecyclePacket.schema,
|
|
1777
|
+
packet_id: providedLifecyclePacket.packet_id,
|
|
1778
|
+
contract_hash: providedLifecyclePacket.contract_hash,
|
|
1779
|
+
hosted_cloud_sellable: providedLifecyclePacket.hosted_cloud_sellable,
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
const providedApiKeyPacket = input.api_key_lifecycle_packet ?? input.apiKeyLifecyclePacket;
|
|
1783
|
+
if (providedApiKeyPacket !== undefined && providedApiKeyPacket !== null) {
|
|
1784
|
+
if (!isPlainObject(providedApiKeyPacket)) throw new TypeError('api_key_lifecycle_packet must be an object');
|
|
1785
|
+
validateApiKeyLifecyclePacket(providedApiKeyPacket);
|
|
1786
|
+
apiKeyOperatorApprovalRef = providedApiKeyPacket.operator_approval_ref;
|
|
1787
|
+
apiKeyLifecycleRef = {
|
|
1788
|
+
schema: providedApiKeyPacket.schema,
|
|
1789
|
+
packet_id: providedApiKeyPacket.packet_id,
|
|
1790
|
+
contract_hash: providedApiKeyPacket.contract_hash,
|
|
1791
|
+
operator_approval_ref: providedApiKeyPacket.operator_approval_ref,
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
const lifecycleExternalBlockers = (providedLifecyclePacket && isPlainObject(providedLifecyclePacket)) ? providedLifecyclePacket.external_blockers : [];
|
|
1795
|
+
const apiKeyExternalBlockers = (providedApiKeyPacket && isPlainObject(providedApiKeyPacket)) ? providedApiKeyPacket.external_blockers : [];
|
|
1796
|
+
const propagatedBlockers = [
|
|
1797
|
+
...propagatedCustomerLifecycleBlockersFrom(lifecycleSellable, lifecycleExternalBlockers),
|
|
1798
|
+
...propagatedApiKeyLifecycleBlockersFrom(apiKeyOperatorApprovalRef, apiKeyExternalBlockers),
|
|
1799
|
+
];
|
|
1800
|
+
const requiredEvidenceRefs = readinessEvidenceRefsFrom(input, lifecycleEvidenceRefs);
|
|
1801
|
+
const readiness = cloudReadinessAssessment(requiredEvidenceRefs, operatorGoLiveRef, lifecycleSellable, apiKeyOperatorApprovalRef, propagatedBlockers);
|
|
1802
|
+
const body = {
|
|
1803
|
+
schema: HOSTED_CLOUD_READINESS_PACKET_SCHEMA,
|
|
1804
|
+
readiness_id: stringOrDefault(input.readiness_id ?? input.readinessId, undefined),
|
|
1805
|
+
generated_at: generatedAt,
|
|
1806
|
+
customer_lifecycle_packet: lifecycleRef,
|
|
1807
|
+
api_key_lifecycle_packet: apiKeyLifecycleRef,
|
|
1808
|
+
required_evidence_refs: requiredEvidenceRefs,
|
|
1809
|
+
readiness_surfaces: readinessSurfaceRows(requiredEvidenceRefs, operatorGoLiveRef),
|
|
1810
|
+
propagated_lifecycle_blockers: readiness.propagated_lifecycle_blockers,
|
|
1811
|
+
operator_go_live_ref: operatorGoLiveRef,
|
|
1812
|
+
external_blockers: readiness.external_blockers,
|
|
1813
|
+
missing_evidence_refs: readiness.missing_evidence_refs,
|
|
1814
|
+
readiness,
|
|
1815
|
+
dashboard: cloudReadinessDashboard(requiredEvidenceRefs, readiness, operatorGoLiveRef, lifecycleRef),
|
|
1816
|
+
hosted_cloud_sellable: readiness.hosted_cloud_sellable,
|
|
1817
|
+
guarantees: cloudReadinessSafetyGuarantees(),
|
|
1818
|
+
public_safety_guarantees: cloudReadinessSafetyGuarantees(),
|
|
1819
|
+
};
|
|
1820
|
+
const packet = withContractIdentity(body, 'hcrp', 'readiness_id');
|
|
1821
|
+
validateHostedCloudReadinessPacket(packet);
|
|
1822
|
+
return packet;
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
export function validateHostedCloudReadinessPacket(packet) {
|
|
1826
|
+
if (!isPlainObject(packet)) throw new TypeError('packet must be an object');
|
|
1827
|
+
assertNoForbiddenPayload(packet, 'packet');
|
|
1828
|
+
if (packet.schema !== HOSTED_CLOUD_READINESS_PACKET_SCHEMA) throw new TypeError(`schema must be ${HOSTED_CLOUD_READINESS_PACKET_SCHEMA}`);
|
|
1829
|
+
requiredString(packet.readiness_id, 'readiness_id');
|
|
1830
|
+
isoTimestamp(packet.generated_at, 'generated_at');
|
|
1831
|
+
requiredString(packet.contract_hash, 'contract_hash');
|
|
1832
|
+
if (!Object.prototype.hasOwnProperty.call(packet, 'customer_lifecycle_packet')) throw new TypeError('customer_lifecycle_packet must be present');
|
|
1833
|
+
if (packet.customer_lifecycle_packet !== null) {
|
|
1834
|
+
if (!isPlainObject(packet.customer_lifecycle_packet)) throw new TypeError('customer_lifecycle_packet must be an object or null');
|
|
1835
|
+
requiredString(packet.customer_lifecycle_packet.schema, 'customer_lifecycle_packet.schema');
|
|
1836
|
+
requiredString(packet.customer_lifecycle_packet.packet_id, 'customer_lifecycle_packet.packet_id');
|
|
1837
|
+
requiredString(packet.customer_lifecycle_packet.contract_hash, 'customer_lifecycle_packet.contract_hash');
|
|
1838
|
+
requiredBoolean(packet.customer_lifecycle_packet.hosted_cloud_sellable, 'customer_lifecycle_packet.hosted_cloud_sellable');
|
|
1839
|
+
}
|
|
1840
|
+
if (!Object.prototype.hasOwnProperty.call(packet, 'api_key_lifecycle_packet')) throw new TypeError('api_key_lifecycle_packet must be present');
|
|
1841
|
+
if (packet.api_key_lifecycle_packet !== null) {
|
|
1842
|
+
if (!isPlainObject(packet.api_key_lifecycle_packet)) throw new TypeError('api_key_lifecycle_packet must be an object or null');
|
|
1843
|
+
requiredString(packet.api_key_lifecycle_packet.schema, 'api_key_lifecycle_packet.schema');
|
|
1844
|
+
requiredString(packet.api_key_lifecycle_packet.packet_id, 'api_key_lifecycle_packet.packet_id');
|
|
1845
|
+
requiredString(packet.api_key_lifecycle_packet.contract_hash, 'api_key_lifecycle_packet.contract_hash');
|
|
1846
|
+
if (!Object.prototype.hasOwnProperty.call(packet.api_key_lifecycle_packet, 'operator_approval_ref')) throw new TypeError('api_key_lifecycle_packet.operator_approval_ref must be present');
|
|
1847
|
+
if (packet.api_key_lifecycle_packet.operator_approval_ref !== null) {
|
|
1848
|
+
requirePublicSafeLifecycleRef(packet.api_key_lifecycle_packet.operator_approval_ref, 'api_key_lifecycle_packet.operator_approval_ref');
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
if (!Array.isArray(packet.propagated_lifecycle_blockers)) throw new TypeError('propagated_lifecycle_blockers must be an array');
|
|
1852
|
+
const requiredEvidenceRefs = validateReadinessEvidenceRefs(packet);
|
|
1853
|
+
const operatorGoLiveRef = operatorGoLiveRefFromPacket(packet);
|
|
1854
|
+
const lifecycleSellable = packet.customer_lifecycle_packet === null
|
|
1855
|
+
? null
|
|
1856
|
+
: packet.customer_lifecycle_packet.hosted_cloud_sellable;
|
|
1857
|
+
const apiKeyOperatorApprovalRef = packet.api_key_lifecycle_packet === null
|
|
1858
|
+
? undefined
|
|
1859
|
+
: packet.api_key_lifecycle_packet.operator_approval_ref;
|
|
1860
|
+
const expectedReadiness = cloudReadinessAssessment(requiredEvidenceRefs, operatorGoLiveRef, lifecycleSellable, apiKeyOperatorApprovalRef, packet.propagated_lifecycle_blockers);
|
|
1861
|
+
assertSameLifecycleArray(packet.readiness_surfaces, readinessSurfaceRows(requiredEvidenceRefs, operatorGoLiveRef), 'readiness_surfaces');
|
|
1862
|
+
assertSameLifecycleArray(packet.external_blockers, expectedReadiness.external_blockers, 'external_blockers');
|
|
1863
|
+
assertSameLifecycleArray(packet.missing_evidence_refs, expectedReadiness.missing_evidence_refs, 'missing_evidence_refs');
|
|
1864
|
+
validateCloudReadinessReadiness(packet.readiness, expectedReadiness);
|
|
1865
|
+
if (packet.hosted_cloud_sellable !== expectedReadiness.hosted_cloud_sellable) throw new TypeError('hosted_cloud_sellable must match readiness.hosted_cloud_sellable');
|
|
1866
|
+
assertSameLifecycleObject(packet.dashboard, cloudReadinessDashboard(requiredEvidenceRefs, expectedReadiness, operatorGoLiveRef, packet.customer_lifecycle_packet), 'dashboard');
|
|
1867
|
+
validateCloudReadinessSafetyGuarantees(packet.guarantees ?? packet.public_safety_guarantees);
|
|
1868
|
+
validateCloudReadinessSafetyGuarantees(packet.public_safety_guarantees ?? packet.guarantees);
|
|
1869
|
+
return true;
|
|
1870
|
+
}
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
const DEFAULT_BUNDLE = '.enigma/bundle.json';
|
|
18
18
|
const JSONRPC_VERSION = '2.0';
|
|
19
19
|
const MCP_PROTOCOL_VERSION = '2024-11-05';
|
|
20
|
-
const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.
|
|
20
|
+
const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.17' });
|
|
21
21
|
const JSON_RPC_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
22
22
|
const JSON_RPC_ERROR = Object.freeze({
|
|
23
23
|
INVALID_REQUEST: -32600,
|