enigma-memory 0.1.0 → 0.1.2

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.
@@ -0,0 +1,538 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ export const HOSTED_CLOUD_USER_ACCOUNT_SCHEMA = 'enigma.hosted_cloud.user_account.v1';
4
+ export const HOSTED_CLOUD_TENANT_SCHEMA = 'enigma.hosted_cloud.tenant.v1';
5
+ export const HOSTED_CLOUD_VAULT_SCHEMA = 'enigma.hosted_cloud.vault.v1';
6
+ export const HOSTED_CLOUD_API_KEY_SCHEMA = 'enigma.hosted_cloud.api_key.v1';
7
+ export const HOSTED_CLOUD_USAGE_BILLING_SCHEMA = 'enigma.hosted_cloud.usage_billing_record.v1';
8
+ export const HOSTED_CLOUD_DASHBOARD_SCHEMA = 'enigma.hosted_cloud.dashboard_summary.v1';
9
+ export const HOSTED_CLOUD_BACKUP_DRILL_SCHEMA = 'enigma.hosted_cloud.backup_drill.v1';
10
+ export const HOSTED_CLOUD_INCIDENT_SLA_SCHEMA = 'enigma.hosted_cloud.incident_sla_refs.v1';
11
+
12
+ export const HOSTED_CLOUD_EXTERNAL_BLOCKERS = Object.freeze([
13
+ 'auth_provider',
14
+ 'billing_provider',
15
+ 'legal_docs',
16
+ 'data_processing_terms',
17
+ 'support_ownership',
18
+ 'external_security_review',
19
+ ]);
20
+
21
+ const SHA256_PREFIX = 'sha256:';
22
+ const PROVIDED = 'provided';
23
+ const BLOCKED = 'blocked_external_dependency';
24
+ const EVIDENCE_STATUSES = new Set([PROVIDED, BLOCKED]);
25
+ const HOSTED_CLOUD_CONTRACT_READY = Object.freeze({
26
+ contract_ready: true,
27
+ integration_kind: 'contract_validator_only',
28
+ no_external_provider_calls: true,
29
+ });
30
+ const BLOCKER_LABELS = Object.freeze({
31
+ auth_provider: 'Auth provider is not wired.',
32
+ billing_provider: 'Billing provider is not wired.',
33
+ legal_docs: 'Hosted legal documents are not approved.',
34
+ data_processing_terms: 'Data processing terms are not approved.',
35
+ support_ownership: 'Support ownership is not assigned.',
36
+ external_security_review: 'External security review is not complete.',
37
+ });
38
+ 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;
39
+ 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}|raw memory|private prompt|provider response|full transcript|decrypted memory)/iu;
40
+ 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;
41
+
42
+ function isPlainObject(value) {
43
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
44
+ }
45
+
46
+ function requiredString(value, name) {
47
+ if (typeof value !== 'string' || value.trim() === '') throw new TypeError(`${name} must be a non-empty string`);
48
+ return value;
49
+ }
50
+
51
+ function stringOrDefault(value, fallback) {
52
+ return typeof value === 'string' && value.trim() !== '' ? value : fallback;
53
+ }
54
+
55
+ function optionalString(value, name) {
56
+ if (value === undefined || value === null) return undefined;
57
+ return requiredString(value, name);
58
+ }
59
+
60
+ function requiredBoolean(value, name) {
61
+ if (typeof value !== 'boolean') throw new TypeError(`${name} must be a boolean`);
62
+ return value;
63
+ }
64
+
65
+ function requiredTrue(value, name) {
66
+ if (requiredBoolean(value, name) !== true) throw new TypeError(`${name} must be true`);
67
+ return true;
68
+ }
69
+
70
+ function requiredFalse(value, name) {
71
+ if (requiredBoolean(value, name) !== false) throw new TypeError(`${name} must be false`);
72
+ return false;
73
+ }
74
+
75
+ function nonNegativeInteger(value, name) {
76
+ if (!Number.isInteger(value) || value < 0) throw new TypeError(`${name} must be a non-negative integer`);
77
+ return value;
78
+ }
79
+
80
+ function nonNegativeNumber(value, name) {
81
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) throw new TypeError(`${name} must be a non-negative number`);
82
+ return value;
83
+ }
84
+
85
+ function isoTimestamp(value, name = 'timestamp') {
86
+ const timestamp = requiredString(value, name);
87
+ if (Number.isNaN(Date.parse(timestamp))) throw new TypeError(`${name} must be an ISO timestamp`);
88
+ return timestamp;
89
+ }
90
+
91
+ function stringArray(value, name) {
92
+ if (!Array.isArray(value)) throw new TypeError(`${name} must be an array`);
93
+ return value.map((item, index) => requiredString(item, `${name}[${index}]`));
94
+ }
95
+
96
+ function canonicalize(value) {
97
+ if (Array.isArray(value)) return value.map(canonicalize);
98
+ if (isPlainObject(value)) {
99
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]));
100
+ }
101
+ return value;
102
+ }
103
+
104
+ function hashValue(value) {
105
+ return `${SHA256_PREFIX}${createHash('sha256').update(JSON.stringify(canonicalize(value))).digest('hex')}`;
106
+ }
107
+
108
+ function contractId(prefix, body) {
109
+ return `${prefix}_${hashValue(body).slice(SHA256_PREFIX.length, SHA256_PREFIX.length + 24)}`;
110
+ }
111
+
112
+ function deepFreeze(value) {
113
+ if (!isPlainObject(value) && !Array.isArray(value)) return value;
114
+ Object.freeze(value);
115
+ for (const child of Object.values(value)) deepFreeze(child);
116
+ return value;
117
+ }
118
+
119
+ function assertNoForbiddenPayload(value, path = 'hosted_cloud') {
120
+ if (typeof value === 'string') {
121
+ if (SECRET_VALUE_RE.test(value)) throw new TypeError(`${path} contains raw, provider, or credential-looking data`);
122
+ if (FORBIDDEN_CLAIM_RE.test(value)) throw new TypeError(`${path} contains a forbidden hosted-cloud claim`);
123
+ return;
124
+ }
125
+ if (Array.isArray(value)) {
126
+ value.forEach((item, index) => assertNoForbiddenPayload(item, `${path}[${index}]`));
127
+ return;
128
+ }
129
+ if (!isPlainObject(value)) return;
130
+ for (const [key, child] of Object.entries(value)) {
131
+ if (FORBIDDEN_KEY_RE.test(key)) throw new TypeError(`${path}.${key} is not allowed in hosted-cloud contracts`);
132
+ assertNoForbiddenPayload(child, `${path}.${key}`);
133
+ }
134
+ }
135
+
136
+ function evidenceRefFor(key, value) {
137
+ const fallback = { ref: `blocked:${key}`, status: BLOCKED, blocker: BLOCKER_LABELS[key] };
138
+ if (value === undefined || value === null) return fallback;
139
+ if (typeof value === 'string') return { ref: requiredString(value, `operator_evidence_refs.${key}`), status: PROVIDED };
140
+ if (!isPlainObject(value)) throw new TypeError(`operator_evidence_refs.${key} must be a string or object`);
141
+ const status = stringOrDefault(value.status, PROVIDED);
142
+ if (!EVIDENCE_STATUSES.has(status)) throw new TypeError(`operator_evidence_refs.${key}.status is invalid`);
143
+ const ref = requiredString(value.ref, `operator_evidence_refs.${key}.ref`);
144
+ const refRecord = { ref, status };
145
+ const owner = optionalString(value.owner, `operator_evidence_refs.${key}.owner`);
146
+ const blocker = optionalString(value.blocker, `operator_evidence_refs.${key}.blocker`);
147
+ if (owner) refRecord.owner = owner;
148
+ if (status === BLOCKED) refRecord.blocker = blocker ?? BLOCKER_LABELS[key];
149
+ return refRecord;
150
+ }
151
+
152
+ function normalizeOperatorEvidenceRefs(input = {}) {
153
+ const refs = isPlainObject(input) ? input : {};
154
+ return Object.fromEntries(HOSTED_CLOUD_EXTERNAL_BLOCKERS.map((key) => [key, evidenceRefFor(key, refs[key])]));
155
+ }
156
+
157
+ function validateOperatorEvidenceRefs(contract) {
158
+ if (!isPlainObject(contract.operator_evidence_refs)) throw new TypeError('operator_evidence_refs must be present');
159
+ for (const key of HOSTED_CLOUD_EXTERNAL_BLOCKERS) {
160
+ const ref = contract.operator_evidence_refs[key];
161
+ if (!isPlainObject(ref)) throw new TypeError(`operator_evidence_refs.${key} must be present`);
162
+ requiredString(ref.ref, `operator_evidence_refs.${key}.ref`);
163
+ if (!EVIDENCE_STATUSES.has(ref.status)) throw new TypeError(`operator_evidence_refs.${key}.status is invalid`);
164
+ if (ref.status === BLOCKED) requiredString(ref.blocker, `operator_evidence_refs.${key}.blocker`);
165
+ }
166
+ }
167
+
168
+ function externalBlockers(operatorEvidenceRefs) {
169
+ return HOSTED_CLOUD_EXTERNAL_BLOCKERS
170
+ .filter((key) => operatorEvidenceRefs[key].status !== PROVIDED)
171
+ .map((key) => ({ key, ref: operatorEvidenceRefs[key].ref, blocker: operatorEvidenceRefs[key].blocker }));
172
+ }
173
+
174
+ function readinessFrom(operatorEvidenceRefs) {
175
+ const blockers = externalBlockers(operatorEvidenceRefs);
176
+ return {
177
+ ...HOSTED_CLOUD_CONTRACT_READY,
178
+ external_wiring_ready: blockers.length === 0,
179
+ hosted_cloud_sellable: false,
180
+ selling_gate: blockers.length === 0 ? 'requires_operator_go_live_approval' : 'blocked_until_external_wiring_and_approvals',
181
+ external_blockers: blockers,
182
+ };
183
+ }
184
+
185
+ function withContractIdentity(body, prefix, idKey) {
186
+ const id = body[idKey] ?? contractId(prefix, body);
187
+ return deepFreeze({ ...body, [idKey]: id, contract_hash: hashValue({ ...body, [idKey]: id }) });
188
+ }
189
+
190
+ function validateBase(contract, schema) {
191
+ if (!isPlainObject(contract)) throw new TypeError('contract must be an object');
192
+ assertNoForbiddenPayload(contract, 'contract');
193
+ if (contract.schema !== schema) throw new TypeError(`schema must be ${schema}`);
194
+ validateOperatorEvidenceRefs(contract);
195
+ if (!isPlainObject(contract.readiness)) throw new TypeError('readiness must be present');
196
+ if (contract.readiness.contract_ready !== true) throw new TypeError('readiness.contract_ready must be true');
197
+ if (contract.readiness.no_external_provider_calls !== true) throw new TypeError('readiness.no_external_provider_calls must be true');
198
+ if (contract.readiness.hosted_cloud_sellable !== false) throw new TypeError('readiness.hosted_cloud_sellable must remain false in contract artifacts');
199
+ const expectedBlockers = externalBlockers(contract.operator_evidence_refs);
200
+ if (contract.readiness.external_wiring_ready !== (expectedBlockers.length === 0)) {
201
+ throw new TypeError('readiness.external_wiring_ready must match operator_evidence_refs');
202
+ }
203
+ if (contract.readiness.selling_gate !== (expectedBlockers.length === 0 ? 'requires_operator_go_live_approval' : 'blocked_until_external_wiring_and_approvals')) {
204
+ throw new TypeError('readiness.selling_gate must match operator_evidence_refs');
205
+ }
206
+ if (!Array.isArray(contract.readiness.external_blockers)) throw new TypeError('readiness.external_blockers must be an array');
207
+ if (contract.readiness.external_blockers.length !== expectedBlockers.length) {
208
+ throw new TypeError('readiness.external_blockers must match operator_evidence_refs');
209
+ }
210
+ expectedBlockers.forEach((blocker, index) => {
211
+ if (contract.readiness.external_blockers[index]?.key !== blocker.key || contract.readiness.external_blockers[index]?.ref !== blocker.ref) {
212
+ throw new TypeError('readiness.external_blockers must match operator_evidence_refs');
213
+ }
214
+ });
215
+ requiredString(contract.contract_hash, 'contract_hash');
216
+ return true;
217
+ }
218
+
219
+ function baseFields(input, generatedAtName = 'generated_at') {
220
+ const operatorEvidenceRefs = normalizeOperatorEvidenceRefs(input.operator_evidence_refs ?? input.operatorEvidenceRefs);
221
+ return {
222
+ operator_evidence_refs: operatorEvidenceRefs,
223
+ readiness: readinessFrom(operatorEvidenceRefs),
224
+ [generatedAtName]: isoTimestamp(input[generatedAtName] ?? input.generatedAt, generatedAtName),
225
+ };
226
+ }
227
+
228
+ export function buildUserAccountContract(input = {}) {
229
+ if (!isPlainObject(input)) throw new TypeError('buildUserAccountContract requires an options object');
230
+ assertNoForbiddenPayload(input, 'input');
231
+ const body = {
232
+ schema: HOSTED_CLOUD_USER_ACCOUNT_SCHEMA,
233
+ account_id: stringOrDefault(input.account_id ?? input.accountId, undefined),
234
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
235
+ subject_ref: requiredString(input.subject_ref ?? input.subjectRef, 'subject_ref'),
236
+ auth_provider_user_ref: requiredString(input.auth_provider_user_ref ?? input.authProviderUserRef, 'auth_provider_user_ref'),
237
+ account_state: stringOrDefault(input.account_state ?? input.accountState, 'pending_external_auth'),
238
+ roles: stringArray(input.roles ?? ['member'], 'roles'),
239
+ controls: {
240
+ stores_personal_profile: false,
241
+ stores_provider_payloads: false,
242
+ stores_auth_material: false,
243
+ },
244
+ ...baseFields(input),
245
+ };
246
+ const contract = withContractIdentity(body, 'hcuacct', 'account_id');
247
+ validateUserAccountContract(contract);
248
+ return contract;
249
+ }
250
+
251
+ export function validateUserAccountContract(contract) {
252
+ validateBase(contract, HOSTED_CLOUD_USER_ACCOUNT_SCHEMA);
253
+ requiredString(contract.account_id, 'account_id');
254
+ requiredString(contract.tenant_id, 'tenant_id');
255
+ requiredString(contract.subject_ref, 'subject_ref');
256
+ requiredString(contract.auth_provider_user_ref, 'auth_provider_user_ref');
257
+ stringArray(contract.roles, 'roles');
258
+ requiredFalse(contract.controls.stores_personal_profile, 'controls.stores_personal_profile');
259
+ requiredFalse(contract.controls.stores_provider_payloads, 'controls.stores_provider_payloads');
260
+ requiredFalse(contract.controls.stores_auth_material, 'controls.stores_auth_material');
261
+ return true;
262
+ }
263
+
264
+ export function buildTenantContract(input = {}) {
265
+ if (!isPlainObject(input)) throw new TypeError('buildTenantContract requires an options object');
266
+ assertNoForbiddenPayload(input, 'input');
267
+ const body = {
268
+ schema: HOSTED_CLOUD_TENANT_SCHEMA,
269
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
270
+ tenant_ref: requiredString(input.tenant_ref ?? input.tenantRef, 'tenant_ref'),
271
+ plan_code: stringOrDefault(input.plan_code ?? input.planCode, 'contract_only'),
272
+ lifecycle_state: stringOrDefault(input.lifecycle_state ?? input.lifecycleState, 'blocked_external_wiring'),
273
+ region: stringOrDefault(input.region, 'operator_selected'),
274
+ policy_ref: requiredString(input.policy_ref ?? input.policyRef, 'policy_ref'),
275
+ retention_policy_ref: requiredString(input.retention_policy_ref ?? input.retentionPolicyRef, 'retention_policy_ref'),
276
+ data_residency_ref: requiredString(input.data_residency_ref ?? input.dataResidencyRef, 'data_residency_ref'),
277
+ ...baseFields(input),
278
+ };
279
+ const contract = withContractIdentity(body, 'hctenant', 'tenant_id');
280
+ validateTenantContract(contract);
281
+ return contract;
282
+ }
283
+
284
+ export function validateTenantContract(contract) {
285
+ validateBase(contract, HOSTED_CLOUD_TENANT_SCHEMA);
286
+ requiredString(contract.tenant_id, 'tenant_id');
287
+ requiredString(contract.tenant_ref, 'tenant_ref');
288
+ requiredString(contract.policy_ref, 'policy_ref');
289
+ requiredString(contract.retention_policy_ref, 'retention_policy_ref');
290
+ requiredString(contract.data_residency_ref, 'data_residency_ref');
291
+ return true;
292
+ }
293
+
294
+ export function buildHostedVaultContract(input = {}) {
295
+ if (!isPlainObject(input)) throw new TypeError('buildHostedVaultContract requires an options object');
296
+ assertNoForbiddenPayload(input, 'input');
297
+ const body = {
298
+ schema: HOSTED_CLOUD_VAULT_SCHEMA,
299
+ vault_id: stringOrDefault(input.vault_id ?? input.vaultId, undefined),
300
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
301
+ vault_ref: requiredString(input.vault_ref ?? input.vaultRef, 'vault_ref'),
302
+ storage_ref: requiredString(input.storage_ref ?? input.storageRef, 'storage_ref'),
303
+ kms_key_ref: requiredString(input.kms_key_ref ?? input.kmsKeyRef, 'kms_key_ref'),
304
+ backup_policy_ref: requiredString(input.backup_policy_ref ?? input.backupPolicyRef, 'backup_policy_ref'),
305
+ retention_policy_ref: requiredString(input.retention_policy_ref ?? input.retentionPolicyRef, 'retention_policy_ref'),
306
+ custody_boundary: {
307
+ opaque_records_only: true,
308
+ content_minimized: true,
309
+ provider_payloads_allowed: false,
310
+ },
311
+ ...baseFields(input),
312
+ };
313
+ const contract = withContractIdentity(body, 'hcvault', 'vault_id');
314
+ validateHostedVaultContract(contract);
315
+ return contract;
316
+ }
317
+
318
+ export function validateHostedVaultContract(contract) {
319
+ validateBase(contract, HOSTED_CLOUD_VAULT_SCHEMA);
320
+ requiredString(contract.vault_id, 'vault_id');
321
+ requiredString(contract.tenant_id, 'tenant_id');
322
+ requiredString(contract.vault_ref, 'vault_ref');
323
+ requiredString(contract.storage_ref, 'storage_ref');
324
+ requiredString(contract.kms_key_ref, 'kms_key_ref');
325
+ requiredString(contract.backup_policy_ref, 'backup_policy_ref');
326
+ requiredString(contract.retention_policy_ref, 'retention_policy_ref');
327
+ requiredTrue(contract.custody_boundary.opaque_records_only, 'custody_boundary.opaque_records_only');
328
+ requiredTrue(contract.custody_boundary.content_minimized, 'custody_boundary.content_minimized');
329
+ requiredFalse(contract.custody_boundary.provider_payloads_allowed, 'custody_boundary.provider_payloads_allowed');
330
+ return true;
331
+ }
332
+
333
+ export function buildApiKeyContract(input = {}) {
334
+ if (!isPlainObject(input)) throw new TypeError('buildApiKeyContract requires an options object');
335
+ assertNoForbiddenPayload(input, 'input');
336
+ const body = {
337
+ schema: HOSTED_CLOUD_API_KEY_SCHEMA,
338
+ api_key_id: stringOrDefault(input.api_key_id ?? input.apiKeyId, undefined),
339
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
340
+ subject_ref: requiredString(input.subject_ref ?? input.subjectRef, 'subject_ref'),
341
+ key_fingerprint: requiredString(input.key_fingerprint ?? input.keyFingerprint, 'key_fingerprint'),
342
+ scopes: stringArray(input.scopes ?? [], 'scopes'),
343
+ issued_at: isoTimestamp(input.issued_at ?? input.issuedAt, 'issued_at'),
344
+ expires_at: optionalString(input.expires_at ?? input.expiresAt, 'expires_at'),
345
+ rotation_ref: requiredString(input.rotation_ref ?? input.rotationRef, 'rotation_ref'),
346
+ key_material_boundary: {
347
+ key_material_in_contract: false,
348
+ fingerprint_only: true,
349
+ },
350
+ ...baseFields(input),
351
+ };
352
+ if (body.expires_at) isoTimestamp(body.expires_at, 'expires_at');
353
+ const contract = withContractIdentity(body, 'hcak', 'api_key_id');
354
+ validateApiKeyContract(contract);
355
+ return contract;
356
+ }
357
+
358
+ export function validateApiKeyContract(contract) {
359
+ validateBase(contract, HOSTED_CLOUD_API_KEY_SCHEMA);
360
+ requiredString(contract.api_key_id, 'api_key_id');
361
+ requiredString(contract.tenant_id, 'tenant_id');
362
+ requiredString(contract.subject_ref, 'subject_ref');
363
+ requiredString(contract.key_fingerprint, 'key_fingerprint');
364
+ stringArray(contract.scopes, 'scopes');
365
+ isoTimestamp(contract.issued_at, 'issued_at');
366
+ if (contract.expires_at !== undefined) isoTimestamp(contract.expires_at, 'expires_at');
367
+ requiredString(contract.rotation_ref, 'rotation_ref');
368
+ requiredFalse(contract.key_material_boundary.key_material_in_contract, 'key_material_boundary.key_material_in_contract');
369
+ requiredTrue(contract.key_material_boundary.fingerprint_only, 'key_material_boundary.fingerprint_only');
370
+ return true;
371
+ }
372
+
373
+ export function buildUsageBillingRecord(input = {}) {
374
+ if (!isPlainObject(input)) throw new TypeError('buildUsageBillingRecord requires an options object');
375
+ assertNoForbiddenPayload(input, 'input');
376
+ const body = {
377
+ schema: HOSTED_CLOUD_USAGE_BILLING_SCHEMA,
378
+ billing_record_id: stringOrDefault(input.billing_record_id ?? input.billingRecordId, undefined),
379
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
380
+ period_start: isoTimestamp(input.period_start ?? input.periodStart, 'period_start'),
381
+ period_end: isoTimestamp(input.period_end ?? input.periodEnd, 'period_end'),
382
+ billing_provider_customer_ref: requiredString(input.billing_provider_customer_ref ?? input.billingProviderCustomerRef, 'billing_provider_customer_ref'),
383
+ usage_aggregate_ref: requiredString(input.usage_aggregate_ref ?? input.usageAggregateRef, 'usage_aggregate_ref'),
384
+ metered_event_count: nonNegativeInteger(input.metered_event_count ?? input.meteredEventCount, 'metered_event_count'),
385
+ billable_units: nonNegativeNumber(input.billable_units ?? input.billableUnits, 'billable_units'),
386
+ currency: stringOrDefault(input.currency, 'USD'),
387
+ amount_due_minor_units: nonNegativeInteger(input.amount_due_minor_units ?? input.amountDueMinorUnits, 'amount_due_minor_units'),
388
+ invoicing_state: stringOrDefault(input.invoicing_state ?? input.invoicingState, 'blocked_external_billing'),
389
+ billing_boundary: {
390
+ estimates_only_until_provider_wired: true,
391
+ external_invoice_required: true,
392
+ financial_outcome_claim: false,
393
+ },
394
+ ...baseFields(input),
395
+ };
396
+ const contract = withContractIdentity(body, 'hcbill', 'billing_record_id');
397
+ validateUsageBillingRecord(contract);
398
+ return contract;
399
+ }
400
+
401
+ export function validateUsageBillingRecord(contract) {
402
+ validateBase(contract, HOSTED_CLOUD_USAGE_BILLING_SCHEMA);
403
+ requiredString(contract.billing_record_id, 'billing_record_id');
404
+ requiredString(contract.tenant_id, 'tenant_id');
405
+ isoTimestamp(contract.period_start, 'period_start');
406
+ isoTimestamp(contract.period_end, 'period_end');
407
+ requiredString(contract.billing_provider_customer_ref, 'billing_provider_customer_ref');
408
+ requiredString(contract.usage_aggregate_ref, 'usage_aggregate_ref');
409
+ nonNegativeInteger(contract.metered_event_count, 'metered_event_count');
410
+ nonNegativeNumber(contract.billable_units, 'billable_units');
411
+ nonNegativeInteger(contract.amount_due_minor_units, 'amount_due_minor_units');
412
+ requiredTrue(contract.billing_boundary.estimates_only_until_provider_wired, 'billing_boundary.estimates_only_until_provider_wired');
413
+ requiredTrue(contract.billing_boundary.external_invoice_required, 'billing_boundary.external_invoice_required');
414
+ requiredFalse(contract.billing_boundary.financial_outcome_claim, 'billing_boundary.financial_outcome_claim');
415
+ return true;
416
+ }
417
+
418
+ export function buildDashboardSummary(input = {}) {
419
+ if (!isPlainObject(input)) throw new TypeError('buildDashboardSummary requires an options object');
420
+ assertNoForbiddenPayload(input, 'input');
421
+ const operatorEvidenceRefs = normalizeOperatorEvidenceRefs(input.operator_evidence_refs ?? input.operatorEvidenceRefs);
422
+ const readiness = readinessFrom(operatorEvidenceRefs);
423
+ const body = {
424
+ schema: HOSTED_CLOUD_DASHBOARD_SCHEMA,
425
+ dashboard_id: stringOrDefault(input.dashboard_id ?? input.dashboardId, undefined),
426
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
427
+ generated_at: isoTimestamp(input.generated_at ?? input.generatedAt, 'generated_at'),
428
+ account_count: nonNegativeInteger(input.account_count ?? input.accountCount, 'account_count'),
429
+ active_api_key_count: nonNegativeInteger(input.active_api_key_count ?? input.activeApiKeyCount, 'active_api_key_count'),
430
+ hosted_vault_count: nonNegativeInteger(input.hosted_vault_count ?? input.hostedVaultCount, 'hosted_vault_count'),
431
+ billing_period_ref: requiredString(input.billing_period_ref ?? input.billingPeriodRef, 'billing_period_ref'),
432
+ open_incident_count: nonNegativeInteger(input.open_incident_count ?? input.openIncidentCount, 'open_incident_count'),
433
+ backup_drill_ref: requiredString(input.backup_drill_ref ?? input.backupDrillRef, 'backup_drill_ref'),
434
+ incident_sla_ref: requiredString(input.incident_sla_ref ?? input.incidentSlaRef, 'incident_sla_ref'),
435
+ operator_evidence_refs: operatorEvidenceRefs,
436
+ readiness,
437
+ };
438
+ const contract = withContractIdentity(body, 'hcdash', 'dashboard_id');
439
+ validateDashboardSummary(contract);
440
+ return contract;
441
+ }
442
+
443
+ export function validateDashboardSummary(contract) {
444
+ validateBase(contract, HOSTED_CLOUD_DASHBOARD_SCHEMA);
445
+ requiredString(contract.dashboard_id, 'dashboard_id');
446
+ requiredString(contract.tenant_id, 'tenant_id');
447
+ isoTimestamp(contract.generated_at, 'generated_at');
448
+ nonNegativeInteger(contract.account_count, 'account_count');
449
+ nonNegativeInteger(contract.active_api_key_count, 'active_api_key_count');
450
+ nonNegativeInteger(contract.hosted_vault_count, 'hosted_vault_count');
451
+ requiredString(contract.billing_period_ref, 'billing_period_ref');
452
+ nonNegativeInteger(contract.open_incident_count, 'open_incident_count');
453
+ requiredString(contract.backup_drill_ref, 'backup_drill_ref');
454
+ requiredString(contract.incident_sla_ref, 'incident_sla_ref');
455
+ return true;
456
+ }
457
+
458
+ export function buildBackupDrillContract(input = {}) {
459
+ if (!isPlainObject(input)) throw new TypeError('buildBackupDrillContract requires an options object');
460
+ assertNoForbiddenPayload(input, 'input');
461
+ const body = {
462
+ schema: HOSTED_CLOUD_BACKUP_DRILL_SCHEMA,
463
+ backup_drill_id: stringOrDefault(input.backup_drill_id ?? input.backupDrillId, undefined),
464
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
465
+ vault_ref: requiredString(input.vault_ref ?? input.vaultRef, 'vault_ref'),
466
+ performed_at: isoTimestamp(input.performed_at ?? input.performedAt, 'performed_at'),
467
+ backup_snapshot_ref: requiredString(input.backup_snapshot_ref ?? input.backupSnapshotRef, 'backup_snapshot_ref'),
468
+ restore_evidence_ref: requiredString(input.restore_evidence_ref ?? input.restoreEvidenceRef, 'restore_evidence_ref'),
469
+ rpo_minutes: nonNegativeInteger(input.rpo_minutes ?? input.rpoMinutes, 'rpo_minutes'),
470
+ rto_minutes: nonNegativeInteger(input.rto_minutes ?? input.rtoMinutes, 'rto_minutes'),
471
+ drill_state: stringOrDefault(input.drill_state ?? input.drillState, 'blocked_until_operator_run'),
472
+ recovery_boundary: {
473
+ restore_operator_verified: input.restore_operator_verified === true || input.restoreOperatorVerified === true,
474
+ external_backup_system_required: true,
475
+ },
476
+ ...baseFields(input),
477
+ };
478
+ const contract = withContractIdentity(body, 'hcbackup', 'backup_drill_id');
479
+ validateBackupDrillContract(contract);
480
+ return contract;
481
+ }
482
+
483
+ export function validateBackupDrillContract(contract) {
484
+ validateBase(contract, HOSTED_CLOUD_BACKUP_DRILL_SCHEMA);
485
+ requiredString(contract.backup_drill_id, 'backup_drill_id');
486
+ requiredString(contract.tenant_id, 'tenant_id');
487
+ requiredString(contract.vault_ref, 'vault_ref');
488
+ isoTimestamp(contract.performed_at, 'performed_at');
489
+ requiredString(contract.backup_snapshot_ref, 'backup_snapshot_ref');
490
+ requiredString(contract.restore_evidence_ref, 'restore_evidence_ref');
491
+ nonNegativeInteger(contract.rpo_minutes, 'rpo_minutes');
492
+ nonNegativeInteger(contract.rto_minutes, 'rto_minutes');
493
+ requiredBoolean(contract.recovery_boundary.restore_operator_verified, 'recovery_boundary.restore_operator_verified');
494
+ requiredTrue(contract.recovery_boundary.external_backup_system_required, 'recovery_boundary.external_backup_system_required');
495
+ return true;
496
+ }
497
+
498
+ export function buildIncidentSlaRefs(input = {}) {
499
+ if (!isPlainObject(input)) throw new TypeError('buildIncidentSlaRefs requires an options object');
500
+ assertNoForbiddenPayload(input, 'input');
501
+ const body = {
502
+ schema: HOSTED_CLOUD_INCIDENT_SLA_SCHEMA,
503
+ incident_sla_id: stringOrDefault(input.incident_sla_id ?? input.incidentSlaId, undefined),
504
+ tenant_id: requiredString(input.tenant_id ?? input.tenantId, 'tenant_id'),
505
+ incident_response_ref: requiredString(input.incident_response_ref ?? input.incidentResponseRef, 'incident_response_ref'),
506
+ sla_policy_ref: requiredString(input.sla_policy_ref ?? input.slaPolicyRef, 'sla_policy_ref'),
507
+ support_owner_ref: requiredString(input.support_owner_ref ?? input.supportOwnerRef, 'support_owner_ref'),
508
+ escalation_policy_ref: requiredString(input.escalation_policy_ref ?? input.escalationPolicyRef, 'escalation_policy_ref'),
509
+ status_page_ref: requiredString(input.status_page_ref ?? input.statusPageRef, 'status_page_ref'),
510
+ generated_at: isoTimestamp(input.generated_at ?? input.generatedAt, 'generated_at'),
511
+ incident_boundary: {
512
+ customer_commitment_requires_approved_sla: true,
513
+ support_owner_required: true,
514
+ external_review_required: true,
515
+ },
516
+ operator_evidence_refs: normalizeOperatorEvidenceRefs(input.operator_evidence_refs ?? input.operatorEvidenceRefs),
517
+ };
518
+ body.readiness = readinessFrom(body.operator_evidence_refs);
519
+ const contract = withContractIdentity(body, 'hcsla', 'incident_sla_id');
520
+ validateIncidentSlaRefs(contract);
521
+ return contract;
522
+ }
523
+
524
+ export function validateIncidentSlaRefs(contract) {
525
+ validateBase(contract, HOSTED_CLOUD_INCIDENT_SLA_SCHEMA);
526
+ requiredString(contract.incident_sla_id, 'incident_sla_id');
527
+ requiredString(contract.tenant_id, 'tenant_id');
528
+ requiredString(contract.incident_response_ref, 'incident_response_ref');
529
+ requiredString(contract.sla_policy_ref, 'sla_policy_ref');
530
+ requiredString(contract.support_owner_ref, 'support_owner_ref');
531
+ requiredString(contract.escalation_policy_ref, 'escalation_policy_ref');
532
+ requiredString(contract.status_page_ref, 'status_page_ref');
533
+ isoTimestamp(contract.generated_at, 'generated_at');
534
+ requiredTrue(contract.incident_boundary.customer_commitment_requires_approved_sla, 'incident_boundary.customer_commitment_requires_approved_sla');
535
+ requiredTrue(contract.incident_boundary.support_owner_required, 'incident_boundary.support_owner_required');
536
+ requiredTrue(contract.incident_boundary.external_review_required, 'incident_boundary.external_review_required');
537
+ return true;
538
+ }
@@ -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.0' });
20
+ const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.2' });
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,