enigma-memory 0.1.0
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/LICENSE +55 -0
- package/README.md +379 -0
- package/apps/cli/bin/enigma.mjs +1117 -0
- package/apps/desktop/src/app.js +1327 -0
- package/apps/desktop/src/index.html +1373 -0
- package/apps/desktop/src/styles.css +386 -0
- package/apps/gateway/bin/enigma-gateway.mjs +52 -0
- package/apps/gateway/src/server.mjs +1403 -0
- package/apps/native-host/README.md +265 -0
- package/apps/native-host/bin/enigma-native-host.mjs +499 -0
- package/apps/native-host/manifests/com.enigma.native_host.chrome.json +9 -0
- package/apps/native-host/manifests/com.enigma.native_host.edge.json +9 -0
- package/apps/native-host/manifests/com.enigma.native_host.firefox.json +9 -0
- package/apps/relay/bin/enigma-relay.mjs +52 -0
- package/apps/relay/src/server.mjs +1571 -0
- package/apps/verifier/bin/enigma-verify.mjs +240 -0
- package/deploy/docker-compose.production.example.yml +150 -0
- package/deploy/kubernetes/enigma-backend.example.yaml +580 -0
- package/package.json +196 -0
- package/packages/adapters/PACKAGE_CONTRACT.md +47 -0
- package/packages/adapters/src/index.js +183 -0
- package/packages/boundary/src/index.js +468 -0
- package/packages/connectors/src/index.js +533 -0
- package/packages/core/src/index.js +766 -0
- package/packages/enterprise/src/index.js +505 -0
- package/packages/importers/src/index.js +1083 -0
- package/packages/mcp-server/bin/enigma-mcp.mjs +19 -0
- package/packages/mcp-server/src/index.js +1185 -0
- package/packages/mesh/src/index.js +531 -0
- package/packages/metering/PACKAGE_CONTRACT.md +20 -0
- package/packages/metering/src/index.js +246 -0
- package/packages/optimizer/src/index.js +707 -0
- package/packages/passport/src/index.js +651 -0
- package/packages/settlement/PACKAGE_CONTRACT.md +28 -0
- package/packages/settlement/src/index.js +369 -0
- package/packages/storage/PACKAGE_CONTRACT.md +23 -0
- package/packages/storage/src/index.js +392 -0
- package/packages/vault/src/index.js +904 -0
- package/scripts/build-ai-orchestration-plan.mjs +248 -0
- package/scripts/build-cloudflare-pages-release-packet.mjs +287 -0
- package/scripts/build-cloudflare-token-policy.mjs +239 -0
- package/scripts/build-cloudflare-token-request.mjs +314 -0
- package/scripts/build-demo-assets.mjs +263 -0
- package/scripts/build-edge-backend-workers.mjs +353 -0
- package/scripts/build-goal-completion-audit.mjs +398 -0
- package/scripts/build-hosted-probe-worker.mjs +191 -0
- package/scripts/build-operator-acceptance-packet.mjs +254 -0
- package/scripts/build-operator-evidence-starter.mjs +525 -0
- package/scripts/build-production-backend-env-kit.mjs +384 -0
- package/scripts/build-production-dependency-report.mjs +369 -0
- package/scripts/build-production-handoff-packet.mjs +475 -0
- package/scripts/build-production-readiness-manifest.mjs +209 -0
- package/scripts/build-production-status-board.mjs +297 -0
- package/scripts/build-production-storage-migration.mjs +86 -0
- package/scripts/build-production-workplan.mjs +371 -0
- package/scripts/build-review-packet.mjs +594 -0
- package/scripts/check.mjs +419 -0
- package/scripts/cloudflare-ops.mjs +1672 -0
- package/scripts/cloudflare-secret-env.mjs +128 -0
- package/scripts/collect-hosted-backend-live-evidence.mjs +263 -0
- package/scripts/infrastructure-readiness.mjs +944 -0
- package/scripts/install-enigma-local.mjs +270 -0
- package/scripts/memory-optimization-benchmark.mjs +242 -0
- package/scripts/monitor-live-endpoints.mjs +358 -0
- package/scripts/release-audit.mjs +5588 -0
- package/scripts/release-provenance.mjs +250 -0
- package/scripts/run-backend-readiness-smoke.mjs +220 -0
- package/scripts/validate-backup-restore-drill.mjs +166 -0
- package/scripts/validate-cloudflare-credentials.mjs +112 -0
- package/scripts/validate-cloudflare-worker-inspect.mjs +179 -0
- package/scripts/validate-domain-tls.mjs +248 -0
- package/scripts/validate-hosted-backend-live.mjs +319 -0
- package/scripts/validate-incident-drill.mjs +221 -0
- package/scripts/validate-kms-custody.mjs +235 -0
- package/scripts/validate-legal-compliance-approval.mjs +274 -0
- package/scripts/validate-monitoring-alerting.mjs +263 -0
- package/scripts/validate-network-access-policy.mjs +285 -0
- package/scripts/validate-operator-acceptance.mjs +298 -0
- package/scripts/validate-production-manifests.mjs +325 -0
- package/scripts/validate-public-site-security.mjs +252 -0
- package/scripts/validate-security-threat-model.mjs +285 -0
- package/scripts/validate-service-settlement.mjs +256 -0
- package/scripts/validate-support-sla.mjs +190 -0
- package/scripts/validate-tenant-policy-approval.mjs +228 -0
- package/scripts/validate-usage-metering.mjs +224 -0
- package/scripts/validate-whitepaper-claims.mjs +166 -0
- package/specs/boundary-manifest-v1.schema.json +35 -0
- package/specs/capsule-v1.schema.json +55 -0
- package/specs/claim-boundary-manifest-v1.schema.json +22 -0
- package/specs/connector-profile-v1.schema.json +62 -0
- package/specs/deletion-tombstone-v1.schema.json +26 -0
- package/specs/enterprise-policy-v1.schema.json +59 -0
- package/specs/gateway-request-v1.schema.json +32 -0
- package/specs/goal-completion-audit-v1.schema.json +70 -0
- package/specs/hosted-backend-live-evidence-v1.schema.json +147 -0
- package/specs/import-report-v1.schema.json +214 -0
- package/specs/infrastructure-readiness-manifest-v1.schema.json +130 -0
- package/specs/memory-event-v1.schema.json +42 -0
- package/specs/mesh-node-v1.schema.json +126 -0
- package/specs/passport-v1.schema.json +50 -0
- package/specs/production-handoff-packet-v1.schema.json +149 -0
- package/specs/receipt-v1.schema.json +61 -0
- package/specs/relay-record-v1.schema.json +43 -0
- package/specs/state-checkpoint-v1.schema.json +37 -0
- package/specs/trust-bundle-v1.schema.json +56 -0
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { canonicalize, receiptHash, sha256Hex, verifyReceipt } from '../../core/src/index.js';
|
|
3
|
+
import {
|
|
4
|
+
createMemoryAccessReceipt,
|
|
5
|
+
createMemoryOptimizationPlan,
|
|
6
|
+
estimateTextTokens,
|
|
7
|
+
} from '../../optimizer/src/index.js';
|
|
8
|
+
|
|
9
|
+
const PASSPORT_SCHEMA = 'enigma.passport.v1';
|
|
10
|
+
const CONTEXT_PACK_SCHEMA = 'enigma.context_pack.v1';
|
|
11
|
+
const ZERO_ROOT = `sha256:${'0'.repeat(64)}`;
|
|
12
|
+
const ROOT_RE = /^sha256:[a-f0-9]{64}$/;
|
|
13
|
+
const PREVIOUS_RECEIPT_RE = /^(GENESIS|sha256:[a-f0-9]{64})$/;
|
|
14
|
+
const RECEIPT_TOP_LEVEL_FIELDS = new Set([
|
|
15
|
+
'schema',
|
|
16
|
+
'receipt_id',
|
|
17
|
+
'event_hash',
|
|
18
|
+
'operation',
|
|
19
|
+
'tenant_id',
|
|
20
|
+
'subject_id',
|
|
21
|
+
'memory_addr',
|
|
22
|
+
'source_addr',
|
|
23
|
+
'provider',
|
|
24
|
+
'model',
|
|
25
|
+
'policy_id',
|
|
26
|
+
'sequence',
|
|
27
|
+
'previous_receipt_hash',
|
|
28
|
+
'active_set_root',
|
|
29
|
+
'receipt_log_root',
|
|
30
|
+
'timestamp',
|
|
31
|
+
'signer',
|
|
32
|
+
'signature'
|
|
33
|
+
]);
|
|
34
|
+
const RECEIPT_SIGNATURE_FIELDS = new Set(['alg', 'value']);
|
|
35
|
+
const PUBLIC_PLAINTEXT_KEYS = new Set(['body', 'content', 'context', 'contexttext', 'memory', 'memories', 'plain', 'plaintext', 'prompt', 'raw', 'rawmemory', 'rawmemories', 'response', 'text']);
|
|
36
|
+
const SOURCE_REF_ROOT_RE = /^sha256:[a-f0-9]{64}$/;
|
|
37
|
+
const PUBLIC_KEY_REQUIRED_FOR_CONTEXT_PACK_VERIFICATION = 'PUBLIC_KEY_REQUIRED_FOR_CONTEXT_PACK_VERIFICATION';
|
|
38
|
+
|
|
39
|
+
function normalizedPublicKey(key) {
|
|
40
|
+
return String(key).toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isPlaintextLikeKey(key) {
|
|
44
|
+
return PUBLIC_PLAINTEXT_KEYS.has(normalizedPublicKey(key));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isSourceRefPlaintextLikeKey(key) {
|
|
48
|
+
return isPlaintextLikeKey(key) || normalizedPublicKey(key) === 'value';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function privateCommitmentKey(key) {
|
|
52
|
+
return `private_field_${sha256Hex(normalizedPublicKey(key)).slice(0, 12)}_commitment`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function sourceRefCommitment(value) {
|
|
56
|
+
return `sha256:${sha256Hex(String(value))}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
function sanitizeSourceRefValue(value) {
|
|
61
|
+
if (value === undefined || value === null) return undefined;
|
|
62
|
+
if (typeof value === 'string') return sourceRefCommitment(value);
|
|
63
|
+
if (['number', 'boolean'].includes(typeof value)) return value;
|
|
64
|
+
if (Array.isArray(value)) return value.map(sanitizeSourceRefValue).filter((item) => item !== undefined);
|
|
65
|
+
if (typeof value !== 'object') return undefined;
|
|
66
|
+
|
|
67
|
+
const out = {};
|
|
68
|
+
for (const [key, item] of Object.entries(value)) {
|
|
69
|
+
if (isSourceRefPlaintextLikeKey(key)) {
|
|
70
|
+
if (item !== undefined && item !== null && ['string', 'number', 'boolean'].includes(typeof item)) {
|
|
71
|
+
out[privateCommitmentKey(key)] = sourceRefCommitment(item);
|
|
72
|
+
}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (key === 'source_hash' && typeof item === 'string' && SOURCE_REF_ROOT_RE.test(item)) {
|
|
76
|
+
out[key] = item;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const sanitized = sanitizeSourceRefValue(item);
|
|
80
|
+
if (sanitized !== undefined) out[key] = sanitized;
|
|
81
|
+
}
|
|
82
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function sanitizeSourceRefs(refs) {
|
|
86
|
+
if (!Array.isArray(refs)) return [];
|
|
87
|
+
const out = [];
|
|
88
|
+
for (const ref of refs) {
|
|
89
|
+
if (typeof ref === 'string') {
|
|
90
|
+
out.push({ source_hash: sourceRefCommitment(ref) });
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const sanitized = sanitizeSourceRefValue(ref);
|
|
94
|
+
if (sanitized !== undefined) out.push(sanitized);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function canonical(value) {
|
|
100
|
+
try {
|
|
101
|
+
const encoded = canonicalize(value);
|
|
102
|
+
return typeof encoded === 'string' ? encoded : JSON.stringify(encoded);
|
|
103
|
+
} catch {
|
|
104
|
+
return stableStringify(value);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function stableStringify(value) {
|
|
109
|
+
if (value === null || typeof value !== 'object') return JSON.stringify(value);
|
|
110
|
+
if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(',')}]`;
|
|
111
|
+
return `{${Object.keys(value)
|
|
112
|
+
.sort()
|
|
113
|
+
.map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`)
|
|
114
|
+
.join(',')}}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function nowIso(now) {
|
|
118
|
+
if (now instanceof Date) return now.toISOString();
|
|
119
|
+
if (typeof now === 'string') return new Date(now).toISOString();
|
|
120
|
+
return new Date().toISOString();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function rootsFromVault(vault) {
|
|
124
|
+
if (vault?.__computeRoots) return vault.__computeRoots();
|
|
125
|
+
return {
|
|
126
|
+
active_set_root: vault?.active_set_root ?? ZERO_ROOT,
|
|
127
|
+
receipt_log_root: vault?.receipt_log_root ?? ZERO_ROOT,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function activeAddressesFrom(input) {
|
|
132
|
+
if (!input) return new Set();
|
|
133
|
+
if (input instanceof Set) return new Set(input);
|
|
134
|
+
if (Array.isArray(input)) return new Set(input);
|
|
135
|
+
if (input.activeAddresses instanceof Set) return new Set(input.activeAddresses);
|
|
136
|
+
if (Array.isArray(input.active_memory_addresses)) return new Set(input.active_memory_addresses);
|
|
137
|
+
if (Array.isArray(input.activeState)) return new Set(input.activeState);
|
|
138
|
+
if (Array.isArray(input.active_memory_addresses)) return new Set(input.active_memory_addresses);
|
|
139
|
+
return new Set();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function tombstoneAddressesFrom(input) {
|
|
143
|
+
if (!input) return new Set();
|
|
144
|
+
if (input instanceof Map) return new Set(input.keys());
|
|
145
|
+
if (Array.isArray(input)) return new Set(input.map((item) => item.memory_addr ?? item.memoryAddr ?? item));
|
|
146
|
+
if (input.tombstones instanceof Map) return new Set(input.tombstones.keys());
|
|
147
|
+
if (Array.isArray(input.tombstones)) return new Set(input.tombstones.map((item) => item.memory_addr ?? item.memoryAddr ?? item));
|
|
148
|
+
return new Set();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function memoryAddressesFromPack(contextPack) {
|
|
152
|
+
const addresses = new Set(contextPack?.memory_addresses ?? []);
|
|
153
|
+
for (const memory of contextPack?.memories ?? []) {
|
|
154
|
+
if (memory?.memory_addr) addresses.add(memory.memory_addr);
|
|
155
|
+
}
|
|
156
|
+
return [...addresses];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function publicMemory(record, content) {
|
|
160
|
+
return {
|
|
161
|
+
memory_addr: record.memory_addr,
|
|
162
|
+
memory_id: record.memory_id,
|
|
163
|
+
subject_id: record.subject_id,
|
|
164
|
+
kind: record.kind,
|
|
165
|
+
sensitivity: record.sensitivity,
|
|
166
|
+
purpose_tags: record.purpose_tags ?? [],
|
|
167
|
+
source_refs: sanitizeSourceRefs(record.source_refs),
|
|
168
|
+
confidence: record.confidence,
|
|
169
|
+
content,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function optimizerEnabled(args) {
|
|
174
|
+
return args.optimize === true
|
|
175
|
+
|| args.optimize_context === true
|
|
176
|
+
|| args.optimizeContext === true
|
|
177
|
+
|| args.max_estimated_tokens !== undefined
|
|
178
|
+
|| args.maxEstimatedTokens !== undefined
|
|
179
|
+
|| args.pricing !== undefined
|
|
180
|
+
|| args.price_per_million_tokens !== undefined
|
|
181
|
+
|| args.pricePerMillionTokens !== undefined;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function contextPackPricing(args) {
|
|
185
|
+
const price = args.pricing ?? args.price ?? args.price_per_million_tokens ?? args.pricePerMillionTokens;
|
|
186
|
+
if (price === undefined || price === null || price === '') return undefined;
|
|
187
|
+
if (typeof price === 'object') return price;
|
|
188
|
+
return {
|
|
189
|
+
price_per_million_tokens: Number(price),
|
|
190
|
+
currency: args.currency ?? 'USD',
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function optimizationCandidateFrom(vault, memoryAddr) {
|
|
195
|
+
const record = vault.__getRecord(memoryAddr);
|
|
196
|
+
if (!record || record.state !== 'active') return null;
|
|
197
|
+
const content = vault.__getPlaintext(memoryAddr);
|
|
198
|
+
return {
|
|
199
|
+
address: memoryAddr,
|
|
200
|
+
content,
|
|
201
|
+
importance: typeof record.importance === 'number' ? record.importance : typeof record.confidence === 'number' ? record.confidence : undefined,
|
|
202
|
+
last_accessed_at: record.updated_at ?? record.created_at,
|
|
203
|
+
metadata: {
|
|
204
|
+
kind: record.kind,
|
|
205
|
+
sensitivity: record.sensitivity,
|
|
206
|
+
purpose_tags: record.purpose_tags ?? [],
|
|
207
|
+
source_refs: sanitizeSourceRefs(record.source_refs),
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function optimizedSelectionFrom(args, candidateAddresses, limit) {
|
|
213
|
+
const candidates = [];
|
|
214
|
+
for (const memoryAddr of candidateAddresses) {
|
|
215
|
+
const candidate = optimizationCandidateFrom(args.vault, memoryAddr);
|
|
216
|
+
if (candidate) candidates.push(candidate);
|
|
217
|
+
}
|
|
218
|
+
const plan = createMemoryOptimizationPlan({
|
|
219
|
+
candidates,
|
|
220
|
+
prompt: args.query ?? '',
|
|
221
|
+
pricing: contextPackPricing(args),
|
|
222
|
+
now: args.now,
|
|
223
|
+
default_importance: args.default_importance ?? args.defaultImportance,
|
|
224
|
+
});
|
|
225
|
+
const maxTokensValue = args.max_estimated_tokens ?? args.maxEstimatedTokens;
|
|
226
|
+
const maxTokens = maxTokensValue === undefined ? undefined : Number(maxTokensValue);
|
|
227
|
+
if (maxTokensValue !== undefined && (!Number.isFinite(maxTokens) || maxTokens < 0)) {
|
|
228
|
+
throw new Error('max_estimated_tokens must be a non-negative number');
|
|
229
|
+
}
|
|
230
|
+
const selected = [];
|
|
231
|
+
let tokenBudgetUsed = estimateTextTokens(args.query ?? '');
|
|
232
|
+
for (const item of plan.items) {
|
|
233
|
+
if (selected.length >= limit) break;
|
|
234
|
+
if (Number.isFinite(maxTokens) && tokenBudgetUsed + item.optimized_prompt_tokens > maxTokens) continue;
|
|
235
|
+
selected.push(item.address);
|
|
236
|
+
tokenBudgetUsed += item.optimized_prompt_tokens;
|
|
237
|
+
}
|
|
238
|
+
const selectedSet = new Set(selected);
|
|
239
|
+
const selectedPlan = createMemoryOptimizationPlan({
|
|
240
|
+
candidates: candidates.filter((candidate) => selectedSet.has(candidate.address)),
|
|
241
|
+
prompt: args.query ?? '',
|
|
242
|
+
pricing: contextPackPricing(args),
|
|
243
|
+
now: args.now,
|
|
244
|
+
default_importance: args.default_importance ?? args.defaultImportance,
|
|
245
|
+
});
|
|
246
|
+
return { selected, plan: selectedPlan };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function publicContextMemory(memory) {
|
|
250
|
+
return {
|
|
251
|
+
memory_addr: memory?.memory_addr,
|
|
252
|
+
memory_id: memory?.memory_id,
|
|
253
|
+
subject_id: memory?.subject_id,
|
|
254
|
+
kind: memory?.kind,
|
|
255
|
+
sensitivity: memory?.sensitivity,
|
|
256
|
+
purpose_tags: Array.isArray(memory?.purpose_tags) ? [...memory.purpose_tags] : [],
|
|
257
|
+
source_refs: sanitizeSourceRefs(memory?.source_refs),
|
|
258
|
+
confidence: memory?.confidence,
|
|
259
|
+
content_redacted: true,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function publicOptimizationItem(item) {
|
|
264
|
+
if (!item || typeof item !== 'object') return item;
|
|
265
|
+
const out = { ...item };
|
|
266
|
+
if (out.content_hash !== undefined) {
|
|
267
|
+
delete out.content_hash;
|
|
268
|
+
out.content_hash_redacted = true;
|
|
269
|
+
}
|
|
270
|
+
return out;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function publicOptimizationPlan(plan) {
|
|
274
|
+
if (!plan || typeof plan !== 'object') return null;
|
|
275
|
+
const tiers = {};
|
|
276
|
+
for (const [tier, items] of Object.entries(plan.tiers ?? {})) {
|
|
277
|
+
tiers[tier] = Array.isArray(items) ? items.map(publicOptimizationItem) : [];
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
...plan,
|
|
281
|
+
tiers,
|
|
282
|
+
items: Array.isArray(plan.items) ? plan.items.map(publicOptimizationItem) : [],
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function publicOptimizationReceipt(receipt) {
|
|
287
|
+
if (!receipt || typeof receipt !== 'object') return receipt;
|
|
288
|
+
const out = { ...receipt };
|
|
289
|
+
if (out.content_hash !== undefined) {
|
|
290
|
+
delete out.content_hash;
|
|
291
|
+
out.content_hash_redacted = true;
|
|
292
|
+
}
|
|
293
|
+
return out;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function publicOptimizationReceipts(receipts) {
|
|
297
|
+
return Array.isArray(receipts) ? receipts.map(publicOptimizationReceipt) : [];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function publicContextPack(contextPack) {
|
|
301
|
+
return {
|
|
302
|
+
schema: contextPack.schema,
|
|
303
|
+
context_pack_id: contextPack.context_pack_id,
|
|
304
|
+
passport_id: contextPack.passport_id,
|
|
305
|
+
generated_at: contextPack.generated_at,
|
|
306
|
+
provider: contextPack.provider,
|
|
307
|
+
model: contextPack.model,
|
|
308
|
+
purpose: contextPack.purpose,
|
|
309
|
+
query_redacted: contextPack.query !== undefined,
|
|
310
|
+
memory_addresses: [...(contextPack.memory_addresses ?? [])],
|
|
311
|
+
memories: Array.isArray(contextPack.memories) ? contextPack.memories.map(publicContextMemory) : [],
|
|
312
|
+
receipts: Array.isArray(contextPack.receipts) ? contextPack.receipts.map(publicReceipt) : [],
|
|
313
|
+
retrieval_receipts: Array.isArray(contextPack.retrieval_receipts) ? contextPack.retrieval_receipts.map(publicReceipt) : [],
|
|
314
|
+
injection_receipts: Array.isArray(contextPack.injection_receipts) ? contextPack.injection_receipts.map(publicReceipt) : [],
|
|
315
|
+
active_set_root: contextPack.active_set_root,
|
|
316
|
+
receipt_log_root: contextPack.receipt_log_root,
|
|
317
|
+
receipt_hashes: [...(contextPack.receipt_hashes ?? [])],
|
|
318
|
+
optimization_plan: publicOptimizationPlan(contextPack.optimization_plan),
|
|
319
|
+
optimization_receipts: publicOptimizationReceipts(contextPack.optimization_receipts),
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function publicReceipt(receipt) {
|
|
324
|
+
return {
|
|
325
|
+
schema: receipt?.schema,
|
|
326
|
+
receipt_id: receipt?.receipt_id,
|
|
327
|
+
event_hash: receipt?.event_hash,
|
|
328
|
+
operation: receipt?.operation,
|
|
329
|
+
tenant_id: receipt?.tenant_id,
|
|
330
|
+
subject_id: receipt?.subject_id,
|
|
331
|
+
memory_addr: receipt?.memory_addr,
|
|
332
|
+
source_addr: receipt?.source_addr,
|
|
333
|
+
provider: receipt?.provider,
|
|
334
|
+
model: receipt?.model,
|
|
335
|
+
policy_id: receipt?.policy_id,
|
|
336
|
+
sequence: receipt?.sequence,
|
|
337
|
+
previous_receipt_hash: receipt?.previous_receipt_hash,
|
|
338
|
+
active_set_root: receipt?.active_set_root,
|
|
339
|
+
receipt_log_root: receipt?.receipt_log_root,
|
|
340
|
+
timestamp: receipt?.timestamp,
|
|
341
|
+
signer: receipt?.signer ? { key_id: receipt.signer.key_id, alg: receipt.signer.alg } : receipt?.signer,
|
|
342
|
+
signature: receipt?.signature ? { alg: receipt.signature.alg, value: receipt.signature.value } : receipt?.signature,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function receiptHasPublicShape(receipt) {
|
|
347
|
+
if (!receipt || receipt.schema !== 'enigma.receipt.v1') return false;
|
|
348
|
+
for (const key of Object.keys(receipt)) {
|
|
349
|
+
if (!RECEIPT_TOP_LEVEL_FIELDS.has(key) || PUBLIC_PLAINTEXT_KEYS.has(key)) return false;
|
|
350
|
+
}
|
|
351
|
+
if (!receipt.signer || typeof receipt.signer !== 'object' || Array.isArray(receipt.signer)) return false;
|
|
352
|
+
if (receipt.signer.alg !== 'Ed25519' || typeof receipt.signer.key_id !== 'string' || receipt.signer.key_id.length === 0) return false;
|
|
353
|
+
if (!receipt.signature || typeof receipt.signature !== 'object' || Array.isArray(receipt.signature)) return false;
|
|
354
|
+
if (receipt.signature.alg !== 'Ed25519' || typeof receipt.signature.value !== 'string' || receipt.signature.value.length === 0) return false;
|
|
355
|
+
for (const key of Object.keys(receipt.signature)) {
|
|
356
|
+
if (!RECEIPT_SIGNATURE_FIELDS.has(key)) return false;
|
|
357
|
+
}
|
|
358
|
+
return (
|
|
359
|
+
typeof receipt.receipt_id === 'string'
|
|
360
|
+
&& typeof receipt.operation === 'string'
|
|
361
|
+
&& typeof receipt.tenant_id === 'string'
|
|
362
|
+
&& typeof receipt.subject_id === 'string'
|
|
363
|
+
&& Number.isInteger(receipt.sequence)
|
|
364
|
+
&& receipt.sequence >= 0
|
|
365
|
+
&& ROOT_RE.test(receipt.event_hash ?? '')
|
|
366
|
+
&& ROOT_RE.test(receipt.active_set_root ?? '')
|
|
367
|
+
&& ROOT_RE.test(receipt.receipt_log_root ?? '')
|
|
368
|
+
&& PREVIOUS_RECEIPT_RE.test(receipt.previous_receipt_hash ?? '')
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
function rejectInvalid(errors) {
|
|
374
|
+
if (errors.length === 0) return;
|
|
375
|
+
const error = new Error(`context pack verification failed: ${errors.join('; ')}`);
|
|
376
|
+
error.code = 'ERR_CONTEXT_PACK_INVALID';
|
|
377
|
+
error.errors = errors;
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function trustedKeyOptions(args = {}) {
|
|
382
|
+
const bundle = args.trustedKeyBundle ?? args.trusted_key_bundle ?? args.trustedBundle ?? args.trusted_bundle ?? args.trustBundle ?? args.trust_bundle ?? args.bundle;
|
|
383
|
+
const descriptor = args.trustDescriptor ?? args.trustedDescriptor ?? args.issuerDescriptor ?? args.descriptor ?? bundle?.trustDescriptor ?? bundle?.descriptor;
|
|
384
|
+
const publicKey = args.publicKey
|
|
385
|
+
?? args.public_key
|
|
386
|
+
?? args.trustedPublicKey
|
|
387
|
+
?? args.trusted_public_key
|
|
388
|
+
?? descriptor?.public_key
|
|
389
|
+
?? descriptor?.publicKey
|
|
390
|
+
?? descriptor?.key?.public_key
|
|
391
|
+
?? descriptor?.key?.publicKey
|
|
392
|
+
?? bundle?.publicKey
|
|
393
|
+
?? bundle?.public_key
|
|
394
|
+
?? bundle?.key?.public_key
|
|
395
|
+
?? bundle?.key?.publicKey
|
|
396
|
+
?? bundle?.signer?.publicKey
|
|
397
|
+
?? bundle?.signer?.public_key
|
|
398
|
+
?? bundle?.keyring?.publicKey
|
|
399
|
+
?? bundle?.keyring?.public_key
|
|
400
|
+
?? bundle?.keypair?.publicKey
|
|
401
|
+
?? bundle?.keys?.publicKey;
|
|
402
|
+
if (publicKey !== undefined) return { publicKey };
|
|
403
|
+
const publicKeys = args.publicKeys
|
|
404
|
+
?? args.public_keys
|
|
405
|
+
?? args.keyring
|
|
406
|
+
?? args.keys
|
|
407
|
+
?? bundle?.publicKeys
|
|
408
|
+
?? bundle?.public_keys
|
|
409
|
+
?? bundle?.keyring
|
|
410
|
+
?? bundle?.keys;
|
|
411
|
+
if (publicKeys !== undefined) return { publicKeys };
|
|
412
|
+
|
|
413
|
+
const trustedIssuers = bundle?.trust_bundle?.trusted_issuers ?? bundle?.trust?.trusted_issuers ?? bundle?.trusted_issuers;
|
|
414
|
+
if (!Array.isArray(trustedIssuers)) return undefined;
|
|
415
|
+
const issuerKeys = {};
|
|
416
|
+
for (const issuer of trustedIssuers) {
|
|
417
|
+
const keyId = issuer?.key_id ?? issuer?.keyId ?? issuer?.key?.key_id ?? issuer?.key?.keyId;
|
|
418
|
+
const issuerPublicKey = issuer?.public_key ?? issuer?.publicKey ?? issuer?.key?.public_key ?? issuer?.key?.publicKey;
|
|
419
|
+
if (typeof keyId === 'string' && issuerPublicKey !== undefined) issuerKeys[keyId] = issuerPublicKey;
|
|
420
|
+
}
|
|
421
|
+
return Object.keys(issuerKeys).length > 0 ? { publicKeys: issuerKeys } : undefined;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function verifyReceiptBestEffort(receipt, trustOptions) {
|
|
425
|
+
if (!trustOptions) return false;
|
|
426
|
+
try {
|
|
427
|
+
const result = verifyReceipt({ receipt, ...trustOptions });
|
|
428
|
+
return result !== false && result?.ok !== false && result?.valid !== false;
|
|
429
|
+
} catch {
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function invalidContextPackResult(contextPack, errors) {
|
|
435
|
+
const publicPack = publicContextPack(contextPack);
|
|
436
|
+
return {
|
|
437
|
+
valid: false,
|
|
438
|
+
error: errors[0],
|
|
439
|
+
reason: errors[0],
|
|
440
|
+
errors,
|
|
441
|
+
context_pack_id: contextPack.context_pack_id,
|
|
442
|
+
memory_addresses: [...(contextPack.memory_addresses ?? [])],
|
|
443
|
+
public_context_pack: publicPack,
|
|
444
|
+
canonical: canonical(publicPack),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function receiptDigest(receipt) {
|
|
449
|
+
try {
|
|
450
|
+
const digest = receiptHash(receipt);
|
|
451
|
+
return String(digest).startsWith('sha256:') ? String(digest) : `sha256:${digest}`;
|
|
452
|
+
} catch {
|
|
453
|
+
return undefined;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function createPassport(args = {}) {
|
|
458
|
+
const vault = args.vault;
|
|
459
|
+
const createdAt = nowIso(args.now);
|
|
460
|
+
const roots = rootsFromVault(vault);
|
|
461
|
+
const activeAddresses = activeAddressesFrom(vault);
|
|
462
|
+
const tombstoneAddresses = tombstoneAddressesFrom(vault);
|
|
463
|
+
return {
|
|
464
|
+
schema: PASSPORT_SCHEMA,
|
|
465
|
+
passport_id: args.passport_id ?? args.passportId ?? `passport_${randomUUID()}`,
|
|
466
|
+
owner: {
|
|
467
|
+
subject_id: args.owner?.subject_id ?? args.subject_id ?? args.subjectId ?? vault?.subject_id ?? 'local-subject',
|
|
468
|
+
display_name: args.owner?.display_name ?? args.display_name ?? args.displayName ?? 'Local user',
|
|
469
|
+
identity_refs: args.owner?.identity_refs ?? args.identity_refs ?? args.identityRefs ?? [],
|
|
470
|
+
},
|
|
471
|
+
created_at: createdAt,
|
|
472
|
+
updated_at: createdAt,
|
|
473
|
+
vault: {
|
|
474
|
+
vault_id: vault?.vault_id ?? args.vault_id ?? args.vaultId ?? 'local-vault',
|
|
475
|
+
encryption: vault?.encryption ?? 'local_aead',
|
|
476
|
+
active_set_root: roots.active_set_root,
|
|
477
|
+
receipt_log_root: roots.receipt_log_root,
|
|
478
|
+
},
|
|
479
|
+
policies: args.policies ?? [vault?.policy_id ?? 'local-default'],
|
|
480
|
+
checkpoints: [
|
|
481
|
+
{
|
|
482
|
+
sequence: vault?.sequence ?? 0,
|
|
483
|
+
active_set_root: roots.active_set_root,
|
|
484
|
+
receipt_log_root: roots.receipt_log_root,
|
|
485
|
+
timestamp: createdAt,
|
|
486
|
+
},
|
|
487
|
+
],
|
|
488
|
+
active_memory_addresses: [...activeAddresses].sort(),
|
|
489
|
+
tombstone_addresses: [...tombstoneAddresses].sort(),
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export function compileContextPack(args = {}) {
|
|
494
|
+
const vault = args.vault;
|
|
495
|
+
if (!vault) throw new Error('compileContextPack requires a vault');
|
|
496
|
+
if (!vault.__getRecord || !vault.__getPlaintext || !vault.__recordEvent) {
|
|
497
|
+
throw new Error('compileContextPack requires a live vault created by packages/vault');
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const passport = args.passport ?? createPassport({ vault, now: args.now });
|
|
501
|
+
const requested = args.memory_addresses ?? args.memoryAddresses;
|
|
502
|
+
const active = activeAddressesFrom(vault);
|
|
503
|
+
const tombstones = tombstoneAddressesFrom(vault);
|
|
504
|
+
const limit = Number(args.limit ?? args.max_memories ?? args.maxMemories ?? 12);
|
|
505
|
+
if (!Number.isInteger(limit) || limit < 0) throw new Error('compileContextPack limit must be a non-negative integer');
|
|
506
|
+
const candidateAddresses = requested ? [...requested] : [...active];
|
|
507
|
+
let selected = candidateAddresses.slice(0, limit);
|
|
508
|
+
let optimizationPlan = null;
|
|
509
|
+
if (optimizerEnabled(args)) {
|
|
510
|
+
const optimized = optimizedSelectionFrom({ ...args, vault }, candidateAddresses, limit);
|
|
511
|
+
selected = optimized.selected;
|
|
512
|
+
optimizationPlan = optimized.plan;
|
|
513
|
+
}
|
|
514
|
+
const errors = [];
|
|
515
|
+
|
|
516
|
+
for (const memoryAddr of selected) {
|
|
517
|
+
if (tombstones.has(memoryAddr)) errors.push(`memory is tombstoned: ${memoryAddr}`);
|
|
518
|
+
if (!active.has(memoryAddr)) errors.push(`memory is absent from active state: ${memoryAddr}`);
|
|
519
|
+
const record = vault.__getRecord(memoryAddr);
|
|
520
|
+
if (!record || record.state !== 'active') errors.push(`memory record is not active: ${memoryAddr}`);
|
|
521
|
+
}
|
|
522
|
+
rejectInvalid(errors);
|
|
523
|
+
|
|
524
|
+
const contextPackId = args.context_pack_id ?? args.contextPackId ?? `ctx_${randomUUID()}`;
|
|
525
|
+
const generatedAt = nowIso(args.now);
|
|
526
|
+
const memories = [];
|
|
527
|
+
const retrievalReceipts = [];
|
|
528
|
+
const injectionReceipts = [];
|
|
529
|
+
|
|
530
|
+
for (const memoryAddr of selected) {
|
|
531
|
+
const record = vault.__getRecord(memoryAddr);
|
|
532
|
+
const content = vault.__getPlaintext(memoryAddr);
|
|
533
|
+
memories.push(publicMemory(record, content));
|
|
534
|
+
|
|
535
|
+
retrievalReceipts.push(
|
|
536
|
+
vault.__recordEvent({
|
|
537
|
+
operation: 'retrieve',
|
|
538
|
+
memory_addr: memoryAddr,
|
|
539
|
+
provider: args.provider,
|
|
540
|
+
model: args.model,
|
|
541
|
+
purpose: args.purpose,
|
|
542
|
+
actor_id: args.actor_id ?? args.actorId,
|
|
543
|
+
policy_id: args.policy_id ?? args.policyId,
|
|
544
|
+
now: args.now,
|
|
545
|
+
metadata: { context_pack_id: contextPackId, kind: record.kind, sensitivity: record.sensitivity },
|
|
546
|
+
}).receipt,
|
|
547
|
+
);
|
|
548
|
+
injectionReceipts.push(
|
|
549
|
+
vault.__recordEvent({
|
|
550
|
+
operation: 'inject',
|
|
551
|
+
memory_addr: memoryAddr,
|
|
552
|
+
provider: args.provider,
|
|
553
|
+
model: args.model,
|
|
554
|
+
purpose: args.purpose,
|
|
555
|
+
actor_id: args.actor_id ?? args.actorId,
|
|
556
|
+
policy_id: args.policy_id ?? args.policyId,
|
|
557
|
+
now: args.now,
|
|
558
|
+
metadata: { context_pack_id: contextPackId, kind: record.kind, sensitivity: record.sensitivity },
|
|
559
|
+
}).receipt,
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const optimizationReceipts = optimizationPlan === null
|
|
564
|
+
? []
|
|
565
|
+
: optimizationPlan.items.map((item, index) => createMemoryAccessReceipt({
|
|
566
|
+
item,
|
|
567
|
+
plan: optimizationPlan,
|
|
568
|
+
timestamp: generatedAt,
|
|
569
|
+
sequence: index,
|
|
570
|
+
pricing: optimizationPlan.pricing,
|
|
571
|
+
}));
|
|
572
|
+
|
|
573
|
+
const roots = rootsFromVault(vault);
|
|
574
|
+
const contextPack = {
|
|
575
|
+
schema: CONTEXT_PACK_SCHEMA,
|
|
576
|
+
context_pack_id: contextPackId,
|
|
577
|
+
passport_id: passport.passport_id,
|
|
578
|
+
generated_at: generatedAt,
|
|
579
|
+
provider: args.provider ?? 'local',
|
|
580
|
+
model: args.model ?? 'local',
|
|
581
|
+
purpose: args.purpose ?? 'context_injection',
|
|
582
|
+
query: args.query ?? '',
|
|
583
|
+
memory_addresses: selected,
|
|
584
|
+
memories,
|
|
585
|
+
receipts: [...retrievalReceipts, ...injectionReceipts],
|
|
586
|
+
retrieval_receipts: retrievalReceipts,
|
|
587
|
+
injection_receipts: injectionReceipts,
|
|
588
|
+
active_set_root: roots.active_set_root,
|
|
589
|
+
receipt_log_root: roots.receipt_log_root,
|
|
590
|
+
receipt_hashes: [...retrievalReceipts, ...injectionReceipts].map(receiptDigest).filter(Boolean),
|
|
591
|
+
optimization_plan: optimizationPlan,
|
|
592
|
+
optimization_receipts: optimizationReceipts,
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
Object.defineProperties(contextPack, {
|
|
596
|
+
contextPack: { value: contextPack, enumerable: false },
|
|
597
|
+
context_pack: { value: contextPack, enumerable: false },
|
|
598
|
+
});
|
|
599
|
+
return contextPack;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
export function verifyContextPack(args = {}) {
|
|
603
|
+
const contextPack = args.schema === CONTEXT_PACK_SCHEMA ? args : (args.contextPack ?? args.context_pack ?? args.pack);
|
|
604
|
+
if (!contextPack || contextPack.schema !== CONTEXT_PACK_SCHEMA) throw new Error('verifyContextPack requires an enigma.context_pack.v1 pack');
|
|
605
|
+
const passport = args.passport;
|
|
606
|
+
const active = new Set([
|
|
607
|
+
...activeAddressesFrom(args.active_state ?? args.activeState),
|
|
608
|
+
...activeAddressesFrom(args.vault),
|
|
609
|
+
...activeAddressesFrom(passport),
|
|
610
|
+
]);
|
|
611
|
+
const tombstones = new Set([
|
|
612
|
+
...tombstoneAddressesFrom(args.tombstones),
|
|
613
|
+
...tombstoneAddressesFrom(args.vault),
|
|
614
|
+
...tombstoneAddressesFrom(passport),
|
|
615
|
+
...(passport?.tombstone_addresses ?? []),
|
|
616
|
+
]);
|
|
617
|
+
const trustOptions = trustedKeyOptions(args);
|
|
618
|
+
|
|
619
|
+
const errors = [];
|
|
620
|
+
if (!trustOptions) errors.push(PUBLIC_KEY_REQUIRED_FOR_CONTEXT_PACK_VERIFICATION);
|
|
621
|
+
for (const memoryAddr of memoryAddressesFromPack(contextPack)) {
|
|
622
|
+
if (tombstones.has(memoryAddr)) errors.push(`memory is tombstoned: ${memoryAddr}`);
|
|
623
|
+
if (!active.has(memoryAddr)) errors.push(`memory is absent from active state: ${memoryAddr}`);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const receiptOperations = new Map();
|
|
627
|
+
for (const receipt of contextPack.receipts ?? []) {
|
|
628
|
+
if (!receiptHasPublicShape(receipt) || (trustOptions && !verifyReceiptBestEffort(receipt, trustOptions))) errors.push(`receipt failed verification: ${receipt.receipt_id ?? 'unknown'}`);
|
|
629
|
+
if (receipt.memory_addr) {
|
|
630
|
+
const ops = receiptOperations.get(receipt.memory_addr) ?? new Set();
|
|
631
|
+
ops.add(receipt.operation);
|
|
632
|
+
receiptOperations.set(receipt.memory_addr, ops);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
for (const memoryAddr of contextPack.memory_addresses ?? []) {
|
|
636
|
+
const ops = receiptOperations.get(memoryAddr) ?? new Set();
|
|
637
|
+
if (!ops.has('retrieve')) errors.push(`missing retrieve receipt: ${memoryAddr}`);
|
|
638
|
+
if (!ops.has('inject')) errors.push(`missing inject receipt: ${memoryAddr}`);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (errors.includes(PUBLIC_KEY_REQUIRED_FOR_CONTEXT_PACK_VERIFICATION)) return invalidContextPackResult(contextPack, errors);
|
|
642
|
+
rejectInvalid(errors);
|
|
643
|
+
const publicPack = publicContextPack(contextPack);
|
|
644
|
+
return {
|
|
645
|
+
valid: true,
|
|
646
|
+
context_pack_id: contextPack.context_pack_id,
|
|
647
|
+
memory_addresses: [...(contextPack.memory_addresses ?? [])],
|
|
648
|
+
public_context_pack: publicPack,
|
|
649
|
+
canonical: canonical(publicPack),
|
|
650
|
+
};
|
|
651
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# `@enigma-ai/enigma/settlement`
|
|
2
|
+
|
|
3
|
+
Permissionless access and service-settlement protocol for Enigma memory jobs.
|
|
4
|
+
|
|
5
|
+
## Contract
|
|
6
|
+
|
|
7
|
+
- Produces content-minimized job, consumer-GPU capacity, quote, settlement receipt, and batch artifacts:
|
|
8
|
+
- `enigma.permissionless_memory_job.v1`
|
|
9
|
+
- `enigma.consumer_gpu_capacity_profile.v1`
|
|
10
|
+
- `enigma.operator_service_quote.v1`
|
|
11
|
+
- `enigma.service_settlement_receipt.v1`
|
|
12
|
+
- `enigma.settlement_batch.v1`
|
|
13
|
+
- Accepts opaque memory commitment roots, policy hashes, usage-event hashes, consumer/workstation GPU capacity refs, service refs, prices, and settlement refs.
|
|
14
|
+
- Keeps raw memory, prompts, completions, transcripts, provider responses, credentials, private keys, and seed phrases out of artifacts.
|
|
15
|
+
- Uses permissionless rails only for access submission, consumer/workstation GPU capacity discovery, service accountability, and settlement. It does not decentralize raw-memory inference or claim token ROI/profit/equity/provider-wide discounts.
|
|
16
|
+
|
|
17
|
+
## Public API
|
|
18
|
+
|
|
19
|
+
- `createPermissionlessMemoryJob(options)`
|
|
20
|
+
- `createConsumerGpuCapacityProfile(options)`
|
|
21
|
+
- `createOperatorServiceQuote(options)`
|
|
22
|
+
- `createServiceSettlementReceipt(options)`
|
|
23
|
+
- `verifyServiceSettlementReceipt(options)`
|
|
24
|
+
- `createSettlementBatch(options)`
|
|
25
|
+
|
|
26
|
+
## Evidence boundary
|
|
27
|
+
|
|
28
|
+
Settlement receipts prove Enigma-side job/quote/settlement linkage under supplied hashes and refs. Consumer GPU capacity profiles prove only declared capacity/pricing metadata boundaries, not realized provider discount or decentralization. These artifacts are not investment, profit, yield, equity, provider invoice, provider deletion, model forgetting, or compliance-certification evidence.
|