xoonya 1.6.0 → 1.7.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 +16 -0
- package/package.json +1 -1
- package/proof_sdk.js +135 -0
- package/server.js +21 -0
package/README.md
CHANGED
|
@@ -28,6 +28,12 @@ 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
|
+
|
|
31
37
|
## Proof Model
|
|
32
38
|
|
|
33
39
|
The primary proof model is layered:
|
|
@@ -80,6 +86,7 @@ The package quickstart demonstrates:
|
|
|
80
86
|
- canonical receipt emission
|
|
81
87
|
- proof bundle construction
|
|
82
88
|
- proof bundle verification
|
|
89
|
+
- transaction proof-handoff follow-through
|
|
83
90
|
|
|
84
91
|
## Service Quickstart
|
|
85
92
|
|
|
@@ -106,6 +113,15 @@ Environment example:
|
|
|
106
113
|
Primary proof-model routes:
|
|
107
114
|
|
|
108
115
|
- `GET /health`
|
|
116
|
+
- `GET /v1/proof-center`
|
|
117
|
+
- `GET /v1/proof-center/summary`
|
|
118
|
+
- `GET /v1/proof-center/default-loops`
|
|
119
|
+
- `GET /v1/proof-center/default-loops/summary`
|
|
120
|
+
- `GET /v1/proof-center/default-loop`
|
|
121
|
+
- `POST /v1/proof-center/default-loops/run`
|
|
122
|
+
- `GET /v1/proof-center/transaction-handoff`
|
|
123
|
+
- `GET /v1/proof-center/transaction-handoff/summary`
|
|
124
|
+
- `POST /v1/proof-center/transaction-handoff/run`
|
|
109
125
|
- `POST /v1/events/canonicalize`
|
|
110
126
|
- `POST /v1/events/hash`
|
|
111
127
|
- `POST /v1/receipts/emit`
|
package/package.json
CHANGED
package/proof_sdk.js
CHANGED
|
@@ -877,6 +877,135 @@ 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 summarizeTransactionProofHandoffCenter() {
|
|
899
|
+
const center = buildTransactionProofHandoffCenter();
|
|
900
|
+
return {
|
|
901
|
+
ok: true,
|
|
902
|
+
brand: center.brand,
|
|
903
|
+
product: center.product,
|
|
904
|
+
source_ref_count: Array.isArray(center.supported_source_refs) ? center.supported_source_refs.length : 0,
|
|
905
|
+
supported_source_refs: center.supported_source_refs,
|
|
906
|
+
required_field_count: Array.isArray(center.required_fields) ? center.required_fields.length : 0,
|
|
907
|
+
required_fields: center.required_fields,
|
|
908
|
+
recommended_loop: center.recommended_loop
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
function canonicalizeTransactionProofHandoff(input) {
|
|
913
|
+
const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
914
|
+
const handoff = body.handoff_bundle && typeof body.handoff_bundle === "object" && !Array.isArray(body.handoff_bundle)
|
|
915
|
+
? body.handoff_bundle
|
|
916
|
+
: body;
|
|
917
|
+
const transactionId = normalizeString(handoff.transaction_id);
|
|
918
|
+
const receiptId = normalizeString(handoff.receipt_id);
|
|
919
|
+
const proofRef = normalizeString(handoff.proof_ref);
|
|
920
|
+
if (!transactionId) throw new Error("handoff_bundle.transaction_id required");
|
|
921
|
+
if (!receiptId) throw new Error("handoff_bundle.receipt_id required");
|
|
922
|
+
if (!proofRef) throw new Error("handoff_bundle.proof_ref required");
|
|
923
|
+
const sourceRef = normalizeString(handoff.source_ref || body.source_ref || "transaction.proof_handoff");
|
|
924
|
+
const taskRefs = normalizeStringArray(handoff.task_refs, "handoff_bundle.task_refs") || [];
|
|
925
|
+
const deliveryCount = Number.isFinite(Number(handoff.delivery_count)) ? Number(handoff.delivery_count) : 0;
|
|
926
|
+
const paymentLedgerCount = Number.isFinite(Number(handoff.payment_ledger_count)) ? Number(handoff.payment_ledger_count) : 0;
|
|
927
|
+
return {
|
|
928
|
+
source_ref: sourceRef,
|
|
929
|
+
transaction_id: transactionId,
|
|
930
|
+
receipt_id: receiptId,
|
|
931
|
+
proof_ref: proofRef,
|
|
932
|
+
task_refs: taskRefs,
|
|
933
|
+
delivery_count: deliveryCount,
|
|
934
|
+
payment_ledger_count: paymentLedgerCount
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
function buildTransactionProofHandoffEvent(input) {
|
|
939
|
+
const handoff = canonicalizeTransactionProofHandoff(input);
|
|
940
|
+
const eventHash = canonicalJsonSha256Hex({
|
|
941
|
+
source_ref: handoff.source_ref,
|
|
942
|
+
transaction_id: handoff.transaction_id,
|
|
943
|
+
receipt_id: handoff.receipt_id,
|
|
944
|
+
proof_ref: handoff.proof_ref,
|
|
945
|
+
task_refs: handoff.task_refs,
|
|
946
|
+
delivery_count: handoff.delivery_count,
|
|
947
|
+
payment_ledger_count: handoff.payment_ledger_count
|
|
948
|
+
});
|
|
949
|
+
return canonicalizeEvent({
|
|
950
|
+
version: CANONICAL_EVENT_BUNDLE_VERSION,
|
|
951
|
+
domain_id: "xytara.transaction_handoff",
|
|
952
|
+
sequence: handoff.transaction_id,
|
|
953
|
+
actor_id: "xytara.transaction_center",
|
|
954
|
+
adapter_source: "xytara.proof_handoff",
|
|
955
|
+
event_type: `${handoff.source_ref}.proof_handoff`,
|
|
956
|
+
event_hash: eventHash,
|
|
957
|
+
semantic_slots: handoff
|
|
958
|
+
});
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
function runTransactionProofHandoff(input) {
|
|
962
|
+
const handoff = canonicalizeTransactionProofHandoff(input);
|
|
963
|
+
const event = buildTransactionProofHandoffEvent(input);
|
|
964
|
+
const options = input && input.options && typeof input.options === "object" && !Array.isArray(input.options)
|
|
965
|
+
? input.options
|
|
966
|
+
: {};
|
|
967
|
+
const receipt = emitReceipt(event, options);
|
|
968
|
+
const proofBundle = buildProofBundle({
|
|
969
|
+
ceb: event,
|
|
970
|
+
receipt,
|
|
971
|
+
evidence_refs: Array.isArray(input && input.evidence_refs) ? input.evidence_refs : [handoff.proof_ref],
|
|
972
|
+
metadata: {
|
|
973
|
+
handoff_kind: "transaction_proof_handoff",
|
|
974
|
+
source_ref: handoff.source_ref
|
|
975
|
+
}
|
|
976
|
+
});
|
|
977
|
+
return {
|
|
978
|
+
ok: true,
|
|
979
|
+
handoff,
|
|
980
|
+
canonical_event: event,
|
|
981
|
+
event_commitment: hashEvent(event),
|
|
982
|
+
receipt,
|
|
983
|
+
proof_bundle: proofBundle,
|
|
984
|
+
bundle_verification: verifyProofBundle(proofBundle),
|
|
985
|
+
recommended_loop: "default.proof.bundle.loop"
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
function summarizeTransactionProofHandoff(bundle) {
|
|
990
|
+
const item = bundle && typeof bundle === "object" ? bundle : {};
|
|
991
|
+
const handoff = item.handoff && typeof item.handoff === "object" ? item.handoff : {};
|
|
992
|
+
const receipt = item.receipt && typeof item.receipt === "object" ? item.receipt : {};
|
|
993
|
+
const proofBundle = item.proof_bundle && typeof item.proof_bundle === "object" ? item.proof_bundle : {};
|
|
994
|
+
const verification = item.bundle_verification && typeof item.bundle_verification === "object" ? item.bundle_verification : {};
|
|
995
|
+
return {
|
|
996
|
+
ok: item.ok === true,
|
|
997
|
+
source_ref: handoff.source_ref || null,
|
|
998
|
+
transaction_id: handoff.transaction_id || null,
|
|
999
|
+
receipt_id: handoff.receipt_id || null,
|
|
1000
|
+
proof_ref: handoff.proof_ref || null,
|
|
1001
|
+
task_ref_count: Array.isArray(handoff.task_refs) ? handoff.task_refs.length : 0,
|
|
1002
|
+
proof_bundle_version: proofBundle.version || null,
|
|
1003
|
+
emitted_receipt_id: receipt.receipt_id || null,
|
|
1004
|
+
bundle_valid: verification.valid === true,
|
|
1005
|
+
recommended_loop: item.recommended_loop || null
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
|
|
880
1009
|
function runDefaultProofLoop(loopRef, input) {
|
|
881
1010
|
const loop = getDefaultProofLoop(loopRef);
|
|
882
1011
|
if (!loop) {
|
|
@@ -920,11 +1049,17 @@ module.exports = {
|
|
|
920
1049
|
buildDefaultProofCenter,
|
|
921
1050
|
buildDefaultProofLoopCatalog,
|
|
922
1051
|
buildDefaultProofLoops,
|
|
1052
|
+
buildTransactionProofHandoffCenter,
|
|
1053
|
+
buildTransactionProofHandoffEvent,
|
|
923
1054
|
getDefaultProofLoop,
|
|
1055
|
+
canonicalizeTransactionProofHandoff,
|
|
924
1056
|
runDefaultProofLoop,
|
|
1057
|
+
runTransactionProofHandoff,
|
|
925
1058
|
summarizeDefaultProofCenter,
|
|
926
1059
|
summarizeDefaultProofLoops,
|
|
927
1060
|
summarizeGuidedProofLoopBundle,
|
|
1061
|
+
summarizeTransactionProofHandoff,
|
|
1062
|
+
summarizeTransactionProofHandoffCenter,
|
|
928
1063
|
canonicalizeEvent,
|
|
929
1064
|
hashEvent,
|
|
930
1065
|
emitReceipt,
|
package/server.js
CHANGED
|
@@ -97,6 +97,16 @@ 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
|
+
|
|
100
110
|
if (req.method === 'GET' && url.pathname === '/v1/proof-center/default-loop') {
|
|
101
111
|
const loop = proofSdk.getDefaultProofLoop(url.searchParams.get('ref'));
|
|
102
112
|
if (!loop) {
|
|
@@ -119,6 +129,17 @@ async function routeRequest(req, res) {
|
|
|
119
129
|
return;
|
|
120
130
|
}
|
|
121
131
|
|
|
132
|
+
if (req.method === 'POST' && url.pathname === '/v1/proof-center/transaction-handoff/run') {
|
|
133
|
+
try {
|
|
134
|
+
const body = await readJsonBody(req);
|
|
135
|
+
const result = proofSdk.runTransactionProofHandoff(body);
|
|
136
|
+
sendJson(res, 200, result);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
sendJson(res, 400, { ok: false, reason: error.message });
|
|
139
|
+
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
122
143
|
if (req.method === 'POST' && url.pathname === '/v1/receipts/verify') {
|
|
123
144
|
try {
|
|
124
145
|
const body = await readJsonBody(req);
|