xoonya 1.6.0 → 1.8.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
@@ -28,6 +28,18 @@ The current `1.6.0` companion slice adds guided default proof loops on top of th
28
28
 
29
29
  This keeps `xoonya` narrow while making the intended proof path easier to inspect alongside the newer guided transaction-loop work in `xytara`.
30
30
 
31
+ The current `1.7.0` companion slice adds a lightweight transaction proof-handoff surface:
32
+
33
+ - a transaction proof-handoff center that states the expected handoff contract
34
+ - a direct handoff run path that turns transaction-side proof handoff data into a proof-native bundle
35
+ - summary helpers that make the recommended proof follow-through explicit without widening proof scope
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
+
31
43
  ## Proof Model
32
44
 
33
45
  The primary proof model is layered:
@@ -80,6 +92,7 @@ The package quickstart demonstrates:
80
92
  - canonical receipt emission
81
93
  - proof bundle construction
82
94
  - proof bundle verification
95
+ - transaction proof-handoff follow-through
83
96
 
84
97
  ## Service Quickstart
85
98
 
@@ -106,6 +119,15 @@ Environment example:
106
119
  Primary proof-model routes:
107
120
 
108
121
  - `GET /health`
122
+ - `GET /v1/proof-center`
123
+ - `GET /v1/proof-center/summary`
124
+ - `GET /v1/proof-center/default-loops`
125
+ - `GET /v1/proof-center/default-loops/summary`
126
+ - `GET /v1/proof-center/default-loop`
127
+ - `POST /v1/proof-center/default-loops/run`
128
+ - `GET /v1/proof-center/transaction-handoff`
129
+ - `GET /v1/proof-center/transaction-handoff/summary`
130
+ - `POST /v1/proof-center/transaction-handoff/run`
109
131
  - `POST /v1/events/canonicalize`
110
132
  - `POST /v1/events/hash`
111
133
  - `POST /v1/receipts/emit`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xoonya",
3
- "version": "1.6.0",
3
+ "version": "1.8.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
@@ -877,6 +877,262 @@ function summarizeGuidedProofLoopBundle(bundle) {
877
877
  };
878
878
  }
879
879
 
880
+ function buildTransactionProofHandoffCenter() {
881
+ return {
882
+ ok: true,
883
+ brand: "xoonya",
884
+ product: "transaction proof handoff center",
885
+ supported_source_refs: [
886
+ "transaction.registry.anchor",
887
+ "transaction.runtime.consequence",
888
+ "transaction.trust.receipt",
889
+ "transaction.admission.settlement",
890
+ "transaction.job.commitment"
891
+ ],
892
+ recommended_loop: "default.proof.bundle.loop",
893
+ required_fields: ["transaction_id", "receipt_id", "proof_ref"],
894
+ optional_fields: ["source_ref", "task_refs", "delivery_count", "payment_ledger_count"]
895
+ };
896
+ }
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 summarizeTransactionProofHandoffCenter() {
915
+ const center = buildTransactionProofHandoffCenter();
916
+ return {
917
+ ok: true,
918
+ brand: center.brand,
919
+ product: center.product,
920
+ source_ref_count: Array.isArray(center.supported_source_refs) ? center.supported_source_refs.length : 0,
921
+ supported_source_refs: center.supported_source_refs,
922
+ required_field_count: Array.isArray(center.required_fields) ? center.required_fields.length : 0,
923
+ required_fields: center.required_fields,
924
+ recommended_loop: center.recommended_loop
925
+ };
926
+ }
927
+
928
+ function summarizeInteractionSpineProofHandoffCenter() {
929
+ const center = buildInteractionSpineProofHandoffCenter();
930
+ return {
931
+ ok: true,
932
+ brand: center.brand,
933
+ product: center.product,
934
+ source_ref_count: Array.isArray(center.supported_source_refs) ? center.supported_source_refs.length : 0,
935
+ supported_source_refs: center.supported_source_refs,
936
+ required_field_count: Array.isArray(center.required_fields) ? center.required_fields.length : 0,
937
+ required_fields: center.required_fields,
938
+ recommended_loop: center.recommended_loop
939
+ };
940
+ }
941
+
942
+ function canonicalizeTransactionProofHandoff(input) {
943
+ const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
944
+ const handoff = body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)
945
+ ? body.handoff_bundle
946
+ : body;
947
+ const transactionId = normalizeString(handoff.transaction_id);
948
+ const receiptId = normalizeString(handoff.receipt_id);
949
+ const proofRef = normalizeString(handoff.proof_ref);
950
+ if (!transactionId) throw new Error("handoff_bundle.transaction_id required");
951
+ if (!receiptId) throw new Error("handoff_bundle.receipt_id required");
952
+ if (!proofRef) throw new Error("handoff_bundle.proof_ref required");
953
+ const sourceRef = normalizeString(handoff.source_ref || body.source_ref || "transaction.proof_handoff");
954
+ const taskRefs = normalizeStringArray(handoff.task_refs, "handoff_bundle.task_refs") || [];
955
+ const deliveryCount = Number.isFinite(Number(handoff.delivery_count)) ? Number(handoff.delivery_count) : 0;
956
+ const paymentLedgerCount = Number.isFinite(Number(handoff.payment_ledger_count)) ? Number(handoff.payment_ledger_count) : 0;
957
+ return {
958
+ source_ref: sourceRef,
959
+ transaction_id: transactionId,
960
+ receipt_id: receiptId,
961
+ proof_ref: proofRef,
962
+ task_refs: taskRefs,
963
+ delivery_count: deliveryCount,
964
+ payment_ledger_count: paymentLedgerCount
965
+ };
966
+ }
967
+
968
+ function canonicalizeInteractionSpineProofHandoff(input) {
969
+ const handoff = canonicalizeTransactionProofHandoff(input);
970
+ const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
971
+ const sourceRef = normalizeString(handoff.source_ref);
972
+ const center = buildInteractionSpineProofHandoffCenter();
973
+ if (!center.supported_source_refs.includes(sourceRef)) {
974
+ throw new Error("handoff_bundle.source_ref must be a supported interaction spine ref");
975
+ }
976
+ const raw = body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)
977
+ ? body.handoff_bundle
978
+ : body;
979
+ const committedRef = normalizeString(raw.committed_ref);
980
+ const precommitPackRef = normalizeString(raw.precommit_pack_ref);
981
+ return {
982
+ ...handoff,
983
+ committed_ref: committedRef || null,
984
+ precommit_pack_ref: precommitPackRef || null
985
+ };
986
+ }
987
+
988
+ function buildTransactionProofHandoffEvent(input) {
989
+ const handoff = canonicalizeTransactionProofHandoff(input);
990
+ const eventHash = canonicalJsonSha256Hex({
991
+ source_ref: handoff.source_ref,
992
+ transaction_id: handoff.transaction_id,
993
+ receipt_id: handoff.receipt_id,
994
+ proof_ref: handoff.proof_ref,
995
+ task_refs: handoff.task_refs,
996
+ delivery_count: handoff.delivery_count,
997
+ payment_ledger_count: handoff.payment_ledger_count
998
+ });
999
+ return canonicalizeEvent({
1000
+ version: CANONICAL_EVENT_BUNDLE_VERSION,
1001
+ domain_id: "xytara.transaction_handoff",
1002
+ sequence: handoff.transaction_id,
1003
+ actor_id: "xytara.transaction_center",
1004
+ adapter_source: "xytara.proof_handoff",
1005
+ event_type: `${handoff.source_ref}.proof_handoff`,
1006
+ event_hash: eventHash,
1007
+ semantic_slots: handoff
1008
+ });
1009
+ }
1010
+
1011
+ function buildInteractionSpineProofHandoffEvent(input) {
1012
+ const handoff = canonicalizeInteractionSpineProofHandoff(input);
1013
+ const eventHash = canonicalJsonSha256Hex({
1014
+ source_ref: handoff.source_ref,
1015
+ transaction_id: handoff.transaction_id,
1016
+ receipt_id: handoff.receipt_id,
1017
+ proof_ref: handoff.proof_ref,
1018
+ task_refs: handoff.task_refs,
1019
+ delivery_count: handoff.delivery_count,
1020
+ payment_ledger_count: handoff.payment_ledger_count,
1021
+ committed_ref: handoff.committed_ref,
1022
+ precommit_pack_ref: handoff.precommit_pack_ref
1023
+ });
1024
+ return canonicalizeEvent({
1025
+ version: CANONICAL_EVENT_BUNDLE_VERSION,
1026
+ domain_id: "xytara.interaction_spine_handoff",
1027
+ sequence: handoff.transaction_id,
1028
+ actor_id: "xytara.interaction_spine",
1029
+ adapter_source: "xytara.spine_handoff",
1030
+ event_type: `${handoff.source_ref}.proof_handoff`,
1031
+ event_hash: eventHash,
1032
+ semantic_slots: handoff
1033
+ });
1034
+ }
1035
+
1036
+ function runTransactionProofHandoff(input) {
1037
+ const handoff = canonicalizeTransactionProofHandoff(input);
1038
+ const event = buildTransactionProofHandoffEvent(input);
1039
+ const options = input && input.options && typeof input.options === "object" && !Array.isArray(input.options)
1040
+ ? input.options
1041
+ : {};
1042
+ const receipt = emitReceipt(event, options);
1043
+ const proofBundle = buildProofBundle({
1044
+ ceb: event,
1045
+ receipt,
1046
+ evidence_refs: Array.isArray(input && input.evidence_refs) ? input.evidence_refs : [handoff.proof_ref],
1047
+ metadata: {
1048
+ handoff_kind: "transaction_proof_handoff",
1049
+ source_ref: handoff.source_ref
1050
+ }
1051
+ });
1052
+ return {
1053
+ ok: true,
1054
+ handoff,
1055
+ canonical_event: event,
1056
+ event_commitment: hashEvent(event),
1057
+ receipt,
1058
+ proof_bundle: proofBundle,
1059
+ bundle_verification: verifyProofBundle(proofBundle),
1060
+ recommended_loop: "default.proof.bundle.loop"
1061
+ };
1062
+ }
1063
+
1064
+ function runInteractionSpineProofHandoff(input) {
1065
+ const handoff = canonicalizeInteractionSpineProofHandoff(input);
1066
+ const event = buildInteractionSpineProofHandoffEvent(input);
1067
+ const options = input && input.options && typeof input.options === "object" && !Array.isArray(input.options)
1068
+ ? input.options
1069
+ : {};
1070
+ const receipt = emitReceipt(event, options);
1071
+ const proofBundle = buildProofBundle({
1072
+ ceb: event,
1073
+ receipt,
1074
+ evidence_refs: Array.isArray(input && input.evidence_refs) ? input.evidence_refs : [handoff.proof_ref],
1075
+ metadata: {
1076
+ handoff_kind: "interaction_spine_proof_handoff",
1077
+ source_ref: handoff.source_ref,
1078
+ committed_ref: handoff.committed_ref || null,
1079
+ precommit_pack_ref: handoff.precommit_pack_ref || null
1080
+ }
1081
+ });
1082
+ return {
1083
+ ok: true,
1084
+ handoff,
1085
+ canonical_event: event,
1086
+ event_commitment: hashEvent(event),
1087
+ receipt,
1088
+ proof_bundle: proofBundle,
1089
+ bundle_verification: verifyProofBundle(proofBundle),
1090
+ recommended_loop: "default.proof.bundle.loop"
1091
+ };
1092
+ }
1093
+
1094
+ function summarizeTransactionProofHandoff(bundle) {
1095
+ const item = bundle && typeof bundle === "object" ? bundle : {};
1096
+ const handoff = item.handoff && typeof item.handoff === "object" ? item.handoff : {};
1097
+ const receipt = item.receipt && typeof item.receipt === "object" ? item.receipt : {};
1098
+ const proofBundle = item.proof_bundle && typeof item.proof_bundle === "object" ? item.proof_bundle : {};
1099
+ const verification = item.bundle_verification && typeof item.bundle_verification === "object" ? item.bundle_verification : {};
1100
+ return {
1101
+ ok: item.ok === true,
1102
+ source_ref: handoff.source_ref || null,
1103
+ transaction_id: handoff.transaction_id || null,
1104
+ receipt_id: handoff.receipt_id || null,
1105
+ proof_ref: handoff.proof_ref || null,
1106
+ task_ref_count: Array.isArray(handoff.task_refs) ? handoff.task_refs.length : 0,
1107
+ proof_bundle_version: proofBundle.version || null,
1108
+ emitted_receipt_id: receipt.receipt_id || null,
1109
+ bundle_valid: verification.valid === true,
1110
+ recommended_loop: item.recommended_loop || null
1111
+ };
1112
+ }
1113
+
1114
+ function summarizeInteractionSpineProofHandoff(bundle) {
1115
+ const item = bundle && typeof bundle === "object" ? bundle : {};
1116
+ const handoff = item.handoff && typeof item.handoff === "object" ? item.handoff : {};
1117
+ const receipt = item.receipt && typeof item.receipt === "object" ? item.receipt : {};
1118
+ const proofBundle = item.proof_bundle && typeof item.proof_bundle === "object" ? item.proof_bundle : {};
1119
+ const verification = item.bundle_verification && typeof item.bundle_verification === "object" ? item.bundle_verification : {};
1120
+ return {
1121
+ ok: item.ok === true,
1122
+ source_ref: handoff.source_ref || null,
1123
+ transaction_id: handoff.transaction_id || null,
1124
+ receipt_id: handoff.receipt_id || null,
1125
+ proof_ref: handoff.proof_ref || null,
1126
+ committed_ref: handoff.committed_ref || null,
1127
+ precommit_pack_ref: handoff.precommit_pack_ref || null,
1128
+ task_ref_count: Array.isArray(handoff.task_refs) ? handoff.task_refs.length : 0,
1129
+ proof_bundle_version: proofBundle.version || null,
1130
+ emitted_receipt_id: receipt.receipt_id || null,
1131
+ bundle_valid: verification.valid === true,
1132
+ recommended_loop: item.recommended_loop || null
1133
+ };
1134
+ }
1135
+
880
1136
  function runDefaultProofLoop(loopRef, input) {
881
1137
  const loop = getDefaultProofLoop(loopRef);
882
1138
  if (!loop) {
@@ -920,11 +1176,23 @@ module.exports = {
920
1176
  buildDefaultProofCenter,
921
1177
  buildDefaultProofLoopCatalog,
922
1178
  buildDefaultProofLoops,
1179
+ buildInteractionSpineProofHandoffCenter,
1180
+ buildTransactionProofHandoffCenter,
1181
+ buildInteractionSpineProofHandoffEvent,
1182
+ buildTransactionProofHandoffEvent,
1183
+ canonicalizeInteractionSpineProofHandoff,
923
1184
  getDefaultProofLoop,
1185
+ canonicalizeTransactionProofHandoff,
924
1186
  runDefaultProofLoop,
1187
+ runInteractionSpineProofHandoff,
1188
+ runTransactionProofHandoff,
925
1189
  summarizeDefaultProofCenter,
926
1190
  summarizeDefaultProofLoops,
927
1191
  summarizeGuidedProofLoopBundle,
1192
+ summarizeInteractionSpineProofHandoff,
1193
+ summarizeInteractionSpineProofHandoffCenter,
1194
+ summarizeTransactionProofHandoff,
1195
+ summarizeTransactionProofHandoffCenter,
928
1196
  canonicalizeEvent,
929
1197
  hashEvent,
930
1198
  emitReceipt,
package/server.js CHANGED
@@ -97,6 +97,26 @@ async function routeRequest(req, res) {
97
97
  return;
98
98
  }
99
99
 
100
+ if (req.method === 'GET' && url.pathname === '/v1/proof-center/transaction-handoff') {
101
+ sendJson(res, 200, proofSdk.buildTransactionProofHandoffCenter());
102
+ return;
103
+ }
104
+
105
+ if (req.method === 'GET' && url.pathname === '/v1/proof-center/transaction-handoff/summary') {
106
+ sendJson(res, 200, proofSdk.summarizeTransactionProofHandoffCenter());
107
+ return;
108
+ }
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
+
100
120
  if (req.method === 'GET' && url.pathname === '/v1/proof-center/default-loop') {
101
121
  const loop = proofSdk.getDefaultProofLoop(url.searchParams.get('ref'));
102
122
  if (!loop) {
@@ -119,6 +139,28 @@ async function routeRequest(req, res) {
119
139
  return;
120
140
  }
121
141
 
142
+ if (req.method === 'POST' && url.pathname === '/v1/proof-center/transaction-handoff/run') {
143
+ try {
144
+ const body = await readJsonBody(req);
145
+ const result = proofSdk.runTransactionProofHandoff(body);
146
+ sendJson(res, 200, result);
147
+ } catch (error) {
148
+ sendJson(res, 400, { ok: false, reason: error.message });
149
+ }
150
+ return;
151
+ }
152
+
153
+ if (req.method === 'POST' && url.pathname === '/v1/proof-center/interaction-spine-handoff/run') {
154
+ try {
155
+ const body = await readJsonBody(req);
156
+ const result = proofSdk.runInteractionSpineProofHandoff(body);
157
+ sendJson(res, 200, result);
158
+ } catch (error) {
159
+ sendJson(res, 400, { ok: false, reason: error.message });
160
+ }
161
+ return;
162
+ }
163
+
122
164
  if (req.method === 'POST' && url.pathname === '/v1/receipts/verify') {
123
165
  try {
124
166
  const body = await readJsonBody(req);