xytara 2.2.0 → 2.4.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.
@@ -0,0 +1,578 @@
1
+ "use strict";
2
+
3
+ function ensureArray(value) {
4
+ return Array.isArray(value) ? value : [];
5
+ }
6
+
7
+ function nowIso() {
8
+ return new Date().toISOString();
9
+ }
10
+
11
+ function listTransactionEntriesForAccount(state, accountId) {
12
+ return Array.from(state.transactions.values())
13
+ .filter((entry) => entry && entry.transaction && entry.transaction.account_id === accountId);
14
+ }
15
+
16
+ function listReceiptsForAccount(state, accountId) {
17
+ return Array.from(state.receipts.values())
18
+ .map((entry) => entry && entry.receipt ? entry.receipt : null)
19
+ .filter((receipt) => receipt && receipt.account_id === accountId);
20
+ }
21
+
22
+ function listAgentAccountsForIdentity(state, accountId) {
23
+ return Array.from(state.agentAccounts.values())
24
+ .map((entry) => entry && entry.account ? entry.account : null)
25
+ .filter((account) => account && account.account_id === accountId);
26
+ }
27
+
28
+ function listIdentityBindingsForAccount(state, accountId) {
29
+ return Array.from(state.machineIdentityBindings.values())
30
+ .filter((binding) => binding && binding.account_id === accountId);
31
+ }
32
+
33
+ function collectIdentityDeliverables(entry) {
34
+ const deliverables = entry && entry.command && Array.isArray(entry.command.deliverables)
35
+ ? entry.command.deliverables
36
+ : [];
37
+ const identityRefs = [];
38
+ const registryRefs = [];
39
+ const anchorRefs = [];
40
+ for (const item of deliverables) {
41
+ if (!item || typeof item !== "object") continue;
42
+ if (item.identity_attestation_ref) identityRefs.push(item.identity_attestation_ref);
43
+ if (item.identity_link_ref) identityRefs.push(item.identity_link_ref);
44
+ if (item.registry_record_ref) registryRefs.push(item.registry_record_ref);
45
+ if (item.registry_pack_ref) registryRefs.push(item.registry_pack_ref);
46
+ if (item.anchor_ref) anchorRefs.push(item.anchor_ref);
47
+ }
48
+ return {
49
+ identity_refs: identityRefs,
50
+ registry_refs: registryRefs,
51
+ anchor_refs: anchorRefs
52
+ };
53
+ }
54
+
55
+ function buildMachineIdentitySummary(state, accountId) {
56
+ const agentAccounts = listAgentAccountsForIdentity(state, accountId);
57
+ const identityBindings = listIdentityBindingsForAccount(state, accountId);
58
+ const transactionEntries = listTransactionEntriesForAccount(state, accountId);
59
+ const receipts = listReceiptsForAccount(state, accountId);
60
+ const identityTransactions = transactionEntries.filter((entry) =>
61
+ ensureArray(entry.command && entry.command.deliverables).some((task) =>
62
+ task && typeof task.task_ref === "string" && (
63
+ task.task_ref === "identity.attest.preview" ||
64
+ task.task_ref === "identity.registry.link" ||
65
+ task.task_ref === "registry.register" ||
66
+ task.task_ref === "registry.pack.bundle" ||
67
+ task.task_ref === "anchoring.submit"
68
+ )
69
+ ) || ensureArray(entry.transaction && entry.transaction.execution && entry.transaction.execution.tasks).some((task) =>
70
+ task && typeof task.task_ref === "string" && (
71
+ task.task_ref === "identity.attest.preview" ||
72
+ task.task_ref === "identity.registry.link" ||
73
+ task.task_ref === "registry.register" ||
74
+ task.task_ref === "registry.pack.bundle" ||
75
+ task.task_ref === "anchoring.submit"
76
+ )
77
+ )
78
+ );
79
+ const refs = identityTransactions.reduce((acc, transaction) => {
80
+ const next = collectIdentityDeliverables(transaction);
81
+ acc.identity_refs.push(...next.identity_refs);
82
+ acc.registry_refs.push(...next.registry_refs);
83
+ acc.anchor_refs.push(...next.anchor_refs);
84
+ return acc;
85
+ }, {
86
+ identity_refs: [],
87
+ registry_refs: [],
88
+ anchor_refs: []
89
+ });
90
+
91
+ const latestIdentityTransaction = identityTransactions
92
+ .map((entry) => ({
93
+ transaction_id: entry.transaction && entry.transaction.transaction_id ? entry.transaction.transaction_id : null,
94
+ created_at_iso: entry.transaction && entry.transaction.created_at_iso ? entry.transaction.created_at_iso : null
95
+ }))
96
+ .sort((a, b) => String(a.created_at_iso || "").localeCompare(String(b.created_at_iso || "")))
97
+ .slice(-1)[0] || null;
98
+
99
+ let identityState = "unbound";
100
+ if (agentAccounts.length > 0) identityState = "account_issued";
101
+ if (identityBindings.length > 0) identityState = "identity_binding_present";
102
+ if (identityTransactions.length > 0) identityState = "identity_activity_present";
103
+ if (refs.registry_refs.length > 0 && refs.anchor_refs.length > 0) identityState = "registry_anchor_present";
104
+
105
+ return {
106
+ summary_version: "xytara-machine-identity-summary-v1",
107
+ account_id: accountId,
108
+ machine_identity_state: identityState,
109
+ counts: {
110
+ agent_account_count: agentAccounts.length,
111
+ identity_binding_count: identityBindings.length,
112
+ identity_transaction_count: identityTransactions.length,
113
+ receipt_count: receipts.length,
114
+ identity_ref_count: refs.identity_refs.length,
115
+ registry_ref_count: refs.registry_refs.length,
116
+ anchor_ref_count: refs.anchor_refs.length
117
+ },
118
+ latest_identity_transaction_id: latestIdentityTransaction ? latestIdentityTransaction.transaction_id : null,
119
+ linked_surfaces: {
120
+ machine_identity_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-bundle`,
121
+ agent_accounts_ref: "/v1/agent-accounts",
122
+ operator_shell_summary_ref: "/v1/operator-shell/summary"
123
+ },
124
+ generated_at_iso: nowIso()
125
+ };
126
+ }
127
+
128
+ function buildMachineIdentityBundle(state, accountId) {
129
+ const summary = buildMachineIdentitySummary(state, accountId);
130
+ const agentAccounts = listAgentAccountsForIdentity(state, accountId);
131
+ const identityBindings = listIdentityBindingsForAccount(state, accountId);
132
+ const transactionEntries = listTransactionEntriesForAccount(state, accountId);
133
+ const identityTransactions = transactionEntries
134
+ .filter((entry) =>
135
+ ensureArray(entry.command && entry.command.deliverables).some((task) =>
136
+ task && typeof task.task_ref === "string" && (
137
+ task.task_ref === "identity.attest.preview" ||
138
+ task.task_ref === "identity.registry.link" ||
139
+ task.task_ref === "registry.register" ||
140
+ task.task_ref === "registry.pack.bundle" ||
141
+ task.task_ref === "anchoring.submit"
142
+ )
143
+ ) || ensureArray(entry.transaction && entry.transaction.execution && entry.transaction.execution.tasks).some((task) =>
144
+ task && typeof task.task_ref === "string" && (
145
+ task.task_ref === "identity.attest.preview" ||
146
+ task.task_ref === "identity.registry.link" ||
147
+ task.task_ref === "registry.register" ||
148
+ task.task_ref === "registry.pack.bundle" ||
149
+ task.task_ref === "anchoring.submit"
150
+ )
151
+ )
152
+ )
153
+ .map((entry) => {
154
+ const refs = collectIdentityDeliverables(entry);
155
+ return {
156
+ transaction_id: entry.transaction && entry.transaction.transaction_id ? entry.transaction.transaction_id : null,
157
+ status: entry.transaction && entry.transaction.status ? entry.transaction.status : null,
158
+ created_at_iso: entry.transaction && entry.transaction.created_at_iso ? entry.transaction.created_at_iso : null,
159
+ identity_refs: refs.identity_refs,
160
+ registry_refs: refs.registry_refs,
161
+ anchor_refs: refs.anchor_refs
162
+ };
163
+ });
164
+
165
+ return {
166
+ bundle_version: "xytara-machine-identity-bundle-v1",
167
+ account_id: accountId,
168
+ machine_identity_summary: summary,
169
+ agent_accounts: agentAccounts,
170
+ identity_bindings: identityBindings,
171
+ identity_transactions: identityTransactions,
172
+ linked_surfaces: {
173
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
174
+ authority_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/authority-summary`,
175
+ wallet_ledger_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/wallet-ledger-bundle`
176
+ },
177
+ generated_at_iso: nowIso()
178
+ };
179
+ }
180
+
181
+ function buildMachineIdentityAttachmentSummary(state, accountId) {
182
+ const agentAccounts = listAgentAccountsForIdentity(state, accountId);
183
+ const bundle = buildMachineIdentityBundle(state, accountId);
184
+ const attachmentRows = bundle.identity_transactions.map((entry) => ({
185
+ transaction_id: entry.transaction_id,
186
+ identity_attachment_count: ensureArray(entry.identity_refs).length,
187
+ registry_attachment_count: ensureArray(entry.registry_refs).length,
188
+ anchor_attachment_count: ensureArray(entry.anchor_refs).length,
189
+ has_registry_anchor_pair: ensureArray(entry.registry_refs).length > 0 && ensureArray(entry.anchor_refs).length > 0,
190
+ created_at_iso: entry.created_at_iso || null
191
+ }));
192
+
193
+ return {
194
+ summary_version: "xytara-machine-identity-attachment-summary-v1",
195
+ account_id: accountId,
196
+ machine_identity_attachment_state: attachmentRows.length > 0 ? "attachments_present" : agentAccounts.length > 0 ? "account_only" : "unattached",
197
+ counts: {
198
+ agent_account_count: agentAccounts.length,
199
+ identity_binding_count: Array.isArray(bundle.identity_bindings) ? bundle.identity_bindings.length : 0,
200
+ attachment_row_count: attachmentRows.length,
201
+ registry_anchor_pair_count: attachmentRows.filter((entry) => entry.has_registry_anchor_pair).length
202
+ },
203
+ attachment_rows: attachmentRows,
204
+ linked_surfaces: {
205
+ machine_identity_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-bundle`,
206
+ machine_identity_lineage_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-lineage-summary`
207
+ },
208
+ generated_at_iso: nowIso()
209
+ };
210
+ }
211
+
212
+ function buildMachineIdentityLineageSummary(state, accountId) {
213
+ const bundle = buildMachineIdentityBundle(state, accountId);
214
+ const lineageRows = bundle.identity_transactions.map((entry, index) => {
215
+ const predecessor = index > 0 ? bundle.identity_transactions[index - 1] : null;
216
+ const successor = index < bundle.identity_transactions.length - 1 ? bundle.identity_transactions[index + 1] : null;
217
+ return {
218
+ transaction_id: entry.transaction_id,
219
+ predecessor_transaction_id: predecessor ? predecessor.transaction_id : null,
220
+ successor_transaction_id: successor ? successor.transaction_id : null,
221
+ lineage_position: predecessor ? successor ? "middle" : "leaf" : successor ? "root" : "standalone",
222
+ registry_ref_count: ensureArray(entry.registry_refs).length,
223
+ anchor_ref_count: ensureArray(entry.anchor_refs).length,
224
+ created_at_iso: entry.created_at_iso || null
225
+ };
226
+ });
227
+
228
+ return {
229
+ summary_version: "xytara-machine-identity-lineage-summary-v1",
230
+ account_id: accountId,
231
+ identity_transaction_count: bundle.identity_transactions.length,
232
+ root_count: lineageRows.filter((entry) => entry.lineage_position === "root" || entry.lineage_position === "standalone").length,
233
+ leaf_count: lineageRows.filter((entry) => entry.lineage_position === "leaf" || entry.lineage_position === "standalone").length,
234
+ lineage_rows: lineageRows,
235
+ linked_surfaces: {
236
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
237
+ machine_identity_attachment_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attachment-summary`
238
+ },
239
+ generated_at_iso: nowIso()
240
+ };
241
+ }
242
+
243
+ function buildMachineIdentityBindingLineageSummary(state, accountId) {
244
+ const identityBindings = listIdentityBindingsForAccount(state, accountId)
245
+ .slice()
246
+ .sort((a, b) => String(a.created_at_iso || "").localeCompare(String(b.created_at_iso || "")));
247
+ const lineageRows = identityBindings.map((entry) => ({
248
+ binding_id: entry.binding_id,
249
+ status: entry.status,
250
+ identity_kind: entry.identity_kind,
251
+ predecessor_binding_id: entry.rotated_from_binding_id || null,
252
+ successor_binding_id: entry.replaced_by_binding_id || null,
253
+ lineage_position: entry.rotated_from_binding_id
254
+ ? entry.replaced_by_binding_id
255
+ ? "middle"
256
+ : "leaf"
257
+ : entry.replaced_by_binding_id
258
+ ? "root"
259
+ : "standalone",
260
+ expires_at_iso: entry.expires_at_iso || null,
261
+ created_at_iso: entry.created_at_iso || null,
262
+ updated_at_iso: entry.updated_at_iso || null
263
+ }));
264
+
265
+ return {
266
+ summary_version: "xytara-machine-identity-binding-lineage-summary-v1",
267
+ account_id: accountId,
268
+ identity_binding_count: identityBindings.length,
269
+ rotated_binding_count: lineageRows.filter((entry) => entry.predecessor_binding_id || entry.successor_binding_id).length,
270
+ lineage_rows: lineageRows,
271
+ linked_surfaces: {
272
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
273
+ machine_identity_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-review-bundle`,
274
+ machine_identity_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attention-summary`
275
+ },
276
+ generated_at_iso: nowIso()
277
+ };
278
+ }
279
+
280
+ function buildMachineIdentityProfile(state, accountId) {
281
+ const summary = buildMachineIdentitySummary(state, accountId);
282
+ const bundle = buildMachineIdentityBundle(state, accountId);
283
+ const attachment = buildMachineIdentityAttachmentSummary(state, accountId);
284
+ const lineage = buildMachineIdentityLineageSummary(state, accountId);
285
+ const primaryAgentAccount = Array.isArray(bundle.agent_accounts) && bundle.agent_accounts.length > 0
286
+ ? bundle.agent_accounts[0]
287
+ : null;
288
+ const primaryIdentityBinding = Array.isArray(bundle.identity_bindings) && bundle.identity_bindings.length > 0
289
+ ? bundle.identity_bindings[0]
290
+ : null;
291
+
292
+ return {
293
+ profile_version: "xytara-machine-identity-profile-v1",
294
+ account_id: accountId,
295
+ machine_identity_state: summary.machine_identity_state,
296
+ primary_identity_kind: primaryIdentityBinding
297
+ ? primaryIdentityBinding.identity_kind
298
+ : primaryAgentAccount
299
+ ? "agent_account"
300
+ : "runtime_account_only",
301
+ primary_agent_account_id: primaryAgentAccount ? primaryAgentAccount.account_id : null,
302
+ primary_identity_binding_id: primaryIdentityBinding ? primaryIdentityBinding.binding_id : null,
303
+ settlement_mode: primaryAgentAccount ? primaryAgentAccount.settlement_mode || null : null,
304
+ protocol: primaryAgentAccount ? primaryAgentAccount.protocol || null : null,
305
+ attachment_state: attachment.machine_identity_attachment_state,
306
+ lineage_state: lineage.identity_transaction_count > 0 ? "lineage_present" : "lineage_absent",
307
+ linked_surfaces: {
308
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
309
+ machine_identity_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-bundle`,
310
+ machine_identity_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-policy-pack`,
311
+ machine_identity_binding_lineage_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-binding-lineage-summary`
312
+ },
313
+ generated_at_iso: nowIso()
314
+ };
315
+ }
316
+
317
+ function buildMachineIdentityPolicyPack(state, accountId) {
318
+ const summary = buildMachineIdentitySummary(state, accountId);
319
+ const profile = buildMachineIdentityProfile(state, accountId);
320
+ const attachment = buildMachineIdentityAttachmentSummary(state, accountId);
321
+ const lineage = buildMachineIdentityLineageSummary(state, accountId);
322
+ const bindingLineage = buildMachineIdentityBindingLineageSummary(state, accountId);
323
+ const policyTemplates = [
324
+ {
325
+ template_id: "runtime_builder_identity",
326
+ target_state: "account_issued",
327
+ recommended_for: "runtime-first machine onboarding",
328
+ steps: ["issue_agent_account", "confirm_protocol", "confirm_settlement_mode"],
329
+ binding_defaults: {
330
+ identity_kind: "runtime_builder_identity",
331
+ registry_scope: null,
332
+ attach_primary_agent_account: true,
333
+ use_latest_identity_transaction: false
334
+ }
335
+ },
336
+ {
337
+ template_id: "registry_anchor_identity",
338
+ target_state: "registry_anchor_present",
339
+ recommended_for: "identity-plus-registry continuity",
340
+ steps: ["identity_attest_preview", "registry_register", "identity_registry_link", "anchoring_submit"],
341
+ binding_defaults: {
342
+ identity_kind: "registry_anchor_identity",
343
+ registry_scope: "registry.identity.default",
344
+ attach_primary_agent_account: false,
345
+ use_latest_identity_transaction: true
346
+ }
347
+ },
348
+ {
349
+ template_id: "continuity_repair_identity",
350
+ target_state: "identity_activity_present",
351
+ recommended_for: "repair partial identity attachment posture",
352
+ steps: ["review_attachment_rows", "complete_registry_anchor_pair", "inspect_lineage"],
353
+ binding_defaults: {
354
+ identity_kind: "registry_anchor_identity",
355
+ registry_scope: "registry.identity.default",
356
+ attach_primary_agent_account: true,
357
+ use_latest_identity_transaction: true
358
+ }
359
+ }
360
+ ];
361
+
362
+ let recommendedPolicyMotion = "issue_identity_from_template";
363
+ if (summary.machine_identity_state === "registry_anchor_present") {
364
+ recommendedPolicyMotion = "maintain_identity_profile";
365
+ } else if (attachment.counts.registry_anchor_pair_count === 0 && attachment.counts.attachment_row_count > 0) {
366
+ recommendedPolicyMotion = "complete_registry_anchor_pair";
367
+ } else if (lineage.identity_transaction_count > 0) {
368
+ recommendedPolicyMotion = "stabilize_identity_lineage";
369
+ }
370
+
371
+ return {
372
+ pack_version: "xytara-machine-identity-policy-pack-v1",
373
+ account_id: accountId,
374
+ machine_identity_summary: summary,
375
+ machine_identity_profile: profile,
376
+ machine_identity_attachment_summary: attachment,
377
+ machine_identity_lineage_summary: lineage,
378
+ machine_identity_binding_lineage_summary: bindingLineage,
379
+ recommended_policy_motion: recommendedPolicyMotion,
380
+ policy_templates: policyTemplates,
381
+ linked_surfaces: {
382
+ machine_identity_profile_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-profile`,
383
+ machine_identity_attachment_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attachment-summary`,
384
+ machine_identity_lineage_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-lineage-summary`,
385
+ machine_identity_binding_lineage_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-binding-lineage-summary`
386
+ },
387
+ generated_at_iso: nowIso()
388
+ };
389
+ }
390
+
391
+ function buildMachineIdentityPolicyApplicationSummary(state, accountId, templateId) {
392
+ const pack = buildMachineIdentityPolicyPack(state, accountId);
393
+ const selectedTemplate = ensureArray(pack.policy_templates).find((entry) => entry.template_id === templateId)
394
+ || ensureArray(pack.policy_templates).find((entry) => {
395
+ if (pack.recommended_policy_motion === "maintain_identity_profile") {
396
+ return entry.template_id === "registry_anchor_identity";
397
+ }
398
+ if (pack.recommended_policy_motion === "complete_registry_anchor_pair") {
399
+ return entry.template_id === "continuity_repair_identity";
400
+ }
401
+ if (pack.recommended_policy_motion === "stabilize_identity_lineage") {
402
+ return entry.template_id === "continuity_repair_identity";
403
+ }
404
+ return entry.template_id === "runtime_builder_identity";
405
+ })
406
+ || ensureArray(pack.policy_templates)[0]
407
+ || null;
408
+ const bindingDefaults = selectedTemplate && selectedTemplate.binding_defaults ? selectedTemplate.binding_defaults : {};
409
+ const suggestedBindingPayload = {
410
+ account_id: accountId,
411
+ identity_kind: bindingDefaults.identity_kind || "registry_anchor_identity",
412
+ registry_scope: bindingDefaults.registry_scope || null,
413
+ attached_agent_account_id: bindingDefaults.attach_primary_agent_account
414
+ ? pack.machine_identity_profile.primary_agent_account_id || null
415
+ : null,
416
+ source_transaction_id: bindingDefaults.use_latest_identity_transaction
417
+ ? pack.machine_identity_summary.latest_identity_transaction_id || null
418
+ : null,
419
+ issued_by: "operator",
420
+ labels: selectedTemplate ? [`policy:${selectedTemplate.template_id}`] : []
421
+ };
422
+
423
+ return {
424
+ summary_version: "xytara-machine-identity-policy-application-summary-v1",
425
+ account_id: accountId,
426
+ recommended_policy_motion: pack.recommended_policy_motion,
427
+ selected_template_id: selectedTemplate ? selectedTemplate.template_id : null,
428
+ available_template_ids: ensureArray(pack.policy_templates).map((entry) => entry.template_id),
429
+ suggested_binding_payload: suggestedBindingPayload,
430
+ selected_template: selectedTemplate,
431
+ linked_surfaces: {
432
+ machine_identity_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-policy-pack`,
433
+ machine_identity_profile_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-profile`,
434
+ machine_identity_binding_lineage_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-binding-lineage-summary`
435
+ },
436
+ generated_at_iso: nowIso()
437
+ };
438
+ }
439
+
440
+ function buildMachineIdentityPolicyPackSummary(state, accountId) {
441
+ const pack = buildMachineIdentityPolicyPack(state, accountId);
442
+ return {
443
+ summary_version: "xytara-machine-identity-policy-pack-summary-v1",
444
+ account_id: accountId,
445
+ machine_identity_state: pack.machine_identity_summary.machine_identity_state,
446
+ recommended_policy_motion: pack.recommended_policy_motion,
447
+ template_count: Array.isArray(pack.policy_templates) ? pack.policy_templates.length : 0,
448
+ linked_surfaces: pack.linked_surfaces,
449
+ generated_at_iso: pack.generated_at_iso
450
+ };
451
+ }
452
+
453
+ function buildMachineIdentityReviewBundle(state, accountId) {
454
+ const summary = buildMachineIdentitySummary(state, accountId);
455
+ const bundle = buildMachineIdentityBundle(state, accountId);
456
+ const reviewRows = ensureArray(bundle.identity_bindings).map((binding) => {
457
+ const hasRegistryScope = typeof binding.registry_scope === "string" && binding.registry_scope.length > 0;
458
+ const hasSourceTransaction = typeof binding.source_transaction_id === "string" && binding.source_transaction_id.length > 0;
459
+ const hasAttachedAgent = typeof binding.attached_agent_account_id === "string" && binding.attached_agent_account_id.length > 0;
460
+ const hasRotationLineage = Boolean(binding.rotated_from_binding_id || binding.replaced_by_binding_id);
461
+ const reviewState = binding.status !== "active"
462
+ ? "revoked"
463
+ : hasRegistryScope && (hasSourceTransaction || hasAttachedAgent)
464
+ ? "healthy"
465
+ : "repair_candidate";
466
+ return {
467
+ binding_id: binding.binding_id,
468
+ identity_kind: binding.identity_kind,
469
+ review_state: reviewState,
470
+ has_registry_scope: hasRegistryScope,
471
+ has_source_transaction: hasSourceTransaction,
472
+ has_attached_agent_account: hasAttachedAgent,
473
+ has_rotation_lineage: hasRotationLineage,
474
+ recommended_action: reviewState === "repair_candidate"
475
+ ? "complete_identity_binding_context"
476
+ : reviewState === "revoked"
477
+ ? "review_for_replacement"
478
+ : "keep_active"
479
+ };
480
+ });
481
+
482
+ return {
483
+ bundle_version: "xytara-machine-identity-review-bundle-v1",
484
+ account_id: accountId,
485
+ machine_identity_summary: summary,
486
+ review_rows: reviewRows,
487
+ review_counts: {
488
+ healthy_count: reviewRows.filter((entry) => entry.review_state === "healthy").length,
489
+ repair_candidate_count: reviewRows.filter((entry) => entry.review_state === "repair_candidate").length,
490
+ revoked_count: reviewRows.filter((entry) => entry.review_state === "revoked").length
491
+ },
492
+ linked_surfaces: {
493
+ machine_identity_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-bundle`,
494
+ machine_identity_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attention-summary`,
495
+ machine_identity_binding_lineage_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-binding-lineage-summary`
496
+ },
497
+ generated_at_iso: nowIso()
498
+ };
499
+ }
500
+
501
+ function buildMachineIdentityAttentionSummary(state, accountId) {
502
+ const reviewBundle = buildMachineIdentityReviewBundle(state, accountId);
503
+ const attentionRows = reviewBundle.review_rows.filter((entry) => entry.review_state !== "healthy");
504
+ return {
505
+ summary_version: "xytara-machine-identity-attention-summary-v1",
506
+ account_id: accountId,
507
+ overall_attention_state: attentionRows.length > 0 ? "attention_required" : "healthy",
508
+ attention_binding_count: attentionRows.length,
509
+ attention_rows: attentionRows,
510
+ review_counts: reviewBundle.review_counts,
511
+ linked_surfaces: {
512
+ machine_identity_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-review-bundle`,
513
+ machine_identity_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-bundle`
514
+ },
515
+ generated_at_iso: nowIso()
516
+ };
517
+ }
518
+
519
+ function buildMachineIdentityOperatorBundle(state, accountId) {
520
+ const summary = buildMachineIdentitySummary(state, accountId);
521
+ const bundle = buildMachineIdentityBundle(state, accountId);
522
+ const attachment = buildMachineIdentityAttachmentSummary(state, accountId);
523
+ const lineage = buildMachineIdentityLineageSummary(state, accountId);
524
+ const bindingLineage = buildMachineIdentityBindingLineageSummary(state, accountId);
525
+ const profile = buildMachineIdentityProfile(state, accountId);
526
+ const policyPackSummary = buildMachineIdentityPolicyPackSummary(state, accountId);
527
+ const policyApplicationSummary = buildMachineIdentityPolicyApplicationSummary(state, accountId, null);
528
+ const reviewBundle = buildMachineIdentityReviewBundle(state, accountId);
529
+ const attentionSummary = buildMachineIdentityAttentionSummary(state, accountId);
530
+
531
+ return {
532
+ bundle_version: "xytara-machine-identity-operator-bundle-v1",
533
+ account_id: accountId,
534
+ operator_posture: {
535
+ machine_identity_state: summary.machine_identity_state,
536
+ overall_attention_state: attentionSummary.overall_attention_state,
537
+ recommended_policy_motion: policyPackSummary.recommended_policy_motion,
538
+ identity_binding_count: summary.counts.identity_binding_count,
539
+ identity_transaction_count: summary.counts.identity_transaction_count,
540
+ rotated_binding_count: bindingLineage.rotated_binding_count,
541
+ repair_candidate_count: reviewBundle.review_counts.repair_candidate_count,
542
+ revoked_binding_count: reviewBundle.review_counts.revoked_count
543
+ },
544
+ machine_identity_summary: summary,
545
+ machine_identity_profile: profile,
546
+ machine_identity_bundle: bundle,
547
+ machine_identity_attachment_summary: attachment,
548
+ machine_identity_lineage_summary: lineage,
549
+ machine_identity_binding_lineage_summary: bindingLineage,
550
+ machine_identity_policy_pack_summary: policyPackSummary,
551
+ machine_identity_policy_application_summary: policyApplicationSummary,
552
+ machine_identity_review_bundle: reviewBundle,
553
+ machine_identity_attention_summary: attentionSummary,
554
+ linked_surfaces: {
555
+ machine_identity_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-summary`,
556
+ machine_identity_profile_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-profile`,
557
+ machine_identity_policy_pack_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-policy-pack`,
558
+ machine_identity_review_bundle_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-review-bundle`,
559
+ machine_identity_attention_summary_ref: `/v1/economics/accounts/${encodeURIComponent(accountId)}/machine-identity-attention-summary`
560
+ },
561
+ generated_at_iso: nowIso()
562
+ };
563
+ }
564
+
565
+ module.exports = {
566
+ buildMachineIdentitySummary,
567
+ buildMachineIdentityBundle,
568
+ buildMachineIdentityAttachmentSummary,
569
+ buildMachineIdentityLineageSummary,
570
+ buildMachineIdentityBindingLineageSummary,
571
+ buildMachineIdentityProfile,
572
+ buildMachineIdentityPolicyPack,
573
+ buildMachineIdentityPolicyPackSummary,
574
+ buildMachineIdentityPolicyApplicationSummary,
575
+ buildMachineIdentityReviewBundle,
576
+ buildMachineIdentityAttentionSummary,
577
+ buildMachineIdentityOperatorBundle
578
+ };
@@ -20,8 +20,12 @@ function createRuntimeState() {
20
20
  checkoutSessions: new Map(),
21
21
  checkoutEvents: new Map(),
22
22
  externalCreditGrants: new Map(),
23
+ accountAuthorityBindings: new Map(),
23
24
  accountSpendCredentials: new Map(),
24
25
  accountSpendCredentialsByToken: new Map(),
26
+ machineIdentityBindings: new Map(),
27
+ operatorParticipants: new Map(),
28
+ networkParticipants: new Map(),
25
29
  runtimeBridgeDispatches: new Map(),
26
30
  agentAccounts: new Map(),
27
31
  transactions: new Map(),