xytara 2.3.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,175 @@
1
+ "use strict";
2
+
3
+ function normalizeString(value, fallback = null) {
4
+ const trimmed = typeof value === "string" ? value.trim() : "";
5
+ return trimmed || fallback;
6
+ }
7
+
8
+ function ensureArray(value) {
9
+ return Array.isArray(value) ? value : [];
10
+ }
11
+
12
+ function nowIso() {
13
+ return new Date().toISOString();
14
+ }
15
+
16
+ function buildIdentityBindingPublicView(binding) {
17
+ if (!binding) return null;
18
+ return {
19
+ binding_id: binding.binding_id,
20
+ account_id: binding.account_id,
21
+ status: binding.status,
22
+ identity_kind: binding.identity_kind,
23
+ identity_ref: binding.identity_ref,
24
+ registry_scope: binding.registry_scope || null,
25
+ attached_agent_account_id: binding.attached_agent_account_id || null,
26
+ source_transaction_id: binding.source_transaction_id || null,
27
+ expires_at_iso: binding.expires_at_iso || null,
28
+ rotated_from_binding_id: binding.rotated_from_binding_id || null,
29
+ replaced_by_binding_id: binding.replaced_by_binding_id || null,
30
+ created_at_iso: binding.created_at_iso,
31
+ updated_at_iso: binding.updated_at_iso,
32
+ revoked_at_iso: binding.revoked_at_iso || null,
33
+ revoke_reason: binding.revoke_reason || null,
34
+ labels: ensureArray(binding.labels),
35
+ issued_by: binding.issued_by || null
36
+ };
37
+ }
38
+
39
+ function createIdentityBinding(state, body) {
40
+ const payload = body && typeof body === "object" && !Array.isArray(body) ? body : {};
41
+ const createdAtIso = nowIso();
42
+ const binding = {
43
+ binding_id: normalizeString(payload.binding_id, `identity_binding_${state.machineIdentityBindings.size + 1}`),
44
+ account_id: normalizeString(payload.account_id, "acct_demo"),
45
+ status: normalizeString(payload.status, "active"),
46
+ identity_kind: normalizeString(payload.identity_kind, "registry_anchor_identity"),
47
+ identity_ref: normalizeString(payload.identity_ref, `identity_ref_${state.machineIdentityBindings.size + 1}`),
48
+ registry_scope: normalizeString(payload.registry_scope, null),
49
+ attached_agent_account_id: normalizeString(payload.attached_agent_account_id, null),
50
+ source_transaction_id: normalizeString(payload.source_transaction_id, null),
51
+ expires_at_iso: normalizeString(payload.expires_at_iso, null),
52
+ labels: ensureArray(payload.labels).map((value) => String(value || "").trim()).filter(Boolean),
53
+ issued_by: normalizeString(payload.issued_by, "operator"),
54
+ rotated_from_binding_id: normalizeString(payload.rotated_from_binding_id, null),
55
+ replaced_by_binding_id: normalizeString(payload.replaced_by_binding_id, null),
56
+ created_at_iso: createdAtIso,
57
+ updated_at_iso: createdAtIso,
58
+ revoked_at_iso: null,
59
+ revoke_reason: null
60
+ };
61
+ state.machineIdentityBindings.set(binding.binding_id, binding);
62
+ return buildIdentityBindingPublicView(binding);
63
+ }
64
+
65
+ function listIdentityBindings(state, filters) {
66
+ const payload = filters && typeof filters === "object" && !Array.isArray(filters) ? filters : {};
67
+ const accountId = normalizeString(payload.account_id, null);
68
+ const status = normalizeString(payload.status, null);
69
+ return Array.from(state.machineIdentityBindings.values())
70
+ .filter((binding) => {
71
+ if (accountId && binding.account_id !== accountId) return false;
72
+ if (status && binding.status !== status) return false;
73
+ return true;
74
+ })
75
+ .map((binding) => buildIdentityBindingPublicView(binding));
76
+ }
77
+
78
+ function getIdentityBinding(state, bindingId) {
79
+ if (!bindingId || !state.machineIdentityBindings.has(bindingId)) return null;
80
+ return buildIdentityBindingPublicView(state.machineIdentityBindings.get(bindingId));
81
+ }
82
+
83
+ function revokeIdentityBinding(state, bindingId, body) {
84
+ if (!bindingId || !state.machineIdentityBindings.has(bindingId)) return null;
85
+ const payload = body && typeof body === "object" && !Array.isArray(body) ? body : {};
86
+ const current = state.machineIdentityBindings.get(bindingId);
87
+ const next = {
88
+ ...current,
89
+ status: "revoked",
90
+ revoked_at_iso: nowIso(),
91
+ revoke_reason: normalizeString(payload.reason, "operator_revoked"),
92
+ updated_at_iso: nowIso()
93
+ };
94
+ state.machineIdentityBindings.set(bindingId, next);
95
+ return buildIdentityBindingPublicView(next);
96
+ }
97
+
98
+ function getIdentityBindingRotationSummary(state, bindingId) {
99
+ if (!bindingId || !state.machineIdentityBindings.has(bindingId)) return null;
100
+ const binding = state.machineIdentityBindings.get(bindingId);
101
+ return {
102
+ summary_version: "xytara-identity-binding-rotation-summary-v1",
103
+ binding_id: binding.binding_id,
104
+ account_id: binding.account_id,
105
+ status: binding.status,
106
+ predecessor_binding_id: binding.rotated_from_binding_id || null,
107
+ successor_binding_id: binding.replaced_by_binding_id || null,
108
+ expires_at_iso: binding.expires_at_iso || null,
109
+ rotation_state: binding.rotated_from_binding_id || binding.replaced_by_binding_id
110
+ ? "lineage_present"
111
+ : "standalone",
112
+ linked_surfaces: {
113
+ identity_binding_ref: `/v1/identity/bindings/${encodeURIComponent(binding.binding_id)}`
114
+ },
115
+ generated_at_iso: nowIso()
116
+ };
117
+ }
118
+
119
+ function renewIdentityBinding(state, bindingId, body) {
120
+ if (!bindingId || !state.machineIdentityBindings.has(bindingId)) return null;
121
+ const payload = body && typeof body === "object" && !Array.isArray(body) ? body : {};
122
+ const current = state.machineIdentityBindings.get(bindingId);
123
+ const next = {
124
+ ...current,
125
+ expires_at_iso: normalizeString(payload.expires_at_iso, current.expires_at_iso || null),
126
+ updated_at_iso: nowIso()
127
+ };
128
+ state.machineIdentityBindings.set(bindingId, next);
129
+ return buildIdentityBindingPublicView(next);
130
+ }
131
+
132
+ function rotateIdentityBinding(state, bindingId, body) {
133
+ if (!bindingId || !state.machineIdentityBindings.has(bindingId)) return null;
134
+ const payload = body && typeof body === "object" && !Array.isArray(body) ? body : {};
135
+ const current = state.machineIdentityBindings.get(bindingId);
136
+ const successorBindingId = normalizeString(payload.successor_binding_id, `${bindingId}_rotated`);
137
+ const successor = createIdentityBinding(state, {
138
+ binding_id: successorBindingId,
139
+ account_id: current.account_id,
140
+ identity_kind: normalizeString(payload.identity_kind, current.identity_kind),
141
+ identity_ref: normalizeString(payload.identity_ref, current.identity_ref),
142
+ registry_scope: normalizeString(payload.registry_scope, current.registry_scope),
143
+ attached_agent_account_id: normalizeString(payload.attached_agent_account_id, current.attached_agent_account_id),
144
+ source_transaction_id: normalizeString(payload.source_transaction_id, current.source_transaction_id),
145
+ expires_at_iso: normalizeString(payload.expires_at_iso, current.expires_at_iso || null),
146
+ labels: ensureArray(payload.labels).length > 0 ? ensureArray(payload.labels) : ensureArray(current.labels),
147
+ issued_by: normalizeString(payload.issued_by, current.issued_by || "operator"),
148
+ rotated_from_binding_id: current.binding_id
149
+ });
150
+ revokeIdentityBinding(state, bindingId, {
151
+ reason: normalizeString(payload.reason, "rotated_to_successor")
152
+ });
153
+ state.machineIdentityBindings.set(successor.binding_id, {
154
+ ...state.machineIdentityBindings.get(successor.binding_id),
155
+ rotated_from_binding_id: current.binding_id
156
+ });
157
+ state.machineIdentityBindings.set(bindingId, {
158
+ ...state.machineIdentityBindings.get(bindingId),
159
+ replaced_by_binding_id: successor.binding_id
160
+ });
161
+ return {
162
+ rotated_binding: buildIdentityBindingPublicView(state.machineIdentityBindings.get(bindingId)),
163
+ successor_identity_binding: buildIdentityBindingPublicView(state.machineIdentityBindings.get(successor.binding_id))
164
+ };
165
+ }
166
+
167
+ module.exports = {
168
+ createIdentityBinding,
169
+ listIdentityBindings,
170
+ getIdentityBinding,
171
+ getIdentityBindingRotationSummary,
172
+ renewIdentityBinding,
173
+ revokeIdentityBinding,
174
+ rotateIdentityBinding
175
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xytara",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Machine commerce SDK for discovery, quoting, execution, lifecycle inspection, and adapters.",
5
5
  "main": "index.js",
6
6
  "bin": {