xoonya 1.7.0 → 1.9.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/README.md CHANGED
@@ -34,6 +34,12 @@ The current `1.7.0` companion slice adds a lightweight transaction proof-handoff
34
34
  - a direct handoff run path that turns transaction-side proof handoff data into a proof-native bundle
35
35
  - summary helpers that make the recommended proof follow-through explicit without widening proof scope
36
36
 
37
+ The current `1.8.0` companion slice extends that same proof-side carry to richer grouped interaction spine handoffs:
38
+
39
+ - an interaction-spine handoff center and summary surface
40
+ - a direct interaction-spine handoff run path for composed transaction spines
41
+ - proof-side summaries that preserve both pre-commit and committed-ref context without importing commerce logic
42
+
37
43
  ## Proof Model
38
44
 
39
45
  The primary proof model is layered:
@@ -122,6 +128,9 @@ Primary proof-model routes:
122
128
  - `GET /v1/proof-center/transaction-handoff`
123
129
  - `GET /v1/proof-center/transaction-handoff/summary`
124
130
  - `POST /v1/proof-center/transaction-handoff/run`
131
+ - `GET /v1/proof-center/result-package-handoff`
132
+ - `GET /v1/proof-center/result-package-handoff/summary`
133
+ - `POST /v1/proof-center/result-package-handoff/run`
125
134
  - `POST /v1/events/canonicalize`
126
135
  - `POST /v1/events/hash`
127
136
  - `POST /v1/receipts/emit`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xoonya",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Deterministic proof SDK for canonical events, receipts, proof bundles, and verification.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
package/proof_sdk.js CHANGED
@@ -895,6 +895,48 @@ function buildTransactionProofHandoffCenter() {
895
895
  };
896
896
  }
897
897
 
898
+ function buildInteractionSpineProofHandoffCenter() {
899
+ return {
900
+ ok: true,
901
+ brand: "xoonya",
902
+ product: "interaction spine proof handoff center",
903
+ supported_source_refs: [
904
+ "spine.a2a.settlement",
905
+ "spine.a2c.tooling",
906
+ "spine.job.commitment"
907
+ ],
908
+ required_fields: ["transaction_id", "receipt_id", "proof_ref", "source_ref"],
909
+ optional_fields: ["task_refs", "delivery_count", "payment_ledger_count", "committed_ref", "precommit_pack_ref"],
910
+ recommended_loop: "default.proof.bundle.loop"
911
+ };
912
+ }
913
+
914
+ function buildInteractionResultPackageHandoffCenter() {
915
+ return {
916
+ ok: true,
917
+ brand: "xoonya",
918
+ product: "interaction result package handoff center",
919
+ supported_source_refs: [
920
+ "result.spine.a2a.settlement",
921
+ "result.spine.a2c.tooling",
922
+ "result.spine.job.commitment"
923
+ ],
924
+ required_fields: ["result_package_ref", "source_ref", "transaction_id", "receipt_id", "proof_ref"],
925
+ optional_fields: [
926
+ "committed_ref",
927
+ "precommit_pack_ref",
928
+ "payment_protocol",
929
+ "settlement_mode",
930
+ "treasury_destination_id",
931
+ "task_refs",
932
+ "delivery_count",
933
+ "payment_ledger_count",
934
+ "seam_layers"
935
+ ],
936
+ recommended_loop: "default.proof.bundle.loop"
937
+ };
938
+ }
939
+
898
940
  function summarizeTransactionProofHandoffCenter() {
899
941
  const center = buildTransactionProofHandoffCenter();
900
942
  return {
@@ -909,6 +951,34 @@ function summarizeTransactionProofHandoffCenter() {
909
951
  };
910
952
  }
911
953
 
954
+ function summarizeInteractionSpineProofHandoffCenter() {
955
+ const center = buildInteractionSpineProofHandoffCenter();
956
+ return {
957
+ ok: true,
958
+ brand: center.brand,
959
+ product: center.product,
960
+ source_ref_count: Array.isArray(center.supported_source_refs) ? center.supported_source_refs.length : 0,
961
+ supported_source_refs: center.supported_source_refs,
962
+ required_field_count: Array.isArray(center.required_fields) ? center.required_fields.length : 0,
963
+ required_fields: center.required_fields,
964
+ recommended_loop: center.recommended_loop
965
+ };
966
+ }
967
+
968
+ function summarizeInteractionResultPackageHandoffCenter() {
969
+ const center = buildInteractionResultPackageHandoffCenter();
970
+ return {
971
+ ok: true,
972
+ brand: center.brand,
973
+ product: center.product,
974
+ source_ref_count: Array.isArray(center.supported_source_refs) ? center.supported_source_refs.length : 0,
975
+ supported_source_refs: center.supported_source_refs,
976
+ required_field_count: Array.isArray(center.required_fields) ? center.required_fields.length : 0,
977
+ required_fields: center.required_fields,
978
+ recommended_loop: center.recommended_loop
979
+ };
980
+ }
981
+
912
982
  function canonicalizeTransactionProofHandoff(input) {
913
983
  const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
914
984
  const handoff = body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)
@@ -935,6 +1005,67 @@ function canonicalizeTransactionProofHandoff(input) {
935
1005
  };
936
1006
  }
937
1007
 
1008
+ function canonicalizeInteractionSpineProofHandoff(input) {
1009
+ const handoff = canonicalizeTransactionProofHandoff(input);
1010
+ const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
1011
+ const sourceRef = normalizeString(handoff.source_ref);
1012
+ const center = buildInteractionSpineProofHandoffCenter();
1013
+ if (!center.supported_source_refs.includes(sourceRef)) {
1014
+ throw new Error("handoff_bundle.source_ref must be a supported interaction spine ref");
1015
+ }
1016
+ const raw = body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)
1017
+ ? body.handoff_bundle
1018
+ : body;
1019
+ const committedRef = normalizeString(raw.committed_ref);
1020
+ const precommitPackRef = normalizeString(raw.precommit_pack_ref);
1021
+ return {
1022
+ ...handoff,
1023
+ committed_ref: committedRef || null,
1024
+ precommit_pack_ref: precommitPackRef || null
1025
+ };
1026
+ }
1027
+
1028
+ function canonicalizeInteractionResultPackageHandoff(input) {
1029
+ const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
1030
+ const handoff = body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)
1031
+ ? body.handoff_bundle
1032
+ : body;
1033
+ const resultPackageRef = normalizeString(handoff.result_package_ref);
1034
+ if (!resultPackageRef) throw new Error("handoff_bundle.result_package_ref required");
1035
+ const center = buildInteractionResultPackageHandoffCenter();
1036
+ if (!center.supported_source_refs.includes(resultPackageRef)) {
1037
+ throw new Error("handoff_bundle.result_package_ref must be a supported interaction result package ref");
1038
+ }
1039
+ const sourceRef = normalizeString(handoff.source_ref);
1040
+ if (!sourceRef) throw new Error("handoff_bundle.source_ref required");
1041
+ const transactionId = normalizeString(handoff.transaction_id);
1042
+ const receiptId = normalizeString(handoff.receipt_id);
1043
+ const proofRef = normalizeString(handoff.proof_ref);
1044
+ if (!transactionId) throw new Error("handoff_bundle.transaction_id required");
1045
+ if (!receiptId) throw new Error("handoff_bundle.receipt_id required");
1046
+ if (!proofRef) throw new Error("handoff_bundle.proof_ref required");
1047
+ const taskRefs = normalizeStringArray(handoff.task_refs, "handoff_bundle.task_refs") || [];
1048
+ const seamLayers = normalizeStringArray(handoff.seam_layers, "handoff_bundle.seam_layers") || [];
1049
+ const deliveryCount = Number.isFinite(Number(handoff.delivery_count)) ? Number(handoff.delivery_count) : 0;
1050
+ const paymentLedgerCount = Number.isFinite(Number(handoff.payment_ledger_count)) ? Number(handoff.payment_ledger_count) : 0;
1051
+ return {
1052
+ result_package_ref: resultPackageRef,
1053
+ source_ref: sourceRef,
1054
+ transaction_id: transactionId,
1055
+ receipt_id: receiptId,
1056
+ proof_ref: proofRef,
1057
+ committed_ref: normalizeString(handoff.committed_ref) || null,
1058
+ precommit_pack_ref: normalizeString(handoff.precommit_pack_ref) || null,
1059
+ payment_protocol: normalizeString(handoff.payment_protocol) || null,
1060
+ settlement_mode: normalizeString(handoff.settlement_mode) || null,
1061
+ treasury_destination_id: normalizeString(handoff.treasury_destination_id) || null,
1062
+ task_refs: taskRefs,
1063
+ delivery_count: deliveryCount,
1064
+ payment_ledger_count: paymentLedgerCount,
1065
+ seam_layers: seamLayers
1066
+ };
1067
+ }
1068
+
938
1069
  function buildTransactionProofHandoffEvent(input) {
939
1070
  const handoff = canonicalizeTransactionProofHandoff(input);
940
1071
  const eventHash = canonicalJsonSha256Hex({
@@ -958,6 +1089,61 @@ function buildTransactionProofHandoffEvent(input) {
958
1089
  });
959
1090
  }
960
1091
 
1092
+ function buildInteractionSpineProofHandoffEvent(input) {
1093
+ const handoff = canonicalizeInteractionSpineProofHandoff(input);
1094
+ const eventHash = canonicalJsonSha256Hex({
1095
+ source_ref: handoff.source_ref,
1096
+ transaction_id: handoff.transaction_id,
1097
+ receipt_id: handoff.receipt_id,
1098
+ proof_ref: handoff.proof_ref,
1099
+ task_refs: handoff.task_refs,
1100
+ delivery_count: handoff.delivery_count,
1101
+ payment_ledger_count: handoff.payment_ledger_count,
1102
+ committed_ref: handoff.committed_ref,
1103
+ precommit_pack_ref: handoff.precommit_pack_ref
1104
+ });
1105
+ return canonicalizeEvent({
1106
+ version: CANONICAL_EVENT_BUNDLE_VERSION,
1107
+ domain_id: "xytara.interaction_spine_handoff",
1108
+ sequence: handoff.transaction_id,
1109
+ actor_id: "xytara.interaction_spine",
1110
+ adapter_source: "xytara.spine_handoff",
1111
+ event_type: `${handoff.source_ref}.proof_handoff`,
1112
+ event_hash: eventHash,
1113
+ semantic_slots: handoff
1114
+ });
1115
+ }
1116
+
1117
+ function buildInteractionResultPackageHandoffEvent(input) {
1118
+ const handoff = canonicalizeInteractionResultPackageHandoff(input);
1119
+ const eventHash = canonicalJsonSha256Hex({
1120
+ result_package_ref: handoff.result_package_ref,
1121
+ source_ref: handoff.source_ref,
1122
+ transaction_id: handoff.transaction_id,
1123
+ receipt_id: handoff.receipt_id,
1124
+ proof_ref: handoff.proof_ref,
1125
+ committed_ref: handoff.committed_ref,
1126
+ precommit_pack_ref: handoff.precommit_pack_ref,
1127
+ payment_protocol: handoff.payment_protocol,
1128
+ settlement_mode: handoff.settlement_mode,
1129
+ treasury_destination_id: handoff.treasury_destination_id,
1130
+ task_refs: handoff.task_refs,
1131
+ delivery_count: handoff.delivery_count,
1132
+ payment_ledger_count: handoff.payment_ledger_count,
1133
+ seam_layers: handoff.seam_layers
1134
+ });
1135
+ return canonicalizeEvent({
1136
+ version: CANONICAL_EVENT_BUNDLE_VERSION,
1137
+ domain_id: "xytara.interaction_result_package_handoff",
1138
+ sequence: handoff.transaction_id,
1139
+ actor_id: "xytara.result_package",
1140
+ adapter_source: "xytara.result_package_handoff",
1141
+ event_type: `${handoff.result_package_ref}.proof_handoff`,
1142
+ event_hash: eventHash,
1143
+ semantic_slots: handoff
1144
+ });
1145
+ }
1146
+
961
1147
  function runTransactionProofHandoff(input) {
962
1148
  const handoff = canonicalizeTransactionProofHandoff(input);
963
1149
  const event = buildTransactionProofHandoffEvent(input);
@@ -986,6 +1172,67 @@ function runTransactionProofHandoff(input) {
986
1172
  };
987
1173
  }
988
1174
 
1175
+ function runInteractionSpineProofHandoff(input) {
1176
+ const handoff = canonicalizeInteractionSpineProofHandoff(input);
1177
+ const event = buildInteractionSpineProofHandoffEvent(input);
1178
+ const options = input && input.options && typeof input.options === "object" && !Array.isArray(input.options)
1179
+ ? input.options
1180
+ : {};
1181
+ const receipt = emitReceipt(event, options);
1182
+ const proofBundle = buildProofBundle({
1183
+ ceb: event,
1184
+ receipt,
1185
+ evidence_refs: Array.isArray(input && input.evidence_refs) ? input.evidence_refs : [handoff.proof_ref],
1186
+ metadata: {
1187
+ handoff_kind: "interaction_spine_proof_handoff",
1188
+ source_ref: handoff.source_ref,
1189
+ committed_ref: handoff.committed_ref || null,
1190
+ precommit_pack_ref: handoff.precommit_pack_ref || null
1191
+ }
1192
+ });
1193
+ return {
1194
+ ok: true,
1195
+ handoff,
1196
+ canonical_event: event,
1197
+ event_commitment: hashEvent(event),
1198
+ receipt,
1199
+ proof_bundle: proofBundle,
1200
+ bundle_verification: verifyProofBundle(proofBundle),
1201
+ recommended_loop: "default.proof.bundle.loop"
1202
+ };
1203
+ }
1204
+
1205
+ function runInteractionResultPackageHandoff(input) {
1206
+ const handoff = canonicalizeInteractionResultPackageHandoff(input);
1207
+ const event = buildInteractionResultPackageHandoffEvent(input);
1208
+ const options = input && input.options && typeof input.options === "object" && !Array.isArray(input.options)
1209
+ ? input.options
1210
+ : {};
1211
+ const receipt = emitReceipt(event, options);
1212
+ const proofBundle = buildProofBundle({
1213
+ ceb: event,
1214
+ receipt,
1215
+ evidence_refs: Array.isArray(input && input.evidence_refs) ? input.evidence_refs : [handoff.proof_ref],
1216
+ metadata: {
1217
+ handoff_kind: "interaction_result_package_handoff",
1218
+ result_package_ref: handoff.result_package_ref,
1219
+ source_ref: handoff.source_ref,
1220
+ committed_ref: handoff.committed_ref || null,
1221
+ precommit_pack_ref: handoff.precommit_pack_ref || null
1222
+ }
1223
+ });
1224
+ return {
1225
+ ok: true,
1226
+ handoff,
1227
+ canonical_event: event,
1228
+ event_commitment: hashEvent(event),
1229
+ receipt,
1230
+ proof_bundle: proofBundle,
1231
+ bundle_verification: verifyProofBundle(proofBundle),
1232
+ recommended_loop: "default.proof.bundle.loop"
1233
+ };
1234
+ }
1235
+
989
1236
  function summarizeTransactionProofHandoff(bundle) {
990
1237
  const item = bundle && typeof bundle === "object" ? bundle : {};
991
1238
  const handoff = item.handoff && typeof item.handoff === "object" ? item.handoff : {};
@@ -1006,6 +1253,52 @@ function summarizeTransactionProofHandoff(bundle) {
1006
1253
  };
1007
1254
  }
1008
1255
 
1256
+ function summarizeInteractionSpineProofHandoff(bundle) {
1257
+ const item = bundle && typeof bundle === "object" ? bundle : {};
1258
+ const handoff = item.handoff && typeof item.handoff === "object" ? item.handoff : {};
1259
+ const receipt = item.receipt && typeof item.receipt === "object" ? item.receipt : {};
1260
+ const proofBundle = item.proof_bundle && typeof item.proof_bundle === "object" ? item.proof_bundle : {};
1261
+ const verification = item.bundle_verification && typeof item.bundle_verification === "object" ? item.bundle_verification : {};
1262
+ return {
1263
+ ok: item.ok === true,
1264
+ source_ref: handoff.source_ref || null,
1265
+ transaction_id: handoff.transaction_id || null,
1266
+ receipt_id: handoff.receipt_id || null,
1267
+ proof_ref: handoff.proof_ref || null,
1268
+ committed_ref: handoff.committed_ref || null,
1269
+ precommit_pack_ref: handoff.precommit_pack_ref || null,
1270
+ task_ref_count: Array.isArray(handoff.task_refs) ? handoff.task_refs.length : 0,
1271
+ proof_bundle_version: proofBundle.version || null,
1272
+ emitted_receipt_id: receipt.receipt_id || null,
1273
+ bundle_valid: verification.valid === true,
1274
+ recommended_loop: item.recommended_loop || null
1275
+ };
1276
+ }
1277
+
1278
+ function summarizeInteractionResultPackageHandoff(bundle) {
1279
+ const item = bundle && typeof bundle === "object" ? bundle : {};
1280
+ const handoff = item.handoff && typeof item.handoff === "object" ? item.handoff : {};
1281
+ const receipt = item.receipt && typeof item.receipt === "object" ? item.receipt : {};
1282
+ const proofBundle = item.proof_bundle && typeof item.proof_bundle === "object" ? item.proof_bundle : {};
1283
+ const verification = item.bundle_verification && typeof item.bundle_verification === "object" ? item.bundle_verification : {};
1284
+ return {
1285
+ ok: item.ok === true,
1286
+ result_package_ref: handoff.result_package_ref || null,
1287
+ source_ref: handoff.source_ref || null,
1288
+ transaction_id: handoff.transaction_id || null,
1289
+ receipt_id: handoff.receipt_id || null,
1290
+ proof_ref: handoff.proof_ref || null,
1291
+ committed_ref: handoff.committed_ref || null,
1292
+ precommit_pack_ref: handoff.precommit_pack_ref || null,
1293
+ seam_layer_count: Array.isArray(handoff.seam_layers) ? handoff.seam_layers.length : 0,
1294
+ task_ref_count: Array.isArray(handoff.task_refs) ? handoff.task_refs.length : 0,
1295
+ proof_bundle_version: proofBundle.version || null,
1296
+ emitted_receipt_id: receipt.receipt_id || null,
1297
+ bundle_valid: verification.valid === true,
1298
+ recommended_loop: item.recommended_loop || null
1299
+ };
1300
+ }
1301
+
1009
1302
  function runDefaultProofLoop(loopRef, input) {
1010
1303
  const loop = getDefaultProofLoop(loopRef);
1011
1304
  if (!loop) {
@@ -1049,15 +1342,27 @@ module.exports = {
1049
1342
  buildDefaultProofCenter,
1050
1343
  buildDefaultProofLoopCatalog,
1051
1344
  buildDefaultProofLoops,
1345
+ buildInteractionResultPackageHandoffCenter,
1346
+ buildInteractionSpineProofHandoffCenter,
1052
1347
  buildTransactionProofHandoffCenter,
1348
+ buildInteractionResultPackageHandoffEvent,
1349
+ buildInteractionSpineProofHandoffEvent,
1053
1350
  buildTransactionProofHandoffEvent,
1351
+ canonicalizeInteractionResultPackageHandoff,
1352
+ canonicalizeInteractionSpineProofHandoff,
1054
1353
  getDefaultProofLoop,
1055
1354
  canonicalizeTransactionProofHandoff,
1056
1355
  runDefaultProofLoop,
1356
+ runInteractionResultPackageHandoff,
1357
+ runInteractionSpineProofHandoff,
1057
1358
  runTransactionProofHandoff,
1058
1359
  summarizeDefaultProofCenter,
1059
1360
  summarizeDefaultProofLoops,
1060
1361
  summarizeGuidedProofLoopBundle,
1362
+ summarizeInteractionResultPackageHandoff,
1363
+ summarizeInteractionResultPackageHandoffCenter,
1364
+ summarizeInteractionSpineProofHandoff,
1365
+ summarizeInteractionSpineProofHandoffCenter,
1061
1366
  summarizeTransactionProofHandoff,
1062
1367
  summarizeTransactionProofHandoffCenter,
1063
1368
  canonicalizeEvent,
package/server.js CHANGED
@@ -107,6 +107,26 @@ async function routeRequest(req, res) {
107
107
  return;
108
108
  }
109
109
 
110
+ if (req.method === 'GET' && url.pathname === '/v1/proof-center/interaction-spine-handoff') {
111
+ sendJson(res, 200, proofSdk.buildInteractionSpineProofHandoffCenter());
112
+ return;
113
+ }
114
+
115
+ if (req.method === 'GET' && url.pathname === '/v1/proof-center/interaction-spine-handoff/summary') {
116
+ sendJson(res, 200, proofSdk.summarizeInteractionSpineProofHandoffCenter());
117
+ return;
118
+ }
119
+
120
+ if (req.method === 'GET' && url.pathname === '/v1/proof-center/result-package-handoff') {
121
+ sendJson(res, 200, proofSdk.buildInteractionResultPackageHandoffCenter());
122
+ return;
123
+ }
124
+
125
+ if (req.method === 'GET' && url.pathname === '/v1/proof-center/result-package-handoff/summary') {
126
+ sendJson(res, 200, proofSdk.summarizeInteractionResultPackageHandoffCenter());
127
+ return;
128
+ }
129
+
110
130
  if (req.method === 'GET' && url.pathname === '/v1/proof-center/default-loop') {
111
131
  const loop = proofSdk.getDefaultProofLoop(url.searchParams.get('ref'));
112
132
  if (!loop) {
@@ -140,6 +160,28 @@ async function routeRequest(req, res) {
140
160
  return;
141
161
  }
142
162
 
163
+ if (req.method === 'POST' && url.pathname === '/v1/proof-center/interaction-spine-handoff/run') {
164
+ try {
165
+ const body = await readJsonBody(req);
166
+ const result = proofSdk.runInteractionSpineProofHandoff(body);
167
+ sendJson(res, 200, result);
168
+ } catch (error) {
169
+ sendJson(res, 400, { ok: false, reason: error.message });
170
+ }
171
+ return;
172
+ }
173
+
174
+ if (req.method === 'POST' && url.pathname === '/v1/proof-center/result-package-handoff/run') {
175
+ try {
176
+ const body = await readJsonBody(req);
177
+ const result = proofSdk.runInteractionResultPackageHandoff(body);
178
+ sendJson(res, 200, result);
179
+ } catch (error) {
180
+ sendJson(res, 400, { ok: false, reason: error.message });
181
+ }
182
+ return;
183
+ }
184
+
143
185
  if (req.method === 'POST' && url.pathname === '/v1/receipts/verify') {
144
186
  try {
145
187
  const body = await readJsonBody(req);