xoonya 2.4.0 → 2.6.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 +135 -7
- package/RELEASE_NOTES.md +27 -18
- package/SERVICE_CONTRACT.md +86 -0
- package/START_HERE.md +39 -0
- package/XOONYA_NATIVE_ATOM_SPEC.md +184 -0
- package/XOONYA_NATIVE_PROOF_FORMAT.md +502 -0
- package/XOONYA_NATIVE_STANDARD_GOVERNANCE.md +116 -0
- package/bin/xoonya-first-run.js +184 -0
- package/bin/xoonya.js +81 -0
- package/lib/artifact_distribution_lane_contract.js +54 -0
- package/lib/asyncapi_contract.js +135 -0
- package/lib/auth_interop_contract.js +69 -0
- package/lib/cloudevents_contract.js +79 -0
- package/lib/erc8004_proof_lane_contract.js +64 -0
- package/lib/event_system_lane_contract.js +76 -0
- package/lib/external_proof_import_lane_contract.js +87 -0
- package/lib/feature_control_lane_contract.js +54 -0
- package/lib/framework_lane_contract.js +76 -0
- package/lib/identity_interop_contract.js +83 -0
- package/lib/integration_matrix_contract.js +81 -0
- package/lib/major_rails_proof_lane_contract.js +87 -0
- package/lib/openapi_contract.js +227 -0
- package/lib/proof_bridge_lane_contract.js +82 -0
- package/lib/provenance_lane_contract.js +54 -0
- package/lib/provider_lane_contract.js +67 -0
- package/lib/release_history.js +32 -0
- package/lib/result_package_trust_lane_contract.js +74 -0
- package/lib/shared_signals_lane_contract.js +54 -0
- package/lib/telemetry_lane_contract.js +54 -0
- package/lib/treasury_proof_lane_contract.js +83 -0
- package/package.json +13 -17
- package/proof_sdk.js +2391 -44
- package/server.js +406 -2
- package/vectors/adversarial-vectors.json +373 -2
- package/vectors/conformance-vectors.json +342 -1
- package/vectors/native-atom-vectors.json +101 -0
- package/vectors/native-payload-profile-vectors.json +50 -0
- package/OPERATIONS_RUNBOOK.md +0 -50
- package/OPERATOR_START_HERE.md +0 -67
- package/PROGRAM_COMPLETE_RELEASE.md +0 -52
- package/PROGRAM_STATUS.md +0 -57
- package/PUBLISH_PLAN.md +0 -14
- package/RELEASE_CHECKLIST.md +0 -16
package/proof_sdk.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const crypto = require("crypto");
|
|
4
4
|
|
|
5
5
|
const MAGIC_HEX = "50524654";
|
|
6
|
+
const XOONYA_NATIVE_ATOM_MAGIC_ASCII = "XNYA";
|
|
7
|
+
const XOONYA_NATIVE_ATOM_MAGIC_HEX = "584e5941";
|
|
6
8
|
const VERSION_V1_HEX = "01";
|
|
7
9
|
const VERSION_V2_HEX = "02";
|
|
8
10
|
const TYPE_REGISTER = "01";
|
|
@@ -15,11 +17,201 @@ const REGISTRY_PROFILE_VERSION = "registry-profile-v1";
|
|
|
15
17
|
const CANONICAL_EVENT_BUNDLE_VERSION = "canonical-event-bundle/v1";
|
|
16
18
|
const CANONICAL_RECEIPT_VERSION = "receipt/v1";
|
|
17
19
|
const PROOF_BUNDLE_VERSION = "proof-bundle/v1";
|
|
20
|
+
const VERIFICATION_METHOD_NONE = "none";
|
|
21
|
+
const LEGACY_OPRETURN_METHOD = "legacy-opreturn-v1";
|
|
22
|
+
const DETACHED_ASSERTION_METHOD = "detached-assertion-v1";
|
|
23
|
+
const XOONYA_NATIVE_SHA256_METHOD = "xoonya-native-sha256-v1";
|
|
24
|
+
const JWT_ASSERTION_METHOD = "jwt-assertion-v1";
|
|
25
|
+
const DID_VC_METHOD = "did-vc-v1";
|
|
26
|
+
const SD_JWT_VC_METHOD = "sd-jwt-vc-v1";
|
|
27
|
+
const SIGNED_ENVELOPE_METHOD = "signed-envelope-v1";
|
|
28
|
+
const PARTNER_PROOF_ENVELOPE_METHOD = "partner-proof-envelope-v1";
|
|
29
|
+
const XOONYA_NATIVE_PROOF_FORMAT_VERSION = "xoonya-native-proof/v1";
|
|
30
|
+
const XOONYA_NATIVE_SIGNED_METHOD = "xoonya-native-signed-v1";
|
|
31
|
+
const XOONYA_NATIVE_ANCHORED_METHOD = "xoonya-native-anchored-v1";
|
|
32
|
+
const XOONYA_NATIVE_HYBRID_METHOD = "xoonya-native-hybrid-v1";
|
|
33
|
+
const XOONYA_NATIVE_ATOM_V1 = "xoonya-native-atom/v1";
|
|
34
|
+
const XOONYA_NATIVE_ATOM_V2 = "xoonya-native-atom/v2";
|
|
35
|
+
const XOONYA_NATIVE_ATOM_V3_CONTINGENCY = "xoonya-native-atom/v3-contingency";
|
|
36
|
+
const XOONYA_NATIVE_PAYLOAD_PROFILE_V1 = "xoonya-native-payload-profile/v1";
|
|
37
|
+
const XOONYA_NATIVE_LINE_RATE_FRAME_V1 = "xoonya-native-line-rate-frame/v1";
|
|
38
|
+
const XNYA_DS_AGENT_V1 = "xoonya:agent:v1:";
|
|
39
|
+
const XNYA_DS_PAYLOAD_V1 = "xoonya:payload:v1:";
|
|
40
|
+
const XNYA_DS_AGENT_V2 = "xoonya:agent:v2:";
|
|
41
|
+
const XNYA_DS_PAYLOAD_V2 = "xoonya:payload:v2:";
|
|
42
|
+
const XNYA_DS_PAYLOAD_PROFILE_V1 = "xoonya:payload-profile:v1:";
|
|
43
|
+
const XNYA_DS_LINE_RATE_FRAME_V1 = "xoonya:line-rate-frame:v1:";
|
|
44
|
+
const XNYA_NATIVE_ATOM_ERROR_CODES = Object.freeze({
|
|
45
|
+
ATOM_HEX_NOT_HEX: "atom_hex_not_hex",
|
|
46
|
+
ATOM_UNSUPPORTED_LENGTH: "atom_unsupported_length",
|
|
47
|
+
ATOM_BAD_MAGIC: "atom_bad_magic",
|
|
48
|
+
ATOM_UNSUPPORTED_RECORD_TYPE: "atom_unsupported_record_type",
|
|
49
|
+
ATOM_VERSION_LENGTH_MISMATCH: "atom_version_length_mismatch",
|
|
50
|
+
IDENTITY_UNSUPPORTED_TYPE_PREFIX: "identity_unsupported_type_prefix",
|
|
51
|
+
IDENTITY_MISSING_RAW_BYTES: "identity_missing_raw_bytes",
|
|
52
|
+
AGENT_ID_MISMATCH: "agent_id_mismatch",
|
|
53
|
+
PAYLOAD_HASH_MISMATCH: "payload_hash_mismatch"
|
|
54
|
+
});
|
|
18
55
|
const REGISTRY_EVENT_TO_TYPE = {
|
|
19
56
|
register: "01",
|
|
20
57
|
update: "02",
|
|
21
58
|
revoke: "03"
|
|
22
59
|
};
|
|
60
|
+
const PROOF_VERIFICATION_METHODS = Object.freeze({
|
|
61
|
+
[LEGACY_OPRETURN_METHOD]: Object.freeze({
|
|
62
|
+
id: LEGACY_OPRETURN_METHOD,
|
|
63
|
+
family: "legacy_receipt",
|
|
64
|
+
verification_posture: "compatibility_verified",
|
|
65
|
+
description: "Verifies the compatibility OP_RETURN receipt and requires the receipt signature to match it."
|
|
66
|
+
}),
|
|
67
|
+
[DETACHED_ASSERTION_METHOD]: Object.freeze({
|
|
68
|
+
id: DETACHED_ASSERTION_METHOD,
|
|
69
|
+
family: "detached_assertion",
|
|
70
|
+
verification_posture: "structure_verified_external_signature",
|
|
71
|
+
description: "Accepts an explicit detached assertion signature after canonical receipt checks; cryptographic verification is external to this helper."
|
|
72
|
+
}),
|
|
73
|
+
[XOONYA_NATIVE_SHA256_METHOD]: Object.freeze({
|
|
74
|
+
id: XOONYA_NATIVE_SHA256_METHOD,
|
|
75
|
+
family: "xoonya_native",
|
|
76
|
+
verification_posture: "native_deterministic_digest",
|
|
77
|
+
description: "Verifies Xoonya's native deterministic receipt digest format for method-agnostic proof bundles."
|
|
78
|
+
}),
|
|
79
|
+
[XOONYA_NATIVE_SIGNED_METHOD]: Object.freeze({
|
|
80
|
+
id: XOONYA_NATIVE_SIGNED_METHOD,
|
|
81
|
+
family: "xoonya_native",
|
|
82
|
+
verification_posture: "native_signature_verified",
|
|
83
|
+
description: "Verifies Xoonya's native signed proof envelope with explicit signature-suite and public-key binding."
|
|
84
|
+
}),
|
|
85
|
+
[XOONYA_NATIVE_ANCHORED_METHOD]: Object.freeze({
|
|
86
|
+
id: XOONYA_NATIVE_ANCHORED_METHOD,
|
|
87
|
+
family: "xoonya_native",
|
|
88
|
+
verification_posture: "native_anchor_binding_verified",
|
|
89
|
+
description: "Verifies Xoonya's native anchor-binding proof envelope for chain, batch, finality, or external attestation references."
|
|
90
|
+
}),
|
|
91
|
+
[JWT_ASSERTION_METHOD]: Object.freeze({
|
|
92
|
+
id: JWT_ASSERTION_METHOD,
|
|
93
|
+
family: "jwt",
|
|
94
|
+
verification_posture: "structure_verified_external_signature",
|
|
95
|
+
description: "Accepts a compact JWT assertion after canonical receipt checks; JWT signature verification is external to this helper."
|
|
96
|
+
}),
|
|
97
|
+
[DID_VC_METHOD]: Object.freeze({
|
|
98
|
+
id: DID_VC_METHOD,
|
|
99
|
+
family: "did_vc",
|
|
100
|
+
verification_posture: "structure_verified_external_signature",
|
|
101
|
+
description: "Accepts a DID/VC proof envelope after canonical receipt checks; DID resolution and VC proof verification are external to this helper."
|
|
102
|
+
}),
|
|
103
|
+
[SD_JWT_VC_METHOD]: Object.freeze({
|
|
104
|
+
id: SD_JWT_VC_METHOD,
|
|
105
|
+
family: "sd_jwt_vc",
|
|
106
|
+
verification_posture: "structure_verified_external_signature",
|
|
107
|
+
description: "Accepts an SD-JWT VC disclosure envelope after canonical receipt checks; disclosure and issuer verification are external to this helper."
|
|
108
|
+
}),
|
|
109
|
+
[SIGNED_ENVELOPE_METHOD]: Object.freeze({
|
|
110
|
+
id: SIGNED_ENVELOPE_METHOD,
|
|
111
|
+
family: "signed_envelope",
|
|
112
|
+
verification_posture: "structure_verified_external_signature",
|
|
113
|
+
description: "Accepts a signed envelope after canonical receipt checks; envelope-specific signature verification is external to this helper."
|
|
114
|
+
}),
|
|
115
|
+
[PARTNER_PROOF_ENVELOPE_METHOD]: Object.freeze({
|
|
116
|
+
id: PARTNER_PROOF_ENVELOPE_METHOD,
|
|
117
|
+
family: "partner_proof_envelope",
|
|
118
|
+
verification_posture: "structure_verified_external_signature",
|
|
119
|
+
description: "Accepts partner-specific proof envelopes after canonical receipt checks; partner verifier policy is external to this helper."
|
|
120
|
+
})
|
|
121
|
+
});
|
|
122
|
+
const NATIVE_SIGNATURE_SUITES = Object.freeze({
|
|
123
|
+
ed25519: Object.freeze({
|
|
124
|
+
id: "ed25519",
|
|
125
|
+
maturity: "implemented",
|
|
126
|
+
public_key_format: "spki-pem",
|
|
127
|
+
verification_posture: "native_verified"
|
|
128
|
+
}),
|
|
129
|
+
secp256k1: Object.freeze({
|
|
130
|
+
id: "secp256k1",
|
|
131
|
+
maturity: "implemented",
|
|
132
|
+
public_key_format: "spki-pem",
|
|
133
|
+
verification_posture: "native_verified",
|
|
134
|
+
curve: "secp256k1",
|
|
135
|
+
signing_hash: "sha256"
|
|
136
|
+
}),
|
|
137
|
+
p256: Object.freeze({
|
|
138
|
+
id: "p256",
|
|
139
|
+
maturity: "implemented",
|
|
140
|
+
public_key_format: "spki-pem",
|
|
141
|
+
verification_posture: "native_verified",
|
|
142
|
+
curve: "prime256v1",
|
|
143
|
+
signing_hash: "sha256"
|
|
144
|
+
}),
|
|
145
|
+
"webauthn-cose": Object.freeze({
|
|
146
|
+
id: "webauthn-cose",
|
|
147
|
+
maturity: "planned",
|
|
148
|
+
public_key_format: "cose-key",
|
|
149
|
+
verification_posture: "registry_declared_not_yet_verified"
|
|
150
|
+
}),
|
|
151
|
+
dilithium: Object.freeze({
|
|
152
|
+
id: "dilithium",
|
|
153
|
+
maturity: "planned_pqc",
|
|
154
|
+
public_key_format: "suite_defined",
|
|
155
|
+
verification_posture: "registry_declared_not_yet_verified"
|
|
156
|
+
}),
|
|
157
|
+
falcon: Object.freeze({
|
|
158
|
+
id: "falcon",
|
|
159
|
+
maturity: "planned_pqc",
|
|
160
|
+
public_key_format: "suite_defined",
|
|
161
|
+
verification_posture: "registry_declared_not_yet_verified"
|
|
162
|
+
}),
|
|
163
|
+
"sphincs-plus": Object.freeze({
|
|
164
|
+
id: "sphincs-plus",
|
|
165
|
+
maturity: "planned_pqc",
|
|
166
|
+
public_key_format: "suite_defined",
|
|
167
|
+
verification_posture: "registry_declared_not_yet_verified"
|
|
168
|
+
})
|
|
169
|
+
});
|
|
170
|
+
const XOONYA_NATIVE_IDENTITY_TYPES = Object.freeze({
|
|
171
|
+
"01": Object.freeze({
|
|
172
|
+
prefix: "01",
|
|
173
|
+
id: "secp256k1-public-key",
|
|
174
|
+
canonical_material: "compressed-sec1-public-key"
|
|
175
|
+
}),
|
|
176
|
+
"02": Object.freeze({
|
|
177
|
+
prefix: "02",
|
|
178
|
+
id: "device-identifier",
|
|
179
|
+
canonical_material: "raw-device-identifier-bytes"
|
|
180
|
+
}),
|
|
181
|
+
"03": Object.freeze({
|
|
182
|
+
prefix: "03",
|
|
183
|
+
id: "did-string",
|
|
184
|
+
canonical_material: "utf8-did-string-no-bom-no-normalization"
|
|
185
|
+
}),
|
|
186
|
+
"04": Object.freeze({
|
|
187
|
+
prefix: "04",
|
|
188
|
+
id: "opaque-agent-key",
|
|
189
|
+
canonical_material: "opaque-agent-key-bytes"
|
|
190
|
+
}),
|
|
191
|
+
"05": Object.freeze({
|
|
192
|
+
prefix: "05",
|
|
193
|
+
id: "dilithium-public-key",
|
|
194
|
+
canonical_material: "suite-defined-pqc-public-key-bytes"
|
|
195
|
+
}),
|
|
196
|
+
"06": Object.freeze({
|
|
197
|
+
prefix: "06",
|
|
198
|
+
id: "falcon-public-key",
|
|
199
|
+
canonical_material: "suite-defined-pqc-public-key-bytes"
|
|
200
|
+
}),
|
|
201
|
+
"07": Object.freeze({
|
|
202
|
+
prefix: "07",
|
|
203
|
+
id: "sphincs-plus-public-key",
|
|
204
|
+
canonical_material: "suite-defined-pqc-public-key-bytes"
|
|
205
|
+
})
|
|
206
|
+
});
|
|
207
|
+
const EXTERNAL_PROOF_IMPORT_METHODS = Object.freeze([
|
|
208
|
+
DETACHED_ASSERTION_METHOD,
|
|
209
|
+
JWT_ASSERTION_METHOD,
|
|
210
|
+
DID_VC_METHOD,
|
|
211
|
+
SD_JWT_VC_METHOD,
|
|
212
|
+
SIGNED_ENVELOPE_METHOD,
|
|
213
|
+
PARTNER_PROOF_ENVELOPE_METHOD
|
|
214
|
+
]);
|
|
23
215
|
|
|
24
216
|
function sha256Hex(buf) {
|
|
25
217
|
return crypto.createHash("sha256").update(buf).digest("hex");
|
|
@@ -38,6 +230,14 @@ function assertHex(hex, expectedLen, label) {
|
|
|
38
230
|
return normalized;
|
|
39
231
|
}
|
|
40
232
|
|
|
233
|
+
function assertVariableHex(hex, label) {
|
|
234
|
+
const normalized = String(hex || "").trim().toLowerCase();
|
|
235
|
+
if (!/^[a-f0-9]+$/.test(normalized) || normalized.length === 0 || normalized.length % 2 !== 0) {
|
|
236
|
+
throw new Error(`${label} must be non-empty byte-aligned hex`);
|
|
237
|
+
}
|
|
238
|
+
return normalized;
|
|
239
|
+
}
|
|
240
|
+
|
|
41
241
|
function canonicalize(value) {
|
|
42
242
|
if (Array.isArray(value)) {
|
|
43
243
|
return `[${value.map((item) => canonicalize(item)).join(",")}]`;
|
|
@@ -53,6 +253,286 @@ function canonicalJsonSha256Hex(value) {
|
|
|
53
253
|
return sha256Hex(Buffer.from(canonicalize(value), "utf8"));
|
|
54
254
|
}
|
|
55
255
|
|
|
256
|
+
function base64urlEncode(buf) {
|
|
257
|
+
return Buffer.from(buf)
|
|
258
|
+
.toString("base64")
|
|
259
|
+
.replace(/\+/g, "-")
|
|
260
|
+
.replace(/\//g, "_")
|
|
261
|
+
.replace(/=+$/g, "");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function base64urlDecode(value, label) {
|
|
265
|
+
const normalized = normalizeString(value);
|
|
266
|
+
if (!/^[A-Za-z0-9_-]+$/.test(normalized)) {
|
|
267
|
+
throw new Error(`${label} must be base64url`);
|
|
268
|
+
}
|
|
269
|
+
const padded = normalized + "=".repeat((4 - (normalized.length % 4)) % 4);
|
|
270
|
+
return Buffer.from(padded.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function uint16Buffer(value, label) {
|
|
274
|
+
const n = Number(value);
|
|
275
|
+
if (!Number.isInteger(n) || n < 0 || n > 0xffff) {
|
|
276
|
+
throw new Error(`${label} must be uint16`);
|
|
277
|
+
}
|
|
278
|
+
const out = Buffer.alloc(2);
|
|
279
|
+
out.writeUInt16BE(n, 0);
|
|
280
|
+
return out;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function uint64Buffer(value, label) {
|
|
284
|
+
let n;
|
|
285
|
+
try {
|
|
286
|
+
n = BigInt(value);
|
|
287
|
+
} catch (error) {
|
|
288
|
+
throw new Error(`${label} must be uint64`);
|
|
289
|
+
}
|
|
290
|
+
if (n < 0n || n > 0xffffffffffffffffn) {
|
|
291
|
+
throw new Error(`${label} must be uint64`);
|
|
292
|
+
}
|
|
293
|
+
const out = Buffer.alloc(8);
|
|
294
|
+
out.writeBigUInt64BE(n, 0);
|
|
295
|
+
return out;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function readUInt64String(buf) {
|
|
299
|
+
return buf.readBigUInt64BE(0).toString();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const XNYA_PAYLOAD_FIELD_TYPES = Object.freeze({
|
|
303
|
+
bytes32: Object.freeze({ id: 1, fixed_length: 32 }),
|
|
304
|
+
bytes20: Object.freeze({ id: 2, fixed_length: 20 }),
|
|
305
|
+
uint64: Object.freeze({ id: 3, fixed_length: 8 }),
|
|
306
|
+
utf8: Object.freeze({ id: 4, max_length: 1024 }),
|
|
307
|
+
bool: Object.freeze({ id: 5, fixed_length: 1 })
|
|
308
|
+
});
|
|
309
|
+
const XNYA_PAYLOAD_FIELD_TYPE_BY_ID = Object.freeze(
|
|
310
|
+
Object.fromEntries(Object.entries(XNYA_PAYLOAD_FIELD_TYPES).map(([name, spec]) => [spec.id, { name, ...spec }]))
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
function normalizePayloadFieldValue(fieldType, value, label) {
|
|
314
|
+
const spec = XNYA_PAYLOAD_FIELD_TYPES[fieldType];
|
|
315
|
+
if (!spec) {
|
|
316
|
+
throw new Error(`${label}.field_type unsupported`);
|
|
317
|
+
}
|
|
318
|
+
if (fieldType === "bytes32" || fieldType === "bytes20") {
|
|
319
|
+
const expectedHexLen = spec.fixed_length * 2;
|
|
320
|
+
return Buffer.from(assertHex(value, expectedHexLen, `${label}.value_hex`), "hex");
|
|
321
|
+
}
|
|
322
|
+
if (fieldType === "uint64") {
|
|
323
|
+
return uint64Buffer(value, `${label}.value`);
|
|
324
|
+
}
|
|
325
|
+
if (fieldType === "utf8") {
|
|
326
|
+
const text = String(value == null ? "" : value);
|
|
327
|
+
const out = Buffer.from(text, "utf8");
|
|
328
|
+
if (out.length === 0 || out.length > spec.max_length) {
|
|
329
|
+
throw new Error(`${label}.value must be non-empty utf8 up to ${spec.max_length} bytes`);
|
|
330
|
+
}
|
|
331
|
+
return out;
|
|
332
|
+
}
|
|
333
|
+
if (fieldType === "bool") {
|
|
334
|
+
if (typeof value !== "boolean") {
|
|
335
|
+
throw new Error(`${label}.value must be boolean`);
|
|
336
|
+
}
|
|
337
|
+
return Buffer.from([value ? 1 : 0]);
|
|
338
|
+
}
|
|
339
|
+
throw new Error(`${label}.field_type unsupported`);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function normalizePayloadProfileFields(fields) {
|
|
343
|
+
if (!Array.isArray(fields) || fields.length === 0) {
|
|
344
|
+
throw new Error("payload profile fields must be a non-empty array");
|
|
345
|
+
}
|
|
346
|
+
if (fields.length > 64) {
|
|
347
|
+
throw new Error("payload profile fields must contain at most 64 entries");
|
|
348
|
+
}
|
|
349
|
+
const normalized = fields.map((field, index) => {
|
|
350
|
+
if (!field || typeof field !== "object" || Array.isArray(field)) {
|
|
351
|
+
throw new Error(`payload profile fields[${index}] must be an object`);
|
|
352
|
+
}
|
|
353
|
+
const fieldId = Number(field.field_id || field.id);
|
|
354
|
+
if (!Number.isInteger(fieldId) || fieldId < 1 || fieldId > 0xffff) {
|
|
355
|
+
throw new Error(`payload profile fields[${index}].field_id must be uint16`);
|
|
356
|
+
}
|
|
357
|
+
const fieldType = normalizeString(field.field_type || field.type);
|
|
358
|
+
const rawValue = Object.prototype.hasOwnProperty.call(field, "value_hex")
|
|
359
|
+
? field.value_hex
|
|
360
|
+
: field.value;
|
|
361
|
+
const value = normalizePayloadFieldValue(fieldType, rawValue, `payload profile fields[${index}]`);
|
|
362
|
+
return {
|
|
363
|
+
field_id: fieldId,
|
|
364
|
+
field_type: fieldType,
|
|
365
|
+
field_type_id: XNYA_PAYLOAD_FIELD_TYPES[fieldType].id,
|
|
366
|
+
value
|
|
367
|
+
};
|
|
368
|
+
}).sort((a, b) => a.field_id - b.field_id || a.field_type_id - b.field_type_id);
|
|
369
|
+
const seen = new Set();
|
|
370
|
+
for (const field of normalized) {
|
|
371
|
+
const key = `${field.field_id}:${field.field_type_id}`;
|
|
372
|
+
if (seen.has(key)) {
|
|
373
|
+
throw new Error("payload profile duplicate field id/type");
|
|
374
|
+
}
|
|
375
|
+
seen.add(key);
|
|
376
|
+
}
|
|
377
|
+
return normalized;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function encodeXoonyaNativePayloadProfileV1(input = {}) {
|
|
381
|
+
const schemaRef = normalizeString(input.schema_ref || input.schemaRef || "xoonya.payload.schema.generic.v1");
|
|
382
|
+
if (!schemaRef) {
|
|
383
|
+
throw new Error("payload profile schema_ref required");
|
|
384
|
+
}
|
|
385
|
+
const fields = normalizePayloadProfileFields(input.fields);
|
|
386
|
+
const schemaHash = sha256Hex(Buffer.from(`xoonya:payload-schema:v1:${schemaRef}`, "utf8"));
|
|
387
|
+
const fieldBuffers = fields.map((field) => Buffer.concat([
|
|
388
|
+
uint16Buffer(field.field_id, "payload profile field_id"),
|
|
389
|
+
Buffer.from([field.field_type_id]),
|
|
390
|
+
uint16Buffer(field.value.length, "payload profile field length"),
|
|
391
|
+
field.value
|
|
392
|
+
]));
|
|
393
|
+
const canonicalBytes = Buffer.concat([
|
|
394
|
+
Buffer.from("XNYP", "ascii"),
|
|
395
|
+
Buffer.from([1]),
|
|
396
|
+
Buffer.from(schemaHash, "hex"),
|
|
397
|
+
Buffer.from([fields.length]),
|
|
398
|
+
...fieldBuffers
|
|
399
|
+
]);
|
|
400
|
+
const payloadHash = sha256Hex(Buffer.concat([
|
|
401
|
+
Buffer.from(XNYA_DS_PAYLOAD_PROFILE_V1, "utf8"),
|
|
402
|
+
canonicalBytes
|
|
403
|
+
]));
|
|
404
|
+
return {
|
|
405
|
+
profile: XOONYA_NATIVE_PAYLOAD_PROFILE_V1,
|
|
406
|
+
schema_ref: schemaRef,
|
|
407
|
+
schema_hash_sha256: schemaHash,
|
|
408
|
+
field_count: fields.length,
|
|
409
|
+
canonical_bytes_hex: canonicalBytes.toString("hex"),
|
|
410
|
+
payload_hash_sha256: payloadHash,
|
|
411
|
+
fields: fields.map((field) => ({
|
|
412
|
+
field_id: field.field_id,
|
|
413
|
+
field_type: field.field_type,
|
|
414
|
+
value_hex: field.value.toString("hex")
|
|
415
|
+
}))
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function parseXoonyaNativePayloadProfileV1(canonicalBytesHex) {
|
|
420
|
+
const hex = assertVariableHex(canonicalBytesHex, "payload profile canonical bytes");
|
|
421
|
+
const buf = Buffer.from(hex, "hex");
|
|
422
|
+
if (buf.length < 38) {
|
|
423
|
+
throw new Error("payload profile bytes too short");
|
|
424
|
+
}
|
|
425
|
+
if (buf.subarray(0, 4).toString("ascii") !== "XNYP") {
|
|
426
|
+
throw new Error("payload profile magic mismatch");
|
|
427
|
+
}
|
|
428
|
+
if (buf[4] !== 1) {
|
|
429
|
+
throw new Error("payload profile version unsupported");
|
|
430
|
+
}
|
|
431
|
+
const schemaHash = buf.subarray(5, 37).toString("hex");
|
|
432
|
+
const fieldCount = buf[37];
|
|
433
|
+
if (fieldCount === 0 || fieldCount > 64) {
|
|
434
|
+
throw new Error("payload profile field count unsupported");
|
|
435
|
+
}
|
|
436
|
+
let offset = 38;
|
|
437
|
+
const fields = [];
|
|
438
|
+
const seen = new Set();
|
|
439
|
+
for (let i = 0; i < fieldCount; i += 1) {
|
|
440
|
+
if (offset + 5 > buf.length) {
|
|
441
|
+
throw new Error("payload profile truncated field header");
|
|
442
|
+
}
|
|
443
|
+
const fieldId = buf.readUInt16BE(offset);
|
|
444
|
+
const fieldTypeId = buf[offset + 2];
|
|
445
|
+
const length = buf.readUInt16BE(offset + 3);
|
|
446
|
+
offset += 5;
|
|
447
|
+
if (offset + length > buf.length) {
|
|
448
|
+
throw new Error("payload profile truncated field value");
|
|
449
|
+
}
|
|
450
|
+
const typeSpec = XNYA_PAYLOAD_FIELD_TYPE_BY_ID[fieldTypeId];
|
|
451
|
+
if (!typeSpec) {
|
|
452
|
+
throw new Error("payload profile field type unsupported");
|
|
453
|
+
}
|
|
454
|
+
const value = buf.subarray(offset, offset + length);
|
|
455
|
+
offset += length;
|
|
456
|
+
if (typeSpec.fixed_length && value.length !== typeSpec.fixed_length) {
|
|
457
|
+
throw new Error("payload profile fixed field length mismatch");
|
|
458
|
+
}
|
|
459
|
+
if (typeSpec.max_length && (value.length === 0 || value.length > typeSpec.max_length)) {
|
|
460
|
+
throw new Error("payload profile variable field length mismatch");
|
|
461
|
+
}
|
|
462
|
+
if (typeSpec.name === "bool" && value[0] !== 0 && value[0] !== 1) {
|
|
463
|
+
throw new Error("payload profile bool value invalid");
|
|
464
|
+
}
|
|
465
|
+
const key = `${fieldId}:${fieldTypeId}`;
|
|
466
|
+
if (seen.has(key)) {
|
|
467
|
+
throw new Error("payload profile duplicate field id/type");
|
|
468
|
+
}
|
|
469
|
+
seen.add(key);
|
|
470
|
+
fields.push({
|
|
471
|
+
field_id: fieldId,
|
|
472
|
+
field_type: typeSpec.name,
|
|
473
|
+
field_type_id: fieldTypeId,
|
|
474
|
+
value_hex: value.toString("hex"),
|
|
475
|
+
...(typeSpec.name === "uint64" ? { value: readUInt64String(value) } : {}),
|
|
476
|
+
...(typeSpec.name === "bool" ? { value: value[0] === 1 } : {})
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
if (offset !== buf.length) {
|
|
480
|
+
throw new Error("payload profile trailing bytes");
|
|
481
|
+
}
|
|
482
|
+
const sorted = fields.slice().sort((a, b) => a.field_id - b.field_id || a.field_type_id - b.field_type_id);
|
|
483
|
+
if (canonicalize(fields) !== canonicalize(sorted)) {
|
|
484
|
+
throw new Error("payload profile fields not canonical order");
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
profile: XOONYA_NATIVE_PAYLOAD_PROFILE_V1,
|
|
488
|
+
version: 1,
|
|
489
|
+
schema_hash_sha256: schemaHash,
|
|
490
|
+
field_count: fieldCount,
|
|
491
|
+
fields,
|
|
492
|
+
canonical_bytes_hex: hex,
|
|
493
|
+
payload_hash_sha256: sha256Hex(Buffer.concat([
|
|
494
|
+
Buffer.from(XNYA_DS_PAYLOAD_PROFILE_V1, "utf8"),
|
|
495
|
+
buf
|
|
496
|
+
]))
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function verifyXoonyaNativePayloadProfileV1(canonicalBytesHex, options = {}) {
|
|
501
|
+
try {
|
|
502
|
+
const parsed = parseXoonyaNativePayloadProfileV1(canonicalBytesHex);
|
|
503
|
+
const expectedHash = normalizeString(options.payload_hash_sha256 || options.expected_payload_hash_sha256).toLowerCase();
|
|
504
|
+
if (expectedHash && expectedHash !== parsed.payload_hash_sha256) {
|
|
505
|
+
return { valid: false, reason: "payload_profile_hash_mismatch", parsed };
|
|
506
|
+
}
|
|
507
|
+
const schemaRef = normalizeString(options.schema_ref || options.schemaRef);
|
|
508
|
+
if (schemaRef) {
|
|
509
|
+
const expectedSchemaHash = sha256Hex(Buffer.from(`xoonya:payload-schema:v1:${schemaRef}`, "utf8"));
|
|
510
|
+
if (expectedSchemaHash !== parsed.schema_hash_sha256) {
|
|
511
|
+
return { valid: false, reason: "payload_profile_schema_mismatch", parsed };
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
const allowedFieldIds = Array.isArray(options.allowed_field_ids)
|
|
515
|
+
? options.allowed_field_ids.map((entry) => Number(entry))
|
|
516
|
+
: null;
|
|
517
|
+
if (allowedFieldIds) {
|
|
518
|
+
const allowed = new Set(allowedFieldIds);
|
|
519
|
+
if (parsed.fields.some((field) => !allowed.has(field.field_id))) {
|
|
520
|
+
return { valid: false, reason: "payload_profile_unknown_field", parsed };
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return { valid: true, parsed };
|
|
524
|
+
} catch (error) {
|
|
525
|
+
return { valid: false, reason: error.message };
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function lineRateFrameChecksum(atomBytes) {
|
|
530
|
+
return sha256Hex(Buffer.concat([
|
|
531
|
+
Buffer.from(XNYA_DS_LINE_RATE_FRAME_V1, "utf8"),
|
|
532
|
+
atomBytes
|
|
533
|
+
])).slice(0, 4);
|
|
534
|
+
}
|
|
535
|
+
|
|
56
536
|
function normalizeString(value) {
|
|
57
537
|
return String(value == null ? "" : value).trim();
|
|
58
538
|
}
|
|
@@ -142,6 +622,349 @@ function buildCanonicalReceiptSigningMaterial(receipt) {
|
|
|
142
622
|
};
|
|
143
623
|
}
|
|
144
624
|
|
|
625
|
+
function listProofVerificationMethods() {
|
|
626
|
+
return Object.values(PROOF_VERIFICATION_METHODS).map((method) => ({ ...method }));
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function getProofVerificationMethod(methodId) {
|
|
630
|
+
const normalized = normalizeString(methodId);
|
|
631
|
+
const method = PROOF_VERIFICATION_METHODS[normalized];
|
|
632
|
+
return method ? { ...method } : null;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function listNativeSignatureSuites() {
|
|
636
|
+
return Object.values(NATIVE_SIGNATURE_SUITES).map((suite) => ({ ...suite }));
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function getNativeSignatureSuite(suiteId) {
|
|
640
|
+
const normalized = normalizeString(suiteId);
|
|
641
|
+
const suite = NATIVE_SIGNATURE_SUITES[normalized];
|
|
642
|
+
return suite ? { ...suite } : null;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function listXoonyaNativeIdentityTypes() {
|
|
646
|
+
return Object.values(XOONYA_NATIVE_IDENTITY_TYPES).map((entry) => ({ ...entry }));
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
function getXoonyaNativeIdentityType(prefixHex) {
|
|
650
|
+
const normalized = normalizeString(prefixHex).toLowerCase();
|
|
651
|
+
const entry = XOONYA_NATIVE_IDENTITY_TYPES[normalized];
|
|
652
|
+
return entry ? { ...entry } : null;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
function isExternalAssertionMethod(algorithm) {
|
|
656
|
+
return EXTERNAL_PROOF_IMPORT_METHODS.includes(algorithm);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
function selectReceiptAlgorithm(options, compatibility) {
|
|
660
|
+
const requested = normalizeString(options.algorithm);
|
|
661
|
+
if (requested) {
|
|
662
|
+
return requested;
|
|
663
|
+
}
|
|
664
|
+
if (compatibility) {
|
|
665
|
+
return LEGACY_OPRETURN_METHOD;
|
|
666
|
+
}
|
|
667
|
+
if (options.signature != null || typeof options.signer === "function") {
|
|
668
|
+
return DETACHED_ASSERTION_METHOD;
|
|
669
|
+
}
|
|
670
|
+
return XOONYA_NATIVE_SHA256_METHOD;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function buildNativeReceiptSignature(receipt, canonicalEvent) {
|
|
674
|
+
const material = {
|
|
675
|
+
method: XOONYA_NATIVE_SHA256_METHOD,
|
|
676
|
+
receipt_signing_material: buildCanonicalReceiptSigningMaterial(receipt),
|
|
677
|
+
event_commitment: hashEvent(canonicalEvent)
|
|
678
|
+
};
|
|
679
|
+
return `${XOONYA_NATIVE_SHA256_METHOD}:${sha256Hex(Buffer.from(canonicalize(material), "utf8"))}`;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function normalizePublicKeyPem(value) {
|
|
683
|
+
const pem = String(value || "").replace(/\r\n/g, "\n").trim();
|
|
684
|
+
if (!pem.includes("BEGIN PUBLIC KEY")) {
|
|
685
|
+
throw new Error("native public key must be SPKI PEM");
|
|
686
|
+
}
|
|
687
|
+
return `${pem}\n`;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function normalizePrivateKeyPem(value) {
|
|
691
|
+
const pem = String(value || "").replace(/\r\n/g, "\n").trim();
|
|
692
|
+
if (!pem.includes("BEGIN PRIVATE KEY")) {
|
|
693
|
+
throw new Error("native private key must be PKCS8 PEM");
|
|
694
|
+
}
|
|
695
|
+
return `${pem}\n`;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
function nativePublicKeyRefFromPem(publicKeyPem, signatureSuite = "ed25519") {
|
|
699
|
+
const suite = getNativeSignatureSuite(signatureSuite);
|
|
700
|
+
if (!suite) {
|
|
701
|
+
throw new Error("native signature suite unsupported");
|
|
702
|
+
}
|
|
703
|
+
if (suite.maturity !== "implemented") {
|
|
704
|
+
throw new Error("native signature suite not implemented");
|
|
705
|
+
}
|
|
706
|
+
const publicKey = crypto.createPublicKey(normalizePublicKeyPem(publicKeyPem));
|
|
707
|
+
const der = publicKey.export({ type: "spki", format: "der" });
|
|
708
|
+
return `${suite.id}-spki-sha256:${sha256Hex(der)}`;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
function nativeSigningHashForSuite(suite) {
|
|
712
|
+
return suite && suite.signing_hash ? suite.signing_hash : null;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
function assertNativeKeyMatchesSuite(keyObject, suite, label) {
|
|
716
|
+
if (suite && suite.curve) {
|
|
717
|
+
const details = keyObject.asymmetricKeyDetails || {};
|
|
718
|
+
if (details.namedCurve !== suite.curve) {
|
|
719
|
+
throw new Error(`${label} curve must be ${suite.curve}`);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function buildNativeSignedProofMaterial(receipt, canonicalEvent, proofDescriptor) {
|
|
725
|
+
return {
|
|
726
|
+
identity_ref: proofDescriptor.identity_ref,
|
|
727
|
+
method: XOONYA_NATIVE_SIGNED_METHOD,
|
|
728
|
+
public_key_ref: proofDescriptor.public_key_ref,
|
|
729
|
+
receipt_signing_material: buildCanonicalReceiptSigningMaterial(receipt),
|
|
730
|
+
event_commitment: hashEvent(canonicalEvent),
|
|
731
|
+
signature_suite: proofDescriptor.signature_suite,
|
|
732
|
+
standard_version: XOONYA_NATIVE_PROOF_FORMAT_VERSION
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function buildNativeSignedReceiptProof(receipt, canonicalEvent, options = {}) {
|
|
737
|
+
const signatureSuite = normalizeString(options.signature_suite || options.native_signature_suite || "ed25519");
|
|
738
|
+
const suite = getNativeSignatureSuite(signatureSuite);
|
|
739
|
+
if (!suite) {
|
|
740
|
+
throw new Error("native signature suite unsupported");
|
|
741
|
+
}
|
|
742
|
+
if (suite.maturity !== "implemented") {
|
|
743
|
+
throw new Error("native signature suite not implemented");
|
|
744
|
+
}
|
|
745
|
+
const publicKeyPem = normalizePublicKeyPem(options.public_key_pem || options.native_public_key_pem);
|
|
746
|
+
const privateKeyPem = normalizePrivateKeyPem(options.private_key_pem || options.native_private_key_pem);
|
|
747
|
+
const publicKey = crypto.createPublicKey(publicKeyPem);
|
|
748
|
+
const privateKey = crypto.createPrivateKey(privateKeyPem);
|
|
749
|
+
assertNativeKeyMatchesSuite(publicKey, suite, "native public key");
|
|
750
|
+
assertNativeKeyMatchesSuite(privateKey, suite, "native private key");
|
|
751
|
+
const identityRef = normalizeString(options.identity_ref || options.native_identity_ref || receipt.agent_identity);
|
|
752
|
+
if (!identityRef) {
|
|
753
|
+
throw new Error("native identity_ref required");
|
|
754
|
+
}
|
|
755
|
+
const publicKeyRef = nativePublicKeyRefFromPem(publicKeyPem, suite.id);
|
|
756
|
+
const descriptor = {
|
|
757
|
+
identity_ref: identityRef,
|
|
758
|
+
public_key_ref: publicKeyRef,
|
|
759
|
+
signature_suite: suite.id
|
|
760
|
+
};
|
|
761
|
+
const signingMaterial = buildNativeSignedProofMaterial(receipt, canonicalEvent, descriptor);
|
|
762
|
+
const signingBytes = Buffer.from(canonicalize(signingMaterial), "utf8");
|
|
763
|
+
const signatureBytes = crypto.sign(nativeSigningHashForSuite(suite), signingBytes, privateKey);
|
|
764
|
+
const signature = base64urlEncode(signatureBytes);
|
|
765
|
+
return {
|
|
766
|
+
method: XOONYA_NATIVE_SIGNED_METHOD,
|
|
767
|
+
signature_suite: suite.id,
|
|
768
|
+
identity_ref: identityRef,
|
|
769
|
+
public_key_ref: publicKeyRef,
|
|
770
|
+
public_key_material: {
|
|
771
|
+
format: suite.public_key_format,
|
|
772
|
+
value: publicKeyPem
|
|
773
|
+
},
|
|
774
|
+
proof_material: {
|
|
775
|
+
signing_material_sha256: sha256Hex(signingBytes),
|
|
776
|
+
signature
|
|
777
|
+
},
|
|
778
|
+
compact_signature: `${XOONYA_NATIVE_SIGNED_METHOD}:${suite.id}:${signature}`
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function normalizeNativeAnchorRefs(anchorRefs, label = "native anchors") {
|
|
783
|
+
if (!Array.isArray(anchorRefs) || anchorRefs.length === 0) {
|
|
784
|
+
throw new Error(`${label} must be a non-empty array`);
|
|
785
|
+
}
|
|
786
|
+
if (anchorRefs.length > 32) {
|
|
787
|
+
throw new Error(`${label} must contain at most 32 entries`);
|
|
788
|
+
}
|
|
789
|
+
const normalized = anchorRefs.map((anchor, index) => {
|
|
790
|
+
if (!anchor || typeof anchor !== "object" || Array.isArray(anchor)) {
|
|
791
|
+
throw new Error(`${label}[${index}] must be an object`);
|
|
792
|
+
}
|
|
793
|
+
const entry = {
|
|
794
|
+
anchor_id: normalizeString(anchor.anchor_id || anchor.id),
|
|
795
|
+
anchor_kind: normalizeString(anchor.anchor_kind || anchor.kind),
|
|
796
|
+
anchor_ref: normalizeString(anchor.anchor_ref || anchor.ref),
|
|
797
|
+
anchor_hash_sha256: normalizeString(anchor.anchor_hash_sha256 || anchor.hash_sha256 || anchor.anchor_hash).toLowerCase()
|
|
798
|
+
};
|
|
799
|
+
if (!entry.anchor_id) throw new Error(`${label}[${index}].anchor_id required`);
|
|
800
|
+
if (!entry.anchor_kind) throw new Error(`${label}[${index}].anchor_kind required`);
|
|
801
|
+
if (!entry.anchor_ref) throw new Error(`${label}[${index}].anchor_ref required`);
|
|
802
|
+
entry.anchor_hash_sha256 = assertHex(entry.anchor_hash_sha256, 64, `${label}[${index}].anchor_hash_sha256`);
|
|
803
|
+
|
|
804
|
+
const network = normalizeString(anchor.network);
|
|
805
|
+
if (network) entry.network = network;
|
|
806
|
+
const finalityState = normalizeString(anchor.finality_state);
|
|
807
|
+
if (finalityState) entry.finality_state = finalityState;
|
|
808
|
+
const observedAtIso = normalizeString(anchor.observed_at_iso);
|
|
809
|
+
if (observedAtIso) entry.observed_at_iso = observedAtIso;
|
|
810
|
+
const providerRef = normalizeString(anchor.provider_ref);
|
|
811
|
+
if (providerRef) entry.provider_ref = providerRef;
|
|
812
|
+
const inclusionProofRef = normalizeString(anchor.inclusion_proof_ref);
|
|
813
|
+
if (inclusionProofRef) entry.inclusion_proof_ref = inclusionProofRef;
|
|
814
|
+
return entry;
|
|
815
|
+
});
|
|
816
|
+
return normalized.sort((a, b) => canonicalize(a).localeCompare(canonicalize(b)));
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function buildNativeAnchorBindingMaterial(receipt, canonicalEvent, anchorRefs) {
|
|
820
|
+
const normalizedAnchors = normalizeNativeAnchorRefs(anchorRefs);
|
|
821
|
+
return {
|
|
822
|
+
anchor_refs: normalizedAnchors,
|
|
823
|
+
base_method: XOONYA_NATIVE_SHA256_METHOD,
|
|
824
|
+
event_commitment: hashEvent(canonicalEvent),
|
|
825
|
+
method: XOONYA_NATIVE_ANCHORED_METHOD,
|
|
826
|
+
receipt_signing_material: buildCanonicalReceiptSigningMaterial(receipt),
|
|
827
|
+
standard_version: XOONYA_NATIVE_PROOF_FORMAT_VERSION
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
function buildNativeAnchoredReceiptProof(receipt, canonicalEvent, options = {}) {
|
|
832
|
+
const anchorRefs = normalizeNativeAnchorRefs(options.anchors || options.native_anchor_refs || options.anchor_refs);
|
|
833
|
+
const bindingMaterial = buildNativeAnchorBindingMaterial(receipt, canonicalEvent, anchorRefs);
|
|
834
|
+
const bindingBytes = Buffer.from(canonicalize(bindingMaterial), "utf8");
|
|
835
|
+
const bindingHash = sha256Hex(bindingBytes);
|
|
836
|
+
const anchorRootHash = canonicalJsonSha256Hex(anchorRefs);
|
|
837
|
+
return {
|
|
838
|
+
method: XOONYA_NATIVE_ANCHORED_METHOD,
|
|
839
|
+
base_method: XOONYA_NATIVE_SHA256_METHOD,
|
|
840
|
+
anchor_refs: anchorRefs,
|
|
841
|
+
proof_material: {
|
|
842
|
+
anchor_root_sha256: anchorRootHash,
|
|
843
|
+
binding_material_sha256: bindingHash
|
|
844
|
+
},
|
|
845
|
+
compact_signature: `${XOONYA_NATIVE_ANCHORED_METHOD}:${bindingHash}`
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function verifyNativeSignedReceiptProof(receipt, ceb) {
|
|
850
|
+
try {
|
|
851
|
+
const proof = receipt.native_proof;
|
|
852
|
+
if (!proof || typeof proof !== "object" || Array.isArray(proof)) {
|
|
853
|
+
return { valid: false, reason: "native_proof_missing" };
|
|
854
|
+
}
|
|
855
|
+
if (normalizeString(proof.method) !== XOONYA_NATIVE_SIGNED_METHOD) {
|
|
856
|
+
return { valid: false, reason: "native_proof_method_mismatch" };
|
|
857
|
+
}
|
|
858
|
+
const signatureSuite = normalizeString(proof.signature_suite);
|
|
859
|
+
const suite = getNativeSignatureSuite(signatureSuite);
|
|
860
|
+
if (!suite) {
|
|
861
|
+
return { valid: false, reason: "native_signature_suite_unsupported" };
|
|
862
|
+
}
|
|
863
|
+
if (suite.maturity !== "implemented") {
|
|
864
|
+
return { valid: false, reason: "native_signature_suite_not_implemented" };
|
|
865
|
+
}
|
|
866
|
+
const identityRef = normalizeString(proof.identity_ref);
|
|
867
|
+
if (!identityRef) {
|
|
868
|
+
return { valid: false, reason: "native_identity_ref_missing" };
|
|
869
|
+
}
|
|
870
|
+
const publicKeyMaterial = proof.public_key_material;
|
|
871
|
+
if (!publicKeyMaterial || typeof publicKeyMaterial !== "object" || Array.isArray(publicKeyMaterial)) {
|
|
872
|
+
return { valid: false, reason: "native_public_key_material_missing" };
|
|
873
|
+
}
|
|
874
|
+
if (normalizeString(publicKeyMaterial.format) !== suite.public_key_format) {
|
|
875
|
+
return { valid: false, reason: "native_public_key_format_mismatch" };
|
|
876
|
+
}
|
|
877
|
+
const publicKeyPem = normalizePublicKeyPem(publicKeyMaterial.value);
|
|
878
|
+
const publicKey = crypto.createPublicKey(publicKeyPem);
|
|
879
|
+
assertNativeKeyMatchesSuite(publicKey, suite, "native public key");
|
|
880
|
+
const expectedPublicKeyRef = nativePublicKeyRefFromPem(publicKeyPem, suite.id);
|
|
881
|
+
if (normalizeString(proof.public_key_ref) !== expectedPublicKeyRef) {
|
|
882
|
+
return { valid: false, reason: "native_public_key_ref_mismatch" };
|
|
883
|
+
}
|
|
884
|
+
const proofMaterial = proof.proof_material;
|
|
885
|
+
if (!proofMaterial || typeof proofMaterial !== "object" || Array.isArray(proofMaterial)) {
|
|
886
|
+
return { valid: false, reason: "native_proof_material_missing" };
|
|
887
|
+
}
|
|
888
|
+
const signature = normalizeString(proofMaterial.signature);
|
|
889
|
+
if (!signature) {
|
|
890
|
+
return { valid: false, reason: "native_signature_missing" };
|
|
891
|
+
}
|
|
892
|
+
const expectedCompactSignature = `${XOONYA_NATIVE_SIGNED_METHOD}:${suite.id}:${signature}`;
|
|
893
|
+
if (normalizeString(receipt.signature) !== expectedCompactSignature) {
|
|
894
|
+
return { valid: false, reason: "signature_native_signed_mismatch" };
|
|
895
|
+
}
|
|
896
|
+
const signingMaterial = buildNativeSignedProofMaterial(receipt, ceb, {
|
|
897
|
+
identity_ref: identityRef,
|
|
898
|
+
public_key_ref: expectedPublicKeyRef,
|
|
899
|
+
signature_suite: suite.id
|
|
900
|
+
});
|
|
901
|
+
const signingBytes = Buffer.from(canonicalize(signingMaterial), "utf8");
|
|
902
|
+
const expectedSigningHash = sha256Hex(signingBytes);
|
|
903
|
+
if (normalizeString(proofMaterial.signing_material_sha256).toLowerCase() !== expectedSigningHash) {
|
|
904
|
+
return { valid: false, reason: "native_signing_material_hash_mismatch" };
|
|
905
|
+
}
|
|
906
|
+
const signatureBytes = base64urlDecode(signature, "native signature");
|
|
907
|
+
const verified = crypto.verify(nativeSigningHashForSuite(suite), signingBytes, publicKey, signatureBytes);
|
|
908
|
+
if (!verified) {
|
|
909
|
+
return { valid: false, reason: "native_signature_invalid" };
|
|
910
|
+
}
|
|
911
|
+
return {
|
|
912
|
+
valid: true,
|
|
913
|
+
verification_state: "verified_native_signature",
|
|
914
|
+
signature_suite: suite.id
|
|
915
|
+
};
|
|
916
|
+
} catch (error) {
|
|
917
|
+
return { valid: false, reason: error.message };
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
function verifyNativeAnchoredReceiptProof(receipt, ceb, bundle) {
|
|
922
|
+
try {
|
|
923
|
+
const proof = receipt.native_proof;
|
|
924
|
+
if (!proof || typeof proof !== "object" || Array.isArray(proof)) {
|
|
925
|
+
return { valid: false, reason: "native_proof_missing" };
|
|
926
|
+
}
|
|
927
|
+
if (normalizeString(proof.method) !== XOONYA_NATIVE_ANCHORED_METHOD) {
|
|
928
|
+
return { valid: false, reason: "native_proof_method_mismatch" };
|
|
929
|
+
}
|
|
930
|
+
if (normalizeString(proof.base_method) !== XOONYA_NATIVE_SHA256_METHOD) {
|
|
931
|
+
return { valid: false, reason: "native_anchor_base_method_unsupported" };
|
|
932
|
+
}
|
|
933
|
+
if (!bundle || !Array.isArray(bundle.anchors)) {
|
|
934
|
+
return { valid: false, reason: "native_anchor_bundle_missing" };
|
|
935
|
+
}
|
|
936
|
+
const proofAnchors = normalizeNativeAnchorRefs(proof.anchor_refs);
|
|
937
|
+
const bundleAnchors = normalizeNativeAnchorRefs(bundle.anchors);
|
|
938
|
+
if (canonicalize(proofAnchors) !== canonicalize(bundleAnchors)) {
|
|
939
|
+
return { valid: false, reason: "native_anchor_bundle_mismatch" };
|
|
940
|
+
}
|
|
941
|
+
const proofMaterial = proof.proof_material;
|
|
942
|
+
if (!proofMaterial || typeof proofMaterial !== "object" || Array.isArray(proofMaterial)) {
|
|
943
|
+
return { valid: false, reason: "native_anchor_proof_material_missing" };
|
|
944
|
+
}
|
|
945
|
+
const expectedAnchorRoot = canonicalJsonSha256Hex(proofAnchors);
|
|
946
|
+
if (normalizeString(proofMaterial.anchor_root_sha256).toLowerCase() !== expectedAnchorRoot) {
|
|
947
|
+
return { valid: false, reason: "native_anchor_root_mismatch" };
|
|
948
|
+
}
|
|
949
|
+
const bindingMaterial = buildNativeAnchorBindingMaterial(receipt, ceb, proofAnchors);
|
|
950
|
+
const bindingHash = sha256Hex(Buffer.from(canonicalize(bindingMaterial), "utf8"));
|
|
951
|
+
if (normalizeString(proofMaterial.binding_material_sha256).toLowerCase() !== bindingHash) {
|
|
952
|
+
return { valid: false, reason: "native_anchor_binding_hash_mismatch" };
|
|
953
|
+
}
|
|
954
|
+
if (normalizeString(receipt.signature) !== `${XOONYA_NATIVE_ANCHORED_METHOD}:${bindingHash}`) {
|
|
955
|
+
return { valid: false, reason: "signature_native_anchored_mismatch" };
|
|
956
|
+
}
|
|
957
|
+
return {
|
|
958
|
+
valid: true,
|
|
959
|
+
verification_state: "verified_native_anchor_binding",
|
|
960
|
+
anchor_count: proofAnchors.length,
|
|
961
|
+
anchor_root_sha256: expectedAnchorRoot
|
|
962
|
+
};
|
|
963
|
+
} catch (error) {
|
|
964
|
+
return { valid: false, reason: error.message };
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
145
968
|
function emitReceipt(event, options = {}) {
|
|
146
969
|
const canonicalEvent = canonicalizeEvent(event);
|
|
147
970
|
const eventCommitment = hashEvent(canonicalEvent);
|
|
@@ -184,7 +1007,7 @@ function emitReceipt(event, options = {}) {
|
|
|
184
1007
|
domain_id: canonicalEvent.domain_id,
|
|
185
1008
|
sequence: canonicalEvent.sequence,
|
|
186
1009
|
event_commitment: eventCommitment,
|
|
187
|
-
algorithm:
|
|
1010
|
+
algorithm: selectReceiptAlgorithm(options, compatibility)
|
|
188
1011
|
};
|
|
189
1012
|
|
|
190
1013
|
if (compatibility) {
|
|
@@ -192,9 +1015,25 @@ function emitReceipt(event, options = {}) {
|
|
|
192
1015
|
}
|
|
193
1016
|
|
|
194
1017
|
let signature = options.signature == null ? "" : normalizeString(options.signature);
|
|
1018
|
+
let nativeProof = options.native_proof && typeof options.native_proof === "object" && !Array.isArray(options.native_proof)
|
|
1019
|
+
? options.native_proof
|
|
1020
|
+
: null;
|
|
195
1021
|
if (!signature && typeof options.signer === "function") {
|
|
196
1022
|
signature = normalizeString(options.signer(buildCanonicalReceiptSigningMaterial(unsignedReceipt), canonicalEvent));
|
|
197
1023
|
}
|
|
1024
|
+
if (!signature && unsignedReceipt.algorithm === XOONYA_NATIVE_SIGNED_METHOD) {
|
|
1025
|
+
nativeProof = buildNativeSignedReceiptProof(unsignedReceipt, canonicalEvent, options);
|
|
1026
|
+
signature = nativeProof.compact_signature;
|
|
1027
|
+
delete nativeProof.compact_signature;
|
|
1028
|
+
}
|
|
1029
|
+
if (!signature && unsignedReceipt.algorithm === XOONYA_NATIVE_ANCHORED_METHOD) {
|
|
1030
|
+
nativeProof = buildNativeAnchoredReceiptProof(unsignedReceipt, canonicalEvent, options);
|
|
1031
|
+
signature = nativeProof.compact_signature;
|
|
1032
|
+
delete nativeProof.compact_signature;
|
|
1033
|
+
}
|
|
1034
|
+
if (!signature && unsignedReceipt.algorithm === XOONYA_NATIVE_SHA256_METHOD) {
|
|
1035
|
+
signature = buildNativeReceiptSignature(unsignedReceipt, canonicalEvent);
|
|
1036
|
+
}
|
|
198
1037
|
if (!signature && compatibility) {
|
|
199
1038
|
signature = compatibility.legacy_receipt.opreturn_hex;
|
|
200
1039
|
}
|
|
@@ -204,21 +1043,134 @@ function emitReceipt(event, options = {}) {
|
|
|
204
1043
|
|
|
205
1044
|
return {
|
|
206
1045
|
...unsignedReceipt,
|
|
1046
|
+
...(nativeProof ? { native_proof: nativeProof } : {}),
|
|
207
1047
|
signature
|
|
208
1048
|
};
|
|
209
1049
|
}
|
|
210
1050
|
|
|
1051
|
+
function verifyReceiptProofMethod(receipt, ceb, bundle) {
|
|
1052
|
+
const algorithm = normalizeString(receipt.algorithm);
|
|
1053
|
+
if (!algorithm) {
|
|
1054
|
+
return { valid: false, reason: "verification_method_missing" };
|
|
1055
|
+
}
|
|
1056
|
+
if (algorithm === VERIFICATION_METHOD_NONE) {
|
|
1057
|
+
return { valid: false, reason: "verification_method_none" };
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
const method = PROOF_VERIFICATION_METHODS[algorithm];
|
|
1061
|
+
if (!method) {
|
|
1062
|
+
return { valid: false, reason: "verification_method_unsupported" };
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
const legacyReceipt = receipt.compatibility && receipt.compatibility.legacy_receipt;
|
|
1066
|
+
if (legacyReceipt && algorithm !== LEGACY_OPRETURN_METHOD) {
|
|
1067
|
+
return { valid: false, reason: "legacy_receipt_method_mismatch" };
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
if (algorithm === LEGACY_OPRETURN_METHOD) {
|
|
1071
|
+
if (!legacyReceipt) {
|
|
1072
|
+
return { valid: false, reason: "legacy_receipt_missing" };
|
|
1073
|
+
}
|
|
1074
|
+
const legacyVerification = verifyReceipt(
|
|
1075
|
+
legacyReceipt.opreturn_hex,
|
|
1076
|
+
Buffer.from(canonicalize(ceb), "utf8")
|
|
1077
|
+
);
|
|
1078
|
+
if (!legacyVerification.valid) {
|
|
1079
|
+
return { valid: false, reason: `legacy_receipt_${legacyVerification.reason}` };
|
|
1080
|
+
}
|
|
1081
|
+
if (normalizeString(legacyReceipt.agent_id).toLowerCase() !== normalizeString(legacyVerification.agent_id).toLowerCase()) {
|
|
1082
|
+
return { valid: false, reason: "legacy_agent_id_mismatch" };
|
|
1083
|
+
}
|
|
1084
|
+
if (normalizeString(receipt.signature).toLowerCase() !== normalizeString(legacyReceipt.opreturn_hex).toLowerCase()) {
|
|
1085
|
+
return { valid: false, reason: "signature_legacy_mismatch" };
|
|
1086
|
+
}
|
|
1087
|
+
return {
|
|
1088
|
+
valid: true,
|
|
1089
|
+
method,
|
|
1090
|
+
verification_state: "verified_legacy_opreturn"
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
if (algorithm === XOONYA_NATIVE_SHA256_METHOD) {
|
|
1095
|
+
const expectedSignature = buildNativeReceiptSignature(receipt, ceb);
|
|
1096
|
+
if (normalizeString(receipt.signature) !== expectedSignature) {
|
|
1097
|
+
return { valid: false, reason: "signature_native_mismatch" };
|
|
1098
|
+
}
|
|
1099
|
+
return {
|
|
1100
|
+
valid: true,
|
|
1101
|
+
method,
|
|
1102
|
+
verification_state: "verified_native_digest"
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
if (algorithm === XOONYA_NATIVE_SIGNED_METHOD) {
|
|
1107
|
+
const verification = verifyNativeSignedReceiptProof(receipt, ceb);
|
|
1108
|
+
if (!verification.valid) {
|
|
1109
|
+
return { valid: false, reason: verification.reason };
|
|
1110
|
+
}
|
|
1111
|
+
return {
|
|
1112
|
+
valid: true,
|
|
1113
|
+
method,
|
|
1114
|
+
verification_state: verification.verification_state,
|
|
1115
|
+
signature_suite: verification.signature_suite
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
if (algorithm === XOONYA_NATIVE_ANCHORED_METHOD) {
|
|
1120
|
+
const verification = verifyNativeAnchoredReceiptProof(receipt, ceb, bundle);
|
|
1121
|
+
if (!verification.valid) {
|
|
1122
|
+
return { valid: false, reason: verification.reason };
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
valid: true,
|
|
1126
|
+
method,
|
|
1127
|
+
verification_state: verification.verification_state,
|
|
1128
|
+
anchor_count: verification.anchor_count,
|
|
1129
|
+
anchor_root_sha256: verification.anchor_root_sha256
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
if (isExternalAssertionMethod(algorithm)) {
|
|
1134
|
+
const signature = normalizeString(receipt.signature);
|
|
1135
|
+
if (
|
|
1136
|
+
signature.startsWith(`${XOONYA_NATIVE_SHA256_METHOD}:`) ||
|
|
1137
|
+
signature.startsWith(`${XOONYA_NATIVE_SIGNED_METHOD}:`) ||
|
|
1138
|
+
signature.startsWith(`${XOONYA_NATIVE_ANCHORED_METHOD}:`)
|
|
1139
|
+
) {
|
|
1140
|
+
return { valid: false, reason: "signature_method_mismatch" };
|
|
1141
|
+
}
|
|
1142
|
+
return {
|
|
1143
|
+
valid: true,
|
|
1144
|
+
method,
|
|
1145
|
+
verification_state: algorithm === DETACHED_ASSERTION_METHOD
|
|
1146
|
+
? "accepted_detached_assertion"
|
|
1147
|
+
: "accepted_external_proof_envelope"
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
return { valid: false, reason: "verification_method_unsupported" };
|
|
1152
|
+
}
|
|
1153
|
+
|
|
211
1154
|
function buildProofBundle(input) {
|
|
212
1155
|
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
213
1156
|
throw new Error("input must be an object");
|
|
214
1157
|
}
|
|
215
1158
|
const ceb = canonicalizeEvent(input.ceb || input.event);
|
|
216
|
-
const
|
|
1159
|
+
const anchors = Array.isArray(input.anchors) ? input.anchors : undefined;
|
|
1160
|
+
const receiptOptions = input.receipt_options && typeof input.receipt_options === "object" && !Array.isArray(input.receipt_options)
|
|
1161
|
+
? input.receipt_options
|
|
1162
|
+
: {};
|
|
1163
|
+
const receipt = input.receipt || emitReceipt(ceb, {
|
|
1164
|
+
...receiptOptions,
|
|
1165
|
+
...(anchors && receiptOptions.anchors == null && receiptOptions.native_anchor_refs == null && receiptOptions.anchor_refs == null
|
|
1166
|
+
? { anchors }
|
|
1167
|
+
: {})
|
|
1168
|
+
});
|
|
217
1169
|
return {
|
|
218
1170
|
version: PROOF_BUNDLE_VERSION,
|
|
219
1171
|
ceb,
|
|
220
1172
|
receipt,
|
|
221
|
-
anchors
|
|
1173
|
+
anchors,
|
|
222
1174
|
attestations: Array.isArray(input.attestations) ? input.attestations : undefined,
|
|
223
1175
|
evidence_refs: Array.isArray(input.evidence_refs) ? input.evidence_refs : undefined,
|
|
224
1176
|
batch_refs: Array.isArray(input.batch_refs) ? input.batch_refs : undefined,
|
|
@@ -272,21 +1224,9 @@ function verifyProofBundle(bundle) {
|
|
|
272
1224
|
return { valid: false, reason: "signature_missing" };
|
|
273
1225
|
}
|
|
274
1226
|
|
|
275
|
-
const
|
|
276
|
-
if (
|
|
277
|
-
|
|
278
|
-
legacyReceipt.opreturn_hex,
|
|
279
|
-
Buffer.from(canonicalize(ceb), "utf8")
|
|
280
|
-
);
|
|
281
|
-
if (!legacyVerification.valid) {
|
|
282
|
-
return { valid: false, reason: `legacy_receipt_${legacyVerification.reason}` };
|
|
283
|
-
}
|
|
284
|
-
if (normalizeString(legacyReceipt.agent_id).toLowerCase() !== normalizeString(legacyVerification.agent_id).toLowerCase()) {
|
|
285
|
-
return { valid: false, reason: "legacy_agent_id_mismatch" };
|
|
286
|
-
}
|
|
287
|
-
if (normalizeString(receipt.signature).toLowerCase() !== normalizeString(legacyReceipt.opreturn_hex).toLowerCase()) {
|
|
288
|
-
return { valid: false, reason: "signature_legacy_mismatch" };
|
|
289
|
-
}
|
|
1227
|
+
const methodVerification = verifyReceiptProofMethod(receipt, ceb, bundle);
|
|
1228
|
+
if (!methodVerification.valid) {
|
|
1229
|
+
return { valid: false, reason: methodVerification.reason };
|
|
290
1230
|
}
|
|
291
1231
|
|
|
292
1232
|
return {
|
|
@@ -294,7 +1234,13 @@ function verifyProofBundle(bundle) {
|
|
|
294
1234
|
reason: null,
|
|
295
1235
|
version: PROOF_BUNDLE_VERSION,
|
|
296
1236
|
event_commitment: expectedCommitment,
|
|
297
|
-
receipt_id: expectedReceiptId
|
|
1237
|
+
receipt_id: expectedReceiptId,
|
|
1238
|
+
verification_method: methodVerification.method.id,
|
|
1239
|
+
verification_method_family: methodVerification.method.family,
|
|
1240
|
+
verification_state: methodVerification.verification_state,
|
|
1241
|
+
...(methodVerification.anchor_count != null ? { anchor_count: methodVerification.anchor_count } : {}),
|
|
1242
|
+
...(methodVerification.anchor_root_sha256 ? { anchor_root_sha256: methodVerification.anchor_root_sha256 } : {}),
|
|
1243
|
+
...(methodVerification.signature_suite ? { signature_suite: methodVerification.signature_suite } : {})
|
|
298
1244
|
};
|
|
299
1245
|
} catch (error) {
|
|
300
1246
|
return { valid: false, reason: error.message };
|
|
@@ -513,27 +1459,292 @@ function verifyReceiptV2(opreturnHex, payloadBytes) {
|
|
|
513
1459
|
};
|
|
514
1460
|
}
|
|
515
1461
|
|
|
516
|
-
function
|
|
517
|
-
const
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
1462
|
+
function normalizeXoonyaNativeAtomType(typeHex = TYPE_REGISTER) {
|
|
1463
|
+
const type = assertHex(typeHex, 2, "typeHex");
|
|
1464
|
+
if (!VALID_TYPES.has(type)) {
|
|
1465
|
+
throw new Error("typeHex must be 01, 02, or 03");
|
|
1466
|
+
}
|
|
1467
|
+
return type;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
function atomValidationError(code, message) {
|
|
1471
|
+
const error = new Error(message);
|
|
1472
|
+
error.code = code;
|
|
1473
|
+
return error;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
function normalizeXoonyaNativeIdentityMaterial(identityMaterialHex) {
|
|
1477
|
+
const materialHex = assertVariableHex(identityMaterialHex, "identityMaterialHex");
|
|
1478
|
+
const typePrefix = materialHex.slice(0, 2);
|
|
1479
|
+
if (!XOONYA_NATIVE_IDENTITY_TYPES[typePrefix]) {
|
|
1480
|
+
throw atomValidationError(
|
|
1481
|
+
XNYA_NATIVE_ATOM_ERROR_CODES.IDENTITY_UNSUPPORTED_TYPE_PREFIX,
|
|
1482
|
+
"identityMaterialHex has unsupported identity type prefix"
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1485
|
+
if (materialHex.length === 2) {
|
|
1486
|
+
throw atomValidationError(
|
|
1487
|
+
XNYA_NATIVE_ATOM_ERROR_CODES.IDENTITY_MISSING_RAW_BYTES,
|
|
1488
|
+
"identityMaterialHex must include raw identity bytes"
|
|
1489
|
+
);
|
|
1490
|
+
}
|
|
1491
|
+
return materialHex;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
function hashXoonyaNativePayload(payloadBytes, domainSeparator) {
|
|
1495
|
+
if (!payloadBytes || payloadBytes.length === 0) {
|
|
1496
|
+
return ZERO_HASH32;
|
|
1497
|
+
}
|
|
1498
|
+
const digest = sha256Hex(Buffer.concat([
|
|
1499
|
+
Buffer.from(domainSeparator, "utf8"),
|
|
1500
|
+
Buffer.from(payloadBytes)
|
|
1501
|
+
]));
|
|
1502
|
+
if (digest === ZERO_HASH32) {
|
|
1503
|
+
throw new Error("payload hash cannot equal the absent-payload sentinel");
|
|
1504
|
+
}
|
|
1505
|
+
return digest;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
function createXoonyaNativeAtomV1(identityMaterialHex, payloadBytes, typeHex = TYPE_REGISTER) {
|
|
1509
|
+
const materialHex = normalizeXoonyaNativeIdentityMaterial(identityMaterialHex);
|
|
1510
|
+
const type = normalizeXoonyaNativeAtomType(typeHex);
|
|
1511
|
+
const agentId = hash160Hex(Buffer.concat([
|
|
1512
|
+
Buffer.from(XNYA_DS_AGENT_V1, "utf8"),
|
|
1513
|
+
Buffer.from(materialHex, "hex")
|
|
1514
|
+
]));
|
|
1515
|
+
const payloadHash = hashXoonyaNativePayload(payloadBytes, XNYA_DS_PAYLOAD_V1);
|
|
1516
|
+
const atomHex = XOONYA_NATIVE_ATOM_MAGIC_HEX + VERSION_V1_HEX + type + agentId + payloadHash;
|
|
1517
|
+
return {
|
|
1518
|
+
atom_hex: atomHex,
|
|
1519
|
+
magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
1520
|
+
atom_version: XOONYA_NATIVE_ATOM_V1,
|
|
1521
|
+
spec_version: "v1",
|
|
1522
|
+
byte_length: 58,
|
|
1523
|
+
record_type_hex: type,
|
|
1524
|
+
agent_id: agentId,
|
|
1525
|
+
payload_hash_sha256: payloadHash,
|
|
1526
|
+
identity_type_prefix: materialHex.slice(0, 2),
|
|
1527
|
+
domain_separation: {
|
|
1528
|
+
agent: XNYA_DS_AGENT_V1,
|
|
1529
|
+
payload: XNYA_DS_PAYLOAD_V1
|
|
1530
|
+
}
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
function createXoonyaNativeAtomV2(identityMaterialHex, payloadBytes, typeHex = TYPE_REGISTER) {
|
|
1535
|
+
const materialHex = normalizeXoonyaNativeIdentityMaterial(identityMaterialHex);
|
|
1536
|
+
const type = normalizeXoonyaNativeAtomType(typeHex);
|
|
1537
|
+
const agentId = sha256Hex(Buffer.concat([
|
|
1538
|
+
Buffer.from(XNYA_DS_AGENT_V2, "utf8"),
|
|
1539
|
+
Buffer.from(materialHex, "hex")
|
|
1540
|
+
]));
|
|
1541
|
+
const payloadHash = hashXoonyaNativePayload(payloadBytes, XNYA_DS_PAYLOAD_V2);
|
|
1542
|
+
const atomHex = XOONYA_NATIVE_ATOM_MAGIC_HEX + VERSION_V2_HEX + type + agentId + payloadHash;
|
|
1543
|
+
return {
|
|
1544
|
+
atom_hex: atomHex,
|
|
1545
|
+
magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
1546
|
+
atom_version: XOONYA_NATIVE_ATOM_V2,
|
|
1547
|
+
spec_version: "v2",
|
|
1548
|
+
byte_length: 70,
|
|
1549
|
+
record_type_hex: type,
|
|
1550
|
+
agent_id: agentId,
|
|
1551
|
+
payload_hash_sha256: payloadHash,
|
|
1552
|
+
identity_type_prefix: materialHex.slice(0, 2),
|
|
1553
|
+
domain_separation: {
|
|
1554
|
+
agent: XNYA_DS_AGENT_V2,
|
|
1555
|
+
payload: XNYA_DS_PAYLOAD_V2
|
|
1556
|
+
}
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
function parseXoonyaNativeAtom(atomHex) {
|
|
1561
|
+
const hex = String(atomHex || "").trim().toLowerCase();
|
|
1562
|
+
if (!/^[a-f0-9]+$/.test(hex)) {
|
|
1563
|
+
throw atomValidationError(XNYA_NATIVE_ATOM_ERROR_CODES.ATOM_HEX_NOT_HEX, "atomHex must be hex");
|
|
1564
|
+
}
|
|
1565
|
+
if (hex.length !== 116 && hex.length !== 140) {
|
|
1566
|
+
throw atomValidationError(
|
|
1567
|
+
XNYA_NATIVE_ATOM_ERROR_CODES.ATOM_UNSUPPORTED_LENGTH,
|
|
1568
|
+
"atomHex must be a supported Xoonya native atom"
|
|
1569
|
+
);
|
|
1570
|
+
}
|
|
1571
|
+
const magic = hex.slice(0, 8);
|
|
1572
|
+
const version = hex.slice(8, 10);
|
|
1573
|
+
const recordType = hex.slice(10, 12);
|
|
1574
|
+
if (magic !== XOONYA_NATIVE_ATOM_MAGIC_HEX.toLowerCase()) {
|
|
1575
|
+
throw atomValidationError(
|
|
1576
|
+
XNYA_NATIVE_ATOM_ERROR_CODES.ATOM_BAD_MAGIC,
|
|
1577
|
+
"atomHex has bad Xoonya native atom magic"
|
|
1578
|
+
);
|
|
1579
|
+
}
|
|
1580
|
+
if (!VALID_TYPES.has(recordType)) {
|
|
1581
|
+
throw atomValidationError(
|
|
1582
|
+
XNYA_NATIVE_ATOM_ERROR_CODES.ATOM_UNSUPPORTED_RECORD_TYPE,
|
|
1583
|
+
"atomHex has unsupported record type"
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
if (version === VERSION_V1_HEX && hex.length === 116) {
|
|
1587
|
+
const agentId = hex.slice(12, 52);
|
|
1588
|
+
const payloadHash = hex.slice(52, 116);
|
|
1589
|
+
return {
|
|
1590
|
+
atom_version: XOONYA_NATIVE_ATOM_V1,
|
|
1591
|
+
spec_version: "v1",
|
|
1592
|
+
byte_length: 58,
|
|
1593
|
+
record_type_hex: recordType,
|
|
1594
|
+
agent_id: agentId,
|
|
1595
|
+
payload_hash_sha256: payloadHash,
|
|
1596
|
+
atom_hash_sha256: sha256Hex(Buffer.from(hex, "hex")),
|
|
1597
|
+
atom_hex: hex
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
if (version === VERSION_V2_HEX && hex.length === 140) {
|
|
1601
|
+
const agentId = hex.slice(12, 76);
|
|
1602
|
+
const payloadHash = hex.slice(76, 140);
|
|
1603
|
+
return {
|
|
1604
|
+
atom_version: XOONYA_NATIVE_ATOM_V2,
|
|
1605
|
+
spec_version: "v2",
|
|
1606
|
+
byte_length: 70,
|
|
1607
|
+
record_type_hex: recordType,
|
|
1608
|
+
agent_id: agentId,
|
|
1609
|
+
payload_hash_sha256: payloadHash,
|
|
1610
|
+
atom_hash_sha256: sha256Hex(Buffer.from(hex, "hex")),
|
|
1611
|
+
atom_hex: hex
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
throw atomValidationError(
|
|
1615
|
+
XNYA_NATIVE_ATOM_ERROR_CODES.ATOM_VERSION_LENGTH_MISMATCH,
|
|
1616
|
+
"atomHex/version length mismatch"
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
function verifyXoonyaNativeAtom(atomHex, options = {}) {
|
|
1621
|
+
try {
|
|
1622
|
+
const parsed = parseXoonyaNativeAtom(atomHex);
|
|
1623
|
+
const hasIdentityMaterial = options.identity_material_hex != null;
|
|
1624
|
+
if (hasIdentityMaterial) {
|
|
1625
|
+
const materialHex = normalizeXoonyaNativeIdentityMaterial(options.identity_material_hex);
|
|
1626
|
+
const expectedAgentId = parsed.spec_version === "v1"
|
|
1627
|
+
? hash160Hex(Buffer.concat([Buffer.from(XNYA_DS_AGENT_V1, "utf8"), Buffer.from(materialHex, "hex")]))
|
|
1628
|
+
: sha256Hex(Buffer.concat([Buffer.from(XNYA_DS_AGENT_V2, "utf8"), Buffer.from(materialHex, "hex")]));
|
|
1629
|
+
if (parsed.agent_id !== expectedAgentId) {
|
|
1630
|
+
return {
|
|
1631
|
+
valid: false,
|
|
1632
|
+
reason: "agent_id_mismatch",
|
|
1633
|
+
error_code: XNYA_NATIVE_ATOM_ERROR_CODES.AGENT_ID_MISMATCH,
|
|
1634
|
+
...parsed
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
const hasPayload = options.payload_bytes != null;
|
|
1640
|
+
if (hasPayload) {
|
|
1641
|
+
const payloadHash = parsed.spec_version === "v1"
|
|
1642
|
+
? hashXoonyaNativePayload(options.payload_bytes, XNYA_DS_PAYLOAD_V1)
|
|
1643
|
+
: hashXoonyaNativePayload(options.payload_bytes, XNYA_DS_PAYLOAD_V2);
|
|
1644
|
+
if (payloadHash !== parsed.payload_hash_sha256) {
|
|
1645
|
+
return {
|
|
1646
|
+
valid: false,
|
|
1647
|
+
reason: "payload_hash_mismatch",
|
|
1648
|
+
error_code: XNYA_NATIVE_ATOM_ERROR_CODES.PAYLOAD_HASH_MISMATCH,
|
|
1649
|
+
...parsed
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1652
|
+
} else if (parsed.payload_hash_sha256 === ZERO_HASH32) {
|
|
1653
|
+
return { valid: true, reason: null, error_code: null, payload_state: "absent", ...parsed };
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
return {
|
|
1657
|
+
valid: true,
|
|
1658
|
+
reason: null,
|
|
1659
|
+
error_code: null,
|
|
1660
|
+
payload_state: parsed.payload_hash_sha256 === ZERO_HASH32 ? "absent" : "committed",
|
|
1661
|
+
...parsed
|
|
1662
|
+
};
|
|
1663
|
+
} catch (error) {
|
|
1664
|
+
return { valid: false, reason: error.message, error_code: error.code || "native_atom_validation_error" };
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
function createXoonyaNativeLineRateFrameV1(atomHex) {
|
|
1669
|
+
const parsed = parseXoonyaNativeAtom(atomHex);
|
|
1670
|
+
const atomBytes = Buffer.from(parsed.atom_hex, "hex");
|
|
1671
|
+
const checksumHex = lineRateFrameChecksum(atomBytes);
|
|
1672
|
+
return {
|
|
1673
|
+
profile: XOONYA_NATIVE_LINE_RATE_FRAME_V1,
|
|
1674
|
+
frame_hex: `${parsed.atom_hex}${checksumHex}`,
|
|
1675
|
+
atom_hex: parsed.atom_hex,
|
|
1676
|
+
atom_version: parsed.atom_version,
|
|
1677
|
+
atom_byte_length: parsed.byte_length,
|
|
1678
|
+
frame_byte_length: parsed.byte_length + 2,
|
|
1679
|
+
checksum_hex: checksumHex,
|
|
1680
|
+
checksum_rule: "first_2_bytes_sha256(domain_separator || atom_bytes)"
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
function parseXoonyaNativeLineRateFrameV1(frameHex) {
|
|
1685
|
+
const hex = assertVariableHex(frameHex, "line-rate frame");
|
|
1686
|
+
const byteLength = hex.length / 2;
|
|
1687
|
+
if (![60, 72].includes(byteLength)) {
|
|
1688
|
+
throw new Error("line-rate frame unsupported length");
|
|
1689
|
+
}
|
|
1690
|
+
const atomHex = hex.slice(0, -4);
|
|
1691
|
+
const checksumHex = hex.slice(-4);
|
|
1692
|
+
const parsedAtom = parseXoonyaNativeAtom(atomHex);
|
|
1693
|
+
const expectedChecksum = lineRateFrameChecksum(Buffer.from(parsedAtom.atom_hex, "hex"));
|
|
1694
|
+
return {
|
|
1695
|
+
profile: XOONYA_NATIVE_LINE_RATE_FRAME_V1,
|
|
1696
|
+
frame_hex: hex,
|
|
1697
|
+
atom_hex: parsedAtom.atom_hex,
|
|
1698
|
+
atom_version: parsedAtom.atom_version,
|
|
1699
|
+
atom_byte_length: parsedAtom.byte_length,
|
|
1700
|
+
frame_byte_length: byteLength,
|
|
1701
|
+
checksum_hex: checksumHex,
|
|
1702
|
+
expected_checksum_hex: expectedChecksum,
|
|
1703
|
+
checksum_valid: checksumHex === expectedChecksum
|
|
1704
|
+
};
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
function verifyXoonyaNativeLineRateFrameV1(frameHex, options = {}) {
|
|
1708
|
+
try {
|
|
1709
|
+
const parsedFrame = parseXoonyaNativeLineRateFrameV1(frameHex);
|
|
1710
|
+
if (!parsedFrame.checksum_valid) {
|
|
1711
|
+
return { valid: false, reason: "line_rate_frame_checksum_mismatch", parsed_frame: parsedFrame };
|
|
1712
|
+
}
|
|
1713
|
+
const atomVerification = verifyXoonyaNativeAtom(parsedFrame.atom_hex, options);
|
|
1714
|
+
if (!atomVerification.valid) {
|
|
1715
|
+
return { valid: false, reason: `line_rate_frame_atom_${atomVerification.reason}`, parsed_frame: parsedFrame, atom_verification: atomVerification };
|
|
1716
|
+
}
|
|
1717
|
+
return {
|
|
1718
|
+
valid: true,
|
|
1719
|
+
parsed_frame: parsedFrame,
|
|
1720
|
+
atom_verification: atomVerification
|
|
1721
|
+
};
|
|
1722
|
+
} catch (error) {
|
|
1723
|
+
return { valid: false, reason: error.message };
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
function createProofEnvelopeV1(opreturnHex, proofs, metadata = {}) {
|
|
1728
|
+
const receiptRef = parseReceipt(opreturnHex);
|
|
1729
|
+
const normalizedProofs = Array.isArray(proofs) ? proofs.map(normalizeProofEntry) : [];
|
|
1730
|
+
if (normalizedProofs.length === 0) throw new Error("proofs must be a non-empty array");
|
|
1731
|
+
const proofIds = new Set();
|
|
1732
|
+
normalizedProofs.forEach((proof) => {
|
|
1733
|
+
if (proofIds.has(proof.proof_id)) throw new Error(`duplicate proof_id: ${proof.proof_id}`);
|
|
1734
|
+
proofIds.add(proof.proof_id);
|
|
1735
|
+
});
|
|
1736
|
+
return {
|
|
1737
|
+
envelope_version: PROOF_ENVELOPE_VERSION,
|
|
1738
|
+
receipt_ref: {
|
|
1739
|
+
opreturn_hex: receiptRef.opreturn_hex,
|
|
1740
|
+
spec_version: receiptRef.spec_version,
|
|
1741
|
+
receipt_hash_sha256: receiptRef.receipt_hash_sha256,
|
|
1742
|
+
payload_hash_sha256: receiptRef.payload_hash_sha256
|
|
1743
|
+
},
|
|
1744
|
+
proofs: normalizedProofs,
|
|
1745
|
+
binding_hash_sha256: canonicalJsonSha256Hex(makeProofEnvelopeBindingMaterial(receiptRef, normalizedProofs)),
|
|
1746
|
+
metadata: metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : {}
|
|
1747
|
+
};
|
|
537
1748
|
}
|
|
538
1749
|
|
|
539
1750
|
function verifyProofEnvelopeV1(envelope) {
|
|
@@ -746,8 +1957,12 @@ function buildDefaultProofCenter() {
|
|
|
746
1957
|
"verifyReceipt",
|
|
747
1958
|
"createReceiptV2",
|
|
748
1959
|
"verifyReceiptV2",
|
|
1960
|
+
"createXoonyaNativeAtomV1",
|
|
1961
|
+
"createXoonyaNativeAtomV2",
|
|
1962
|
+
"verifyXoonyaNativeAtom",
|
|
749
1963
|
"createProofEnvelopeV1",
|
|
750
|
-
"verifyProofEnvelopeV1"
|
|
1964
|
+
"verifyProofEnvelopeV1",
|
|
1965
|
+
"runExternalProofImport"
|
|
751
1966
|
],
|
|
752
1967
|
posture: "compatibility_helpers_preserved_but_not_public_center"
|
|
753
1968
|
},
|
|
@@ -756,14 +1971,16 @@ function buildDefaultProofCenter() {
|
|
|
756
1971
|
"/v1/events/hash",
|
|
757
1972
|
"/v1/receipts/emit",
|
|
758
1973
|
"/v1/proof-bundles/build",
|
|
759
|
-
"/v1/proof-bundles/verify"
|
|
1974
|
+
"/v1/proof-bundles/verify",
|
|
1975
|
+
"/v1/proof-center/import-adapter/run"
|
|
760
1976
|
],
|
|
761
1977
|
suggested_package_flow: [
|
|
762
1978
|
"canonicalizeEvent",
|
|
763
1979
|
"hashEvent",
|
|
764
1980
|
"emitReceipt",
|
|
765
1981
|
"buildProofBundle",
|
|
766
|
-
"verifyProofBundle"
|
|
1982
|
+
"verifyProofBundle",
|
|
1983
|
+
"runExternalProofImport"
|
|
767
1984
|
],
|
|
768
1985
|
proof_posture: {
|
|
769
1986
|
deterministic: true,
|
|
@@ -771,7 +1988,8 @@ function buildDefaultProofCenter() {
|
|
|
771
1988
|
replayable: true,
|
|
772
1989
|
settlement_agnostic: true,
|
|
773
1990
|
workflow_agnostic: true
|
|
774
|
-
}
|
|
1991
|
+
},
|
|
1992
|
+
verification_methods: listProofVerificationMethods()
|
|
775
1993
|
};
|
|
776
1994
|
}
|
|
777
1995
|
|
|
@@ -789,10 +2007,1097 @@ function summarizeDefaultProofCenter() {
|
|
|
789
2007
|
compatibility_helper_count: Array.isArray(center.compatibility_surface.preserved_helpers)
|
|
790
2008
|
? center.compatibility_surface.preserved_helpers.length
|
|
791
2009
|
: 0,
|
|
2010
|
+
verification_method_count: Array.isArray(center.verification_methods) ? center.verification_methods.length : 0,
|
|
2011
|
+
external_verification_method_count: Array.isArray(center.verification_methods)
|
|
2012
|
+
? center.verification_methods.filter((method) => method.verification_posture === "structure_verified_external_signature").length
|
|
2013
|
+
: 0,
|
|
2014
|
+
verification_methods: Array.isArray(center.verification_methods)
|
|
2015
|
+
? center.verification_methods.map((method) => method.id)
|
|
2016
|
+
: [],
|
|
792
2017
|
proof_posture: center.proof_posture
|
|
793
2018
|
};
|
|
794
2019
|
}
|
|
795
2020
|
|
|
2021
|
+
function normalizeExternalProofMaterial(value) {
|
|
2022
|
+
if (typeof value === "string") {
|
|
2023
|
+
const compact = normalizeString(value);
|
|
2024
|
+
if (!compact) {
|
|
2025
|
+
throw new Error("external_proof_material_empty");
|
|
2026
|
+
}
|
|
2027
|
+
return {
|
|
2028
|
+
material_kind: "compact",
|
|
2029
|
+
material: compact,
|
|
2030
|
+
canonical_material: compact,
|
|
2031
|
+
material_hash_sha256: sha256Hex(Buffer.from(compact, "utf8"))
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
2035
|
+
if (Object.keys(value).length === 0) {
|
|
2036
|
+
throw new Error("external_proof_material_empty");
|
|
2037
|
+
}
|
|
2038
|
+
const canonicalMaterial = canonicalize(value);
|
|
2039
|
+
return {
|
|
2040
|
+
material_kind: "object",
|
|
2041
|
+
material: value,
|
|
2042
|
+
canonical_material: canonicalMaterial,
|
|
2043
|
+
material_hash_sha256: sha256Hex(Buffer.from(canonicalMaterial, "utf8"))
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
throw new Error("external_proof_material_required");
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
function pickExternalProofMaterial(body) {
|
|
2050
|
+
if (body.external_proof != null) return body.external_proof;
|
|
2051
|
+
if (body.external_envelope != null) return body.external_envelope;
|
|
2052
|
+
if (body.proof_envelope != null) return body.proof_envelope;
|
|
2053
|
+
if (body.proof_material != null) return body.proof_material;
|
|
2054
|
+
if (body.token != null) return body.token;
|
|
2055
|
+
if (body.compact != null) return body.compact;
|
|
2056
|
+
return undefined;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
function normalizeExternalProofImport(input) {
|
|
2060
|
+
const body = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
2061
|
+
const method = normalizeString(body.method || body.verification_method || body.proof_method);
|
|
2062
|
+
if (!method) {
|
|
2063
|
+
throw new Error("verification_method_required");
|
|
2064
|
+
}
|
|
2065
|
+
const methodInfo = getProofVerificationMethod(method);
|
|
2066
|
+
if (!methodInfo) {
|
|
2067
|
+
throw new Error("verification_method_unsupported");
|
|
2068
|
+
}
|
|
2069
|
+
if (!EXTERNAL_PROOF_IMPORT_METHODS.includes(method)) {
|
|
2070
|
+
throw new Error("verification_method_not_external_importable");
|
|
2071
|
+
}
|
|
2072
|
+
const material = normalizeExternalProofMaterial(pickExternalProofMaterial(body));
|
|
2073
|
+
const declaredHash = normalizeString(body.declared_hash_sha256 || body.external_hash_sha256).toLowerCase();
|
|
2074
|
+
if (declaredHash && declaredHash !== material.material_hash_sha256) {
|
|
2075
|
+
throw new Error("external_proof_hash_mismatch");
|
|
2076
|
+
}
|
|
2077
|
+
const importRef = normalizeString(body.import_ref || body.external_ref || `external-proof.${material.material_hash_sha256.slice(0, 16)}`);
|
|
2078
|
+
const issuerRef = normalizeString(body.issuer_ref || body.issuer || `${method}.issuer`);
|
|
2079
|
+
const subjectRef = normalizeString(body.subject_ref || body.subject || importRef);
|
|
2080
|
+
const evidenceRefs = normalizeStringArray(body.evidence_refs, "evidence_refs") || [];
|
|
2081
|
+
const profileRefs = normalizeStringArray(body.profile_refs, "profile_refs") || [];
|
|
2082
|
+
const receivedAtIso = normalizeString(body.received_at_iso);
|
|
2083
|
+
const policyRef = normalizeString(body.policy_ref);
|
|
2084
|
+
return {
|
|
2085
|
+
method,
|
|
2086
|
+
method_family: methodInfo.family,
|
|
2087
|
+
verification_posture: methodInfo.verification_posture,
|
|
2088
|
+
import_ref: importRef,
|
|
2089
|
+
issuer_ref: issuerRef,
|
|
2090
|
+
subject_ref: subjectRef,
|
|
2091
|
+
material_kind: material.material_kind,
|
|
2092
|
+
external_proof_material_hash_sha256: material.material_hash_sha256,
|
|
2093
|
+
declared_hash_sha256: declaredHash || null,
|
|
2094
|
+
evidence_refs: evidenceRefs,
|
|
2095
|
+
profile_refs: profileRefs,
|
|
2096
|
+
received_at_iso: receivedAtIso || null,
|
|
2097
|
+
policy_ref: policyRef || null,
|
|
2098
|
+
material: material.material
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
function buildExternalProofImportAdapterPack() {
|
|
2103
|
+
return {
|
|
2104
|
+
ok: true,
|
|
2105
|
+
product: "xoonya",
|
|
2106
|
+
category: "xoonya-external-proof-import-adapter",
|
|
2107
|
+
adapter_version: "xoonya-external-proof-import-adapter-v1",
|
|
2108
|
+
posture: "method_agnostic_external_proof_intake_into_canonical_xoonya_bundles",
|
|
2109
|
+
supported_methods: EXTERNAL_PROOF_IMPORT_METHODS.map((method) => {
|
|
2110
|
+
const methodInfo = getProofVerificationMethod(method);
|
|
2111
|
+
return {
|
|
2112
|
+
method,
|
|
2113
|
+
family: methodInfo ? methodInfo.family : null,
|
|
2114
|
+
verification_posture: methodInfo ? methodInfo.verification_posture : null
|
|
2115
|
+
};
|
|
2116
|
+
}),
|
|
2117
|
+
required_fields: [
|
|
2118
|
+
"method",
|
|
2119
|
+
"external_proof"
|
|
2120
|
+
],
|
|
2121
|
+
optional_fields: [
|
|
2122
|
+
"import_ref",
|
|
2123
|
+
"external_ref",
|
|
2124
|
+
"issuer_ref",
|
|
2125
|
+
"subject_ref",
|
|
2126
|
+
"declared_hash_sha256",
|
|
2127
|
+
"evidence_refs",
|
|
2128
|
+
"profile_refs",
|
|
2129
|
+
"policy_ref",
|
|
2130
|
+
"received_at_iso"
|
|
2131
|
+
],
|
|
2132
|
+
output_artifacts: [
|
|
2133
|
+
"canonical_event",
|
|
2134
|
+
"receipt",
|
|
2135
|
+
"proof_bundle",
|
|
2136
|
+
"bundle_verification",
|
|
2137
|
+
"import_review"
|
|
2138
|
+
],
|
|
2139
|
+
verification_boundary: {
|
|
2140
|
+
xoonya_verifies: [
|
|
2141
|
+
"registered_method",
|
|
2142
|
+
"external_material_hash",
|
|
2143
|
+
"declared_hash_when_supplied",
|
|
2144
|
+
"canonical_event_binding",
|
|
2145
|
+
"proof_bundle_shape",
|
|
2146
|
+
"receipt_method_binding"
|
|
2147
|
+
],
|
|
2148
|
+
external_verifier_retains: [
|
|
2149
|
+
"issuer_cryptographic_truth",
|
|
2150
|
+
"credential_revocation_status",
|
|
2151
|
+
"did_resolution",
|
|
2152
|
+
"jwt_jws_signature_truth",
|
|
2153
|
+
"partner_policy_decision"
|
|
2154
|
+
]
|
|
2155
|
+
},
|
|
2156
|
+
linked_surfaces: {
|
|
2157
|
+
proof_center_ref: "/v1/proof-center",
|
|
2158
|
+
import_adapter_summary_ref: "/v1/proof-center/import-adapter/summary",
|
|
2159
|
+
import_review_ref: "/v1/proof-center/import-adapter/review",
|
|
2160
|
+
import_run_ref: "/v1/proof-center/import-adapter/run",
|
|
2161
|
+
native_standard_ref: "/v1/proof-center/native-standard"
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
function summarizeExternalProofImportAdapterPack() {
|
|
2167
|
+
const pack = buildExternalProofImportAdapterPack();
|
|
2168
|
+
return {
|
|
2169
|
+
ok: true,
|
|
2170
|
+
product: pack.product,
|
|
2171
|
+
category: "xoonya-external-proof-import-adapter-summary",
|
|
2172
|
+
summary_version: "xoonya-external-proof-import-adapter-summary-v1",
|
|
2173
|
+
posture: pack.posture,
|
|
2174
|
+
supported_method_count: pack.supported_methods.length,
|
|
2175
|
+
supported_methods: pack.supported_methods.map((entry) => entry.method),
|
|
2176
|
+
output_artifact_count: pack.output_artifacts.length,
|
|
2177
|
+
xoonya_verified_boundary_count: pack.verification_boundary.xoonya_verifies.length,
|
|
2178
|
+
external_verifier_boundary_count: pack.verification_boundary.external_verifier_retains.length,
|
|
2179
|
+
linked_surfaces: pack.linked_surfaces
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
function reviewExternalProofImport(input) {
|
|
2184
|
+
const imported = normalizeExternalProofImport(input);
|
|
2185
|
+
return {
|
|
2186
|
+
ok: true,
|
|
2187
|
+
product: "xoonya",
|
|
2188
|
+
category: "xoonya-external-proof-import-review",
|
|
2189
|
+
review_version: "xoonya-external-proof-import-review-v1",
|
|
2190
|
+
accepted: true,
|
|
2191
|
+
import_ref: imported.import_ref,
|
|
2192
|
+
method: imported.method,
|
|
2193
|
+
method_family: imported.method_family,
|
|
2194
|
+
verification_posture: imported.verification_posture,
|
|
2195
|
+
material_kind: imported.material_kind,
|
|
2196
|
+
external_proof_material_hash_sha256: imported.external_proof_material_hash_sha256,
|
|
2197
|
+
issuer_ref: imported.issuer_ref,
|
|
2198
|
+
subject_ref: imported.subject_ref,
|
|
2199
|
+
evidence_ref_count: imported.evidence_refs.length,
|
|
2200
|
+
profile_ref_count: imported.profile_refs.length,
|
|
2201
|
+
boundary: "xoonya_imports_and_binds_external_evidence_without_claiming_external_issuer_truth",
|
|
2202
|
+
run_surface: "/v1/proof-center/import-adapter/run"
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
function summarizeExternalProofImportReview(input) {
|
|
2207
|
+
const review = reviewExternalProofImport(input);
|
|
2208
|
+
return {
|
|
2209
|
+
ok: review.ok,
|
|
2210
|
+
category: "xoonya-external-proof-import-review-summary",
|
|
2211
|
+
import_ref: review.import_ref,
|
|
2212
|
+
method: review.method,
|
|
2213
|
+
method_family: review.method_family,
|
|
2214
|
+
accepted: review.accepted,
|
|
2215
|
+
material_hash_present: Boolean(review.external_proof_material_hash_sha256),
|
|
2216
|
+
evidence_ref_count: review.evidence_ref_count,
|
|
2217
|
+
boundary: review.boundary,
|
|
2218
|
+
run_surface: review.run_surface
|
|
2219
|
+
};
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
function buildExternalProofImportEvent(imported) {
|
|
2223
|
+
const importMaterial = {
|
|
2224
|
+
evidence_refs: imported.evidence_refs,
|
|
2225
|
+
external_proof_material_hash_sha256: imported.external_proof_material_hash_sha256,
|
|
2226
|
+
import_ref: imported.import_ref,
|
|
2227
|
+
issuer_ref: imported.issuer_ref,
|
|
2228
|
+
method: imported.method,
|
|
2229
|
+
method_family: imported.method_family,
|
|
2230
|
+
profile_refs: imported.profile_refs,
|
|
2231
|
+
subject_ref: imported.subject_ref
|
|
2232
|
+
};
|
|
2233
|
+
return canonicalizeEvent({
|
|
2234
|
+
version: CANONICAL_EVENT_BUNDLE_VERSION,
|
|
2235
|
+
domain_id: "xoonya.external_proof_import",
|
|
2236
|
+
sequence: imported.import_ref,
|
|
2237
|
+
actor_id: imported.issuer_ref,
|
|
2238
|
+
adapter_source: "xoonya.external_proof_import_adapter",
|
|
2239
|
+
event_type: `${imported.method}.imported`,
|
|
2240
|
+
event_hash: canonicalJsonSha256Hex(importMaterial),
|
|
2241
|
+
parent_refs: imported.evidence_refs,
|
|
2242
|
+
semantic_slots: {
|
|
2243
|
+
...importMaterial,
|
|
2244
|
+
received_at_iso: imported.received_at_iso,
|
|
2245
|
+
policy_ref: imported.policy_ref,
|
|
2246
|
+
verification_boundary: "external_issuer_truth_out_of_scope_for_import_adapter"
|
|
2247
|
+
}
|
|
2248
|
+
});
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
function runExternalProofImport(input) {
|
|
2252
|
+
const imported = normalizeExternalProofImport(input);
|
|
2253
|
+
const event = buildExternalProofImportEvent(imported);
|
|
2254
|
+
const signature = `${imported.method}:${imported.external_proof_material_hash_sha256}`;
|
|
2255
|
+
const receipt = emitReceipt(event, {
|
|
2256
|
+
agent_identity: imported.issuer_ref,
|
|
2257
|
+
algorithm: imported.method,
|
|
2258
|
+
signature
|
|
2259
|
+
});
|
|
2260
|
+
const proofBundle = buildProofBundle({
|
|
2261
|
+
ceb: event,
|
|
2262
|
+
receipt,
|
|
2263
|
+
evidence_refs: [
|
|
2264
|
+
imported.import_ref,
|
|
2265
|
+
...imported.evidence_refs
|
|
2266
|
+
],
|
|
2267
|
+
attestations: [
|
|
2268
|
+
{
|
|
2269
|
+
attestation_id: imported.import_ref,
|
|
2270
|
+
attestation_kind: "external_proof_import",
|
|
2271
|
+
method: imported.method,
|
|
2272
|
+
issuer_ref: imported.issuer_ref,
|
|
2273
|
+
subject_ref: imported.subject_ref,
|
|
2274
|
+
material_hash_sha256: imported.external_proof_material_hash_sha256,
|
|
2275
|
+
verification_boundary: "structure_and_binding_verified_external_truth_out_of_scope"
|
|
2276
|
+
}
|
|
2277
|
+
],
|
|
2278
|
+
metadata: {
|
|
2279
|
+
import_adapter_version: "xoonya-external-proof-import-adapter-v1",
|
|
2280
|
+
method_family: imported.method_family,
|
|
2281
|
+
profile_refs: imported.profile_refs
|
|
2282
|
+
}
|
|
2283
|
+
});
|
|
2284
|
+
const verification = verifyProofBundle(proofBundle);
|
|
2285
|
+
return {
|
|
2286
|
+
ok: verification.valid === true,
|
|
2287
|
+
product: "xoonya",
|
|
2288
|
+
category: "xoonya-external-proof-import-run",
|
|
2289
|
+
import_ref: imported.import_ref,
|
|
2290
|
+
import_review: reviewExternalProofImport(input),
|
|
2291
|
+
canonical_event: event,
|
|
2292
|
+
event_commitment: hashEvent(event),
|
|
2293
|
+
receipt,
|
|
2294
|
+
proof_bundle: proofBundle,
|
|
2295
|
+
bundle_verification: verification,
|
|
2296
|
+
boundary: "external_material_is_bound_into_xoonya_proof_bundle_external_cryptographic_truth_remains_with_external_verifier"
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
function summarizeExternalProofImportRun(input) {
|
|
2301
|
+
const run = runExternalProofImport(input);
|
|
2302
|
+
return {
|
|
2303
|
+
ok: run.ok,
|
|
2304
|
+
category: "xoonya-external-proof-import-run-summary",
|
|
2305
|
+
import_ref: run.import_ref,
|
|
2306
|
+
event_commitment: run.event_commitment,
|
|
2307
|
+
receipt_id: run.receipt ? run.receipt.receipt_id : null,
|
|
2308
|
+
proof_bundle_version: run.proof_bundle ? run.proof_bundle.version : null,
|
|
2309
|
+
bundle_valid: run.bundle_verification ? run.bundle_verification.valid === true : false,
|
|
2310
|
+
verification_method: run.bundle_verification ? run.bundle_verification.verification_method : null,
|
|
2311
|
+
verification_state: run.bundle_verification ? run.bundle_verification.verification_state : null,
|
|
2312
|
+
boundary: run.boundary
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
function buildXoonyaNativeAtomSpec() {
|
|
2317
|
+
return {
|
|
2318
|
+
ok: true,
|
|
2319
|
+
product: "xoonya",
|
|
2320
|
+
category: "xoonya-native-atom-spec",
|
|
2321
|
+
spec_version: "xoonya-native-atom-spec/v1",
|
|
2322
|
+
status: "formal_spec_pack_active",
|
|
2323
|
+
canonical_magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
2324
|
+
canonical_magic_hex: XOONYA_NATIVE_ATOM_MAGIC_HEX.toLowerCase(),
|
|
2325
|
+
canonical_magic_rule: "new_xoonya_native_atoms_use_xnya_only",
|
|
2326
|
+
repo_strategy: {
|
|
2327
|
+
current: "ship_inside_xoonya_package",
|
|
2328
|
+
reason: "one_public_package_is_simpler_for_adoption_and_keeps_native_proof_near_verifier_implementation",
|
|
2329
|
+
extraction_rule: "extract_to_separate_standards_repo_only_after_external_adoption_or_governance_pressure"
|
|
2330
|
+
},
|
|
2331
|
+
versions: [
|
|
2332
|
+
{
|
|
2333
|
+
atom_version: XOONYA_NATIVE_ATOM_V1,
|
|
2334
|
+
version_byte: VERSION_V1_HEX,
|
|
2335
|
+
fixed_size_bytes: 58,
|
|
2336
|
+
field_layout: [
|
|
2337
|
+
{ field: "MAGIC", bytes: 4, value: XOONYA_NATIVE_ATOM_MAGIC_ASCII },
|
|
2338
|
+
{ field: "VERSION", bytes: 1, value: "0x01" },
|
|
2339
|
+
{ field: "TYPE", bytes: 1, values: ["0x01", "0x02", "0x03"] },
|
|
2340
|
+
{ field: "AGENT_ID", bytes: 20, derivation: `HASH160(${XNYA_DS_AGENT_V1} || identity_material)` },
|
|
2341
|
+
{ field: "PAYLOAD_HASH", bytes: 32, derivation: `SHA256(${XNYA_DS_PAYLOAD_V1} || payload_bytes) or zero sentinel when absent` }
|
|
2342
|
+
],
|
|
2343
|
+
role: "classical minimal identity and payload commitment"
|
|
2344
|
+
},
|
|
2345
|
+
{
|
|
2346
|
+
atom_version: XOONYA_NATIVE_ATOM_V2,
|
|
2347
|
+
version_byte: VERSION_V2_HEX,
|
|
2348
|
+
fixed_size_bytes: 70,
|
|
2349
|
+
field_layout: [
|
|
2350
|
+
{ field: "MAGIC", bytes: 4, value: XOONYA_NATIVE_ATOM_MAGIC_ASCII },
|
|
2351
|
+
{ field: "VERSION", bytes: 1, value: "0x02" },
|
|
2352
|
+
{ field: "TYPE", bytes: 1, values: ["0x01", "0x02", "0x03"] },
|
|
2353
|
+
{ field: "AGENT_ID", bytes: 32, derivation: `SHA256(${XNYA_DS_AGENT_V2} || identity_material)` },
|
|
2354
|
+
{ field: "PAYLOAD_HASH", bytes: 32, derivation: `SHA256(${XNYA_DS_PAYLOAD_V2} || payload_bytes) or zero sentinel when absent` }
|
|
2355
|
+
],
|
|
2356
|
+
role: "pq_horizon_identity_commitment_with_32_byte_agent_digest"
|
|
2357
|
+
}
|
|
2358
|
+
],
|
|
2359
|
+
validation_rules: [
|
|
2360
|
+
"magic_must_equal_XNYA",
|
|
2361
|
+
"version_must_match_length",
|
|
2362
|
+
"type_must_be_01_02_or_03",
|
|
2363
|
+
"identity_type_prefix_must_be_registered",
|
|
2364
|
+
"wire_format_is_raw_bytes_hex_is_display_only",
|
|
2365
|
+
"payload_absent_is_exactly_32_zero_bytes",
|
|
2366
|
+
"present_payload_must_not_use_absent_zero_sentinel",
|
|
2367
|
+
"signatures_timestamps_prices_settlement_refs_and_runtime_metadata_are_forbidden_in_atom"
|
|
2368
|
+
],
|
|
2369
|
+
deterministic_error_codes: Object.values(XNYA_NATIVE_ATOM_ERROR_CODES),
|
|
2370
|
+
identity_type_registry: listXoonyaNativeIdentityTypes(),
|
|
2371
|
+
linked_surfaces: {
|
|
2372
|
+
native_standard_ref: "/v1/proof-center/native-standard",
|
|
2373
|
+
native_atom_spec_summary_ref: "/v1/proof-center/native-atom-spec/summary",
|
|
2374
|
+
native_atom_conformance_ref: "/v1/proof-center/native-atom-conformance"
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
function summarizeXoonyaNativeAtomSpec() {
|
|
2380
|
+
const spec = buildXoonyaNativeAtomSpec();
|
|
2381
|
+
return {
|
|
2382
|
+
ok: true,
|
|
2383
|
+
product: spec.product,
|
|
2384
|
+
category: "xoonya-native-atom-spec-summary",
|
|
2385
|
+
spec_version: spec.spec_version,
|
|
2386
|
+
status: spec.status,
|
|
2387
|
+
canonical_magic: spec.canonical_magic,
|
|
2388
|
+
version_count: spec.versions.length,
|
|
2389
|
+
fixed_size_bytes: spec.versions.map((entry) => entry.fixed_size_bytes),
|
|
2390
|
+
identity_type_count: spec.identity_type_registry.length,
|
|
2391
|
+
deterministic_error_code_count: spec.deterministic_error_codes.length,
|
|
2392
|
+
repo_strategy: spec.repo_strategy.current,
|
|
2393
|
+
linked_surfaces: spec.linked_surfaces
|
|
2394
|
+
};
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
function buildXoonyaNativeAtomConformancePack() {
|
|
2398
|
+
const spec = buildXoonyaNativeAtomSpec();
|
|
2399
|
+
return {
|
|
2400
|
+
ok: true,
|
|
2401
|
+
product: "xoonya",
|
|
2402
|
+
category: "xoonya-native-atom-conformance-pack",
|
|
2403
|
+
pack_version: "xoonya-native-atom-conformance-pack-v1",
|
|
2404
|
+
status: "active",
|
|
2405
|
+
canonical_magic: spec.canonical_magic,
|
|
2406
|
+
atom_versions: spec.versions.map((entry) => ({
|
|
2407
|
+
atom_version: entry.atom_version,
|
|
2408
|
+
fixed_size_bytes: entry.fixed_size_bytes,
|
|
2409
|
+
version_byte: entry.version_byte
|
|
2410
|
+
})),
|
|
2411
|
+
deterministic_error_codes: spec.deterministic_error_codes,
|
|
2412
|
+
conformance_requirements: [
|
|
2413
|
+
"emit_exact_v1_and_v2_vectors",
|
|
2414
|
+
"parse_exact_field_boundaries",
|
|
2415
|
+
"verify_identity_material_against_agent_id",
|
|
2416
|
+
"verify_payload_bytes_against_payload_hash",
|
|
2417
|
+
"reject_bad_magic",
|
|
2418
|
+
"reject_bad_length",
|
|
2419
|
+
"reject_unsupported_record_type",
|
|
2420
|
+
"reject_version_length_mismatch",
|
|
2421
|
+
"reject_unsupported_identity_type_prefix",
|
|
2422
|
+
"return_stable_error_code_for_each_reject"
|
|
2423
|
+
],
|
|
2424
|
+
adversarial_vector_categories: [
|
|
2425
|
+
"non_hex",
|
|
2426
|
+
"bad_length",
|
|
2427
|
+
"bad_magic",
|
|
2428
|
+
"unsupported_type",
|
|
2429
|
+
"version_length_mismatch",
|
|
2430
|
+
"payload_mismatch",
|
|
2431
|
+
"agent_mismatch",
|
|
2432
|
+
"unsupported_identity_prefix",
|
|
2433
|
+
"identity_missing_raw_bytes"
|
|
2434
|
+
],
|
|
2435
|
+
reference_vector_file: "vectors/native-atom-vectors.json",
|
|
2436
|
+
validator_entrypoint: "verifyXoonyaNativeAtom(atomHex, { identity_material_hex, payload_bytes })",
|
|
2437
|
+
public_claim_boundary: "Xoonya Native atom compatibility requires exact XNYA bytes, exact version lengths, exact hash derivation, and stable reject codes.",
|
|
2438
|
+
linked_surfaces: {
|
|
2439
|
+
native_atom_spec_ref: "/v1/proof-center/native-atom-spec",
|
|
2440
|
+
native_atom_spec_summary_ref: "/v1/proof-center/native-atom-spec/summary",
|
|
2441
|
+
native_atom_conformance_summary_ref: "/v1/proof-center/native-atom-conformance/summary"
|
|
2442
|
+
}
|
|
2443
|
+
};
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
function summarizeXoonyaNativeAtomConformancePack() {
|
|
2447
|
+
const pack = buildXoonyaNativeAtomConformancePack();
|
|
2448
|
+
return {
|
|
2449
|
+
ok: true,
|
|
2450
|
+
product: pack.product,
|
|
2451
|
+
category: "xoonya-native-atom-conformance-summary",
|
|
2452
|
+
summary_version: "xoonya-native-atom-conformance-summary-v1",
|
|
2453
|
+
status: pack.status,
|
|
2454
|
+
canonical_magic: pack.canonical_magic,
|
|
2455
|
+
atom_version_count: pack.atom_versions.length,
|
|
2456
|
+
deterministic_error_code_count: pack.deterministic_error_codes.length,
|
|
2457
|
+
conformance_requirement_count: pack.conformance_requirements.length,
|
|
2458
|
+
adversarial_vector_category_count: pack.adversarial_vector_categories.length,
|
|
2459
|
+
reference_vector_file: pack.reference_vector_file,
|
|
2460
|
+
linked_surfaces: pack.linked_surfaces
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2464
|
+
function buildXoonyaNativeProofStandard() {
|
|
2465
|
+
return {
|
|
2466
|
+
ok: true,
|
|
2467
|
+
product: "xoonya",
|
|
2468
|
+
category: "xoonya-native-proof-standard",
|
|
2469
|
+
standard_version: XOONYA_NATIVE_PROOF_FORMAT_VERSION,
|
|
2470
|
+
status: "design_contract_active",
|
|
2471
|
+
posture: "optional_native_cold_truth_format_not_identity_or_auth_replacement",
|
|
2472
|
+
design_doctrine: [
|
|
2473
|
+
"xoonya_remains_method_agnostic",
|
|
2474
|
+
"native_format_is_first_class_but_optional",
|
|
2475
|
+
"external_formats_remain_interop_lanes",
|
|
2476
|
+
"verification_methods_are_registry_backed",
|
|
2477
|
+
"native_standard_optimizes_for_replayable_machine_proof_not_login_or_sessions"
|
|
2478
|
+
],
|
|
2479
|
+
not_a_replacement_for: [
|
|
2480
|
+
"JWT",
|
|
2481
|
+
"OAuth",
|
|
2482
|
+
"OIDC",
|
|
2483
|
+
"DID/VC",
|
|
2484
|
+
"SD-JWT VC",
|
|
2485
|
+
"generic_credential_wallet_interop"
|
|
2486
|
+
],
|
|
2487
|
+
native_design_carry_in: {
|
|
2488
|
+
lineage: "fixed_atom_plus_proof_envelope",
|
|
2489
|
+
durable_invention: [
|
|
2490
|
+
"fixed_size_hot_path_commitment_atom",
|
|
2491
|
+
"variable_size_cold_path_proof_envelope",
|
|
2492
|
+
"semantic_free_core_bytes",
|
|
2493
|
+
"strict_deterministic_validation",
|
|
2494
|
+
"profile_layers_for_economics_registry_anchors_and_disputes"
|
|
2495
|
+
],
|
|
2496
|
+
strategic_assessment: "substantial_native_machine_evidence_line_not_jwt_did_vc_reimplementation"
|
|
2497
|
+
},
|
|
2498
|
+
layer_model: [
|
|
2499
|
+
{
|
|
2500
|
+
layer: "L0",
|
|
2501
|
+
name: "native_atom",
|
|
2502
|
+
role: "fixed length identity and payload commitment"
|
|
2503
|
+
},
|
|
2504
|
+
{
|
|
2505
|
+
layer: "L1",
|
|
2506
|
+
name: "canonical_payload_or_intent",
|
|
2507
|
+
role: "deterministic machine meaning committed by the atom, with optional strict binary payload profile"
|
|
2508
|
+
},
|
|
2509
|
+
{
|
|
2510
|
+
layer: "L2",
|
|
2511
|
+
name: "proof_envelope",
|
|
2512
|
+
role: "signatures attestations anchors finality refs and external proof material"
|
|
2513
|
+
},
|
|
2514
|
+
{
|
|
2515
|
+
layer: "L3",
|
|
2516
|
+
name: "profiles",
|
|
2517
|
+
role: "registry economic batch dispute and anchor evidence semantics"
|
|
2518
|
+
},
|
|
2519
|
+
{
|
|
2520
|
+
layer: "L4",
|
|
2521
|
+
name: "runtime_and_policy_consumers",
|
|
2522
|
+
role: "systems that consume proof without redefining core bytes"
|
|
2523
|
+
}
|
|
2524
|
+
],
|
|
2525
|
+
hot_path_atom: {
|
|
2526
|
+
candidate_version: XOONYA_NATIVE_ATOM_V1,
|
|
2527
|
+
magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
2528
|
+
magic_hex: XOONYA_NATIVE_ATOM_MAGIC_HEX.toLowerCase(),
|
|
2529
|
+
native_lineage: "xoonya-native-atom/v1",
|
|
2530
|
+
fixed_size_bytes: 58,
|
|
2531
|
+
shape: "MAGIC(4)|VERSION(1)|TYPE(1)|AGENT_ID(20)|PAYLOAD_HASH(32)",
|
|
2532
|
+
core_boundary: "commitment_only_no_signatures_timestamps_prices_settlement_refs_or_runtime_metadata",
|
|
2533
|
+
validation_posture: "strict_fixed_length_deterministic_rejects"
|
|
2534
|
+
},
|
|
2535
|
+
future_atom_candidates: [
|
|
2536
|
+
{
|
|
2537
|
+
candidate_version: XOONYA_NATIVE_ATOM_V1,
|
|
2538
|
+
magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
2539
|
+
fixed_size_bytes: 58,
|
|
2540
|
+
purpose: "classical minimal identity and payload commitment",
|
|
2541
|
+
domain_separation: [
|
|
2542
|
+
XNYA_DS_AGENT_V1,
|
|
2543
|
+
XNYA_DS_PAYLOAD_V1
|
|
2544
|
+
]
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
candidate_version: XOONYA_NATIVE_ATOM_V2,
|
|
2548
|
+
magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
2549
|
+
fixed_size_bytes: 70,
|
|
2550
|
+
purpose: "pq_horizon_identity_commitment_with_32_byte_agent_digest",
|
|
2551
|
+
domain_separation: [
|
|
2552
|
+
XNYA_DS_AGENT_V2,
|
|
2553
|
+
XNYA_DS_PAYLOAD_V2
|
|
2554
|
+
]
|
|
2555
|
+
},
|
|
2556
|
+
{
|
|
2557
|
+
candidate_version: XOONYA_NATIVE_ATOM_V3_CONTINGENCY,
|
|
2558
|
+
maturity: "not_an_implementation_target",
|
|
2559
|
+
purpose: "future_digest_family_shift_only_if_sha256_assumptions_materially_change"
|
|
2560
|
+
}
|
|
2561
|
+
],
|
|
2562
|
+
atom_registry_policy: {
|
|
2563
|
+
canonical_magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
2564
|
+
canonical_magic_status: "XNYA_is_the_only_canonical_magic_for_xoonya_native_atoms",
|
|
2565
|
+
repo_strategy: "ship_inside_xoonya_package_first_extract_to_standards_repo_only_after_external_adoption_pressure",
|
|
2566
|
+
identity_type_registry: listXoonyaNativeIdentityTypes()
|
|
2567
|
+
},
|
|
2568
|
+
object_model: [
|
|
2569
|
+
{
|
|
2570
|
+
object: "canonical_event",
|
|
2571
|
+
version: CANONICAL_EVENT_BUNDLE_VERSION,
|
|
2572
|
+
role: "deterministic machine event input"
|
|
2573
|
+
},
|
|
2574
|
+
{
|
|
2575
|
+
object: "native_receipt",
|
|
2576
|
+
version: CANONICAL_RECEIPT_VERSION,
|
|
2577
|
+
role: "portable event commitment and proof-method boundary"
|
|
2578
|
+
},
|
|
2579
|
+
{
|
|
2580
|
+
object: "proof_bundle",
|
|
2581
|
+
version: PROOF_BUNDLE_VERSION,
|
|
2582
|
+
role: "replayable verification container with optional references"
|
|
2583
|
+
},
|
|
2584
|
+
{
|
|
2585
|
+
object: "native_envelope",
|
|
2586
|
+
version: XOONYA_NATIVE_PROOF_FORMAT_VERSION,
|
|
2587
|
+
role: "future formal wrapper for receipt, method, proof material, anchors, and attestations"
|
|
2588
|
+
}
|
|
2589
|
+
],
|
|
2590
|
+
current_native_methods: [
|
|
2591
|
+
{
|
|
2592
|
+
method: XOONYA_NATIVE_SHA256_METHOD,
|
|
2593
|
+
maturity: "implemented",
|
|
2594
|
+
purpose: "deterministic digest proof for replayable local proof integrity"
|
|
2595
|
+
},
|
|
2596
|
+
{
|
|
2597
|
+
method: XOONYA_NATIVE_SIGNED_METHOD,
|
|
2598
|
+
maturity: "implemented",
|
|
2599
|
+
purpose: "native signature envelope with explicit signature-suite and public-key binding"
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
method: XOONYA_NATIVE_ANCHORED_METHOD,
|
|
2603
|
+
maturity: "implemented",
|
|
2604
|
+
purpose: "native anchor binding for chain, batch, finality, or external attestation references"
|
|
2605
|
+
}
|
|
2606
|
+
],
|
|
2607
|
+
planned_native_methods: [
|
|
2608
|
+
{
|
|
2609
|
+
method: XOONYA_NATIVE_HYBRID_METHOD,
|
|
2610
|
+
maturity: "future_extension",
|
|
2611
|
+
purpose: "stronger-crypto or PQC-sensitive proof lane without changing the native object model"
|
|
2612
|
+
}
|
|
2613
|
+
],
|
|
2614
|
+
supported_external_method_families: listProofVerificationMethods()
|
|
2615
|
+
.filter((method) => method.verification_posture === "structure_verified_external_signature")
|
|
2616
|
+
.map((method) => ({
|
|
2617
|
+
method: method.id,
|
|
2618
|
+
family: method.family,
|
|
2619
|
+
posture: "interop_lane_external_verifier"
|
|
2620
|
+
})),
|
|
2621
|
+
native_signature_suite_policy: {
|
|
2622
|
+
algorithm_policy: "pluggable_explicit_suite",
|
|
2623
|
+
default_constraint: "no_single_algorithm_or_chain_is_mandatory",
|
|
2624
|
+
implemented_suites: listNativeSignatureSuites()
|
|
2625
|
+
.filter((suite) => suite.maturity === "implemented")
|
|
2626
|
+
.map((suite) => suite.id),
|
|
2627
|
+
suite_registry: listNativeSignatureSuites(),
|
|
2628
|
+
required_fields_for_signed_native_method: [
|
|
2629
|
+
"method",
|
|
2630
|
+
"signature_suite",
|
|
2631
|
+
"identity_ref",
|
|
2632
|
+
"public_key_ref",
|
|
2633
|
+
"proof_material"
|
|
2634
|
+
]
|
|
2635
|
+
},
|
|
2636
|
+
crypto_support_boundary: {
|
|
2637
|
+
native_provides: [
|
|
2638
|
+
"identity_commitment",
|
|
2639
|
+
"payload_commitment",
|
|
2640
|
+
"proof_binding",
|
|
2641
|
+
"replayable_verification_material"
|
|
2642
|
+
],
|
|
2643
|
+
native_does_not_provide: [
|
|
2644
|
+
"encryption",
|
|
2645
|
+
"forward_secrecy",
|
|
2646
|
+
"transport_security",
|
|
2647
|
+
"custody",
|
|
2648
|
+
"access_control"
|
|
2649
|
+
],
|
|
2650
|
+
cleanly_layers_with: [
|
|
2651
|
+
"secp256k1",
|
|
2652
|
+
"ed25519",
|
|
2653
|
+
"p256",
|
|
2654
|
+
"webauthn",
|
|
2655
|
+
"did_vc",
|
|
2656
|
+
"jwt_jws",
|
|
2657
|
+
"sd_jwt_vc",
|
|
2658
|
+
"dilithium",
|
|
2659
|
+
"falcon",
|
|
2660
|
+
"sphincs_plus",
|
|
2661
|
+
"hpke",
|
|
2662
|
+
"zk_proof_commitments"
|
|
2663
|
+
]
|
|
2664
|
+
},
|
|
2665
|
+
competitive_positioning: {
|
|
2666
|
+
category: "deterministic_machine_evidence",
|
|
2667
|
+
jwt_boundary: "jwt_wins_for_broad_web_signed_json_xoonya_native_wins_for_byte_stable_replayable_machine_proof",
|
|
2668
|
+
did_vc_boundary: "did_vc_wins_for_rich_identity_credentials_xoonya_native_wins_for_compact_machine_receipts_and_proof_roots",
|
|
2669
|
+
chain_proof_boundary: "chain_specific_proofs_win_on_native_settlement_xoonya_native_wins_cross_runtime_cross_rail_proof_continuity",
|
|
2670
|
+
unique_claim: "minimal_deterministic_replayable_chain_neutral_machine_evidence_standard"
|
|
2671
|
+
},
|
|
2672
|
+
standardization_protection: {
|
|
2673
|
+
technical_controls: [
|
|
2674
|
+
"frozen_version_lines",
|
|
2675
|
+
"canonical_conformance_vectors",
|
|
2676
|
+
"adversarial_vectors",
|
|
2677
|
+
"reference_validators",
|
|
2678
|
+
"deterministic_error_codes",
|
|
2679
|
+
"method_and_suite_registries",
|
|
2680
|
+
"bounded_public_claims"
|
|
2681
|
+
],
|
|
2682
|
+
legal_and_brand_controls: [
|
|
2683
|
+
"tagged_releases_and_checksummed_specs",
|
|
2684
|
+
"apache_2_0_implementation_licensing_where_intended",
|
|
2685
|
+
"xoonya_name_and_conformance_mark_usage_rules",
|
|
2686
|
+
"qualified_ip_counsel_for_patent_trademark_or_defensive_publication_strategy"
|
|
2687
|
+
]
|
|
2688
|
+
},
|
|
2689
|
+
standardization_steps: [
|
|
2690
|
+
"publish_native_format_doc",
|
|
2691
|
+
"freeze_xnya_atom_ladder_as_xoonya_native_lineage",
|
|
2692
|
+
"add_xoonya_native_signed_v1_method",
|
|
2693
|
+
"add_signature_suite_registry",
|
|
2694
|
+
"add_native_signed_conformance_vectors",
|
|
2695
|
+
"add_native_payload_profile_for_strict_binary_machine_evidence",
|
|
2696
|
+
"add_optional_line_rate_frame_profile_for_transport_fast_reject",
|
|
2697
|
+
"add_cross_runtime_canonicalization_vectors",
|
|
2698
|
+
"add_anchor_and_attestation_reference_vectors",
|
|
2699
|
+
"ship_external_proof_import_adapter_for_registered_interop_methods",
|
|
2700
|
+
"keep_external_methods_as_interop_lanes"
|
|
2701
|
+
],
|
|
2702
|
+
linked_surfaces: {
|
|
2703
|
+
proof_center_summary_ref: "/v1/proof-center/summary",
|
|
2704
|
+
native_standard_summary_ref: "/v1/proof-center/native-standard/summary",
|
|
2705
|
+
native_atom_conformance_ref: "/v1/proof-center/native-atom-conformance",
|
|
2706
|
+
native_anchor_profile_ref: "/v1/proof-center/native-anchor-profile",
|
|
2707
|
+
native_payload_profile_ref: "/v1/proof-center/native-payload-profile",
|
|
2708
|
+
native_line_rate_frame_ref: "/v1/proof-center/native-line-rate-frame",
|
|
2709
|
+
external_import_adapter_ref: "/v1/proof-center/import-adapter",
|
|
2710
|
+
verification_methods_ref: "/v1/proof-center",
|
|
2711
|
+
default_loop_ref: "/v1/proof-center/default-loops/run"
|
|
2712
|
+
}
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
2715
|
+
|
|
2716
|
+
function summarizeXoonyaNativeProofStandard() {
|
|
2717
|
+
const standard = buildXoonyaNativeProofStandard();
|
|
2718
|
+
return {
|
|
2719
|
+
ok: true,
|
|
2720
|
+
product: standard.product,
|
|
2721
|
+
category: "xoonya-native-proof-standard-summary",
|
|
2722
|
+
standard_version: standard.standard_version,
|
|
2723
|
+
status: standard.status,
|
|
2724
|
+
posture: standard.posture,
|
|
2725
|
+
current_native_method_count: standard.current_native_methods.length,
|
|
2726
|
+
planned_native_method_count: standard.planned_native_methods.length,
|
|
2727
|
+
external_method_family_count: standard.supported_external_method_families.length,
|
|
2728
|
+
object_count: standard.object_model.length,
|
|
2729
|
+
doctrine_count: standard.design_doctrine.length,
|
|
2730
|
+
native_design_lineage: standard.native_design_carry_in.lineage,
|
|
2731
|
+
native_atom_magic: standard.hot_path_atom.magic,
|
|
2732
|
+
native_hot_atom_fixed_size_bytes: standard.hot_path_atom.fixed_size_bytes,
|
|
2733
|
+
future_atom_candidate_count: standard.future_atom_candidates.length,
|
|
2734
|
+
native_identity_type_count: standard.atom_registry_policy.identity_type_registry.length,
|
|
2735
|
+
layer_count: standard.layer_model.length,
|
|
2736
|
+
competitive_category: standard.competitive_positioning.category,
|
|
2737
|
+
native_methods: standard.current_native_methods.map((entry) => entry.method),
|
|
2738
|
+
next_native_method: XOONYA_NATIVE_HYBRID_METHOD,
|
|
2739
|
+
implemented_signature_suites: standard.native_signature_suite_policy.implemented_suites,
|
|
2740
|
+
linked_surfaces: standard.linked_surfaces
|
|
2741
|
+
};
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2744
|
+
function buildXoonyaNativeHybridReadinessPack() {
|
|
2745
|
+
return {
|
|
2746
|
+
ok: true,
|
|
2747
|
+
product: "xoonya",
|
|
2748
|
+
category: "xoonya-native-hybrid-readiness-pack",
|
|
2749
|
+
pack_version: "xoonya-native-hybrid-readiness-v1",
|
|
2750
|
+
method: XOONYA_NATIVE_HYBRID_METHOD,
|
|
2751
|
+
status: "design_gated",
|
|
2752
|
+
posture: "future_stronger_crypto_or_pqc_sensitive_lane_without_changing_xnya_atom_core",
|
|
2753
|
+
current_decision: "do_not_claim_pqc_or_hybrid_verification_until_runtime_validators_and_vectors_exist",
|
|
2754
|
+
implemented_classical_suites: listNativeSignatureSuites()
|
|
2755
|
+
.filter((suite) => suite.maturity === "implemented")
|
|
2756
|
+
.map((suite) => ({
|
|
2757
|
+
suite: suite.id,
|
|
2758
|
+
public_key_format: suite.public_key_format,
|
|
2759
|
+
verification_posture: suite.verification_posture
|
|
2760
|
+
})),
|
|
2761
|
+
gated_candidate_suites: listNativeSignatureSuites()
|
|
2762
|
+
.filter((suite) => suite.maturity !== "implemented")
|
|
2763
|
+
.map((suite) => ({
|
|
2764
|
+
suite: suite.id,
|
|
2765
|
+
maturity: suite.maturity,
|
|
2766
|
+
public_key_format: suite.public_key_format,
|
|
2767
|
+
verification_posture: suite.verification_posture
|
|
2768
|
+
})),
|
|
2769
|
+
promotion_requirements: [
|
|
2770
|
+
"runtime_validator_available_without_experimental_flags",
|
|
2771
|
+
"positive_conformance_vectors",
|
|
2772
|
+
"wrong_key_adversarial_vectors",
|
|
2773
|
+
"tampered_signature_adversarial_vectors",
|
|
2774
|
+
"downgrade_and_method_confusion_vectors",
|
|
2775
|
+
"public_key_format_documented",
|
|
2776
|
+
"deterministic_error_codes_documented",
|
|
2777
|
+
"independent_reference_verifier_or_cross_runtime_vector"
|
|
2778
|
+
],
|
|
2779
|
+
hybrid_object_model_boundary: {
|
|
2780
|
+
atom_rule: "XNYA_atom_remains_commitment_only",
|
|
2781
|
+
envelope_rule: "hybrid_or_pqc_material_lives_in_proof_envelope_or_profile",
|
|
2782
|
+
downgrade_rule: "hybrid_receipts_must_not_verify_as_classical_native_signed_receipts",
|
|
2783
|
+
claim_rule: "claim_candidate_or_design_gated_until_validators_and_vectors_are_real"
|
|
2784
|
+
},
|
|
2785
|
+
linked_surfaces: {
|
|
2786
|
+
native_standard_ref: "/v1/proof-center/native-standard",
|
|
2787
|
+
hybrid_readiness_summary_ref: "/v1/proof-center/native-hybrid-readiness/summary",
|
|
2788
|
+
native_atom_spec_ref: "/v1/proof-center/native-atom-spec",
|
|
2789
|
+
native_atom_conformance_ref: "/v1/proof-center/native-atom-conformance"
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
function summarizeXoonyaNativeHybridReadinessPack() {
|
|
2795
|
+
const pack = buildXoonyaNativeHybridReadinessPack();
|
|
2796
|
+
return {
|
|
2797
|
+
ok: true,
|
|
2798
|
+
product: pack.product,
|
|
2799
|
+
category: "xoonya-native-hybrid-readiness-summary",
|
|
2800
|
+
summary_version: "xoonya-native-hybrid-readiness-summary-v1",
|
|
2801
|
+
method: pack.method,
|
|
2802
|
+
status: pack.status,
|
|
2803
|
+
posture: pack.posture,
|
|
2804
|
+
implemented_classical_suite_count: pack.implemented_classical_suites.length,
|
|
2805
|
+
implemented_classical_suites: pack.implemented_classical_suites.map((entry) => entry.suite),
|
|
2806
|
+
gated_candidate_suite_count: pack.gated_candidate_suites.length,
|
|
2807
|
+
promotion_requirement_count: pack.promotion_requirements.length,
|
|
2808
|
+
current_decision: pack.current_decision,
|
|
2809
|
+
linked_surfaces: pack.linked_surfaces
|
|
2810
|
+
};
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
function buildXoonyaNativePayloadProfilePack() {
|
|
2814
|
+
return {
|
|
2815
|
+
ok: true,
|
|
2816
|
+
product: "xoonya",
|
|
2817
|
+
category: "xoonya-native-payload-profile-pack",
|
|
2818
|
+
profile_version: XOONYA_NATIVE_PAYLOAD_PROFILE_V1,
|
|
2819
|
+
status: "implemented",
|
|
2820
|
+
posture: "strict_canonical_binary_payload_profile_for_xnya_commitments",
|
|
2821
|
+
binary_magic: "XNYP",
|
|
2822
|
+
domain_separator: XNYA_DS_PAYLOAD_PROFILE_V1,
|
|
2823
|
+
field_types: Object.entries(XNYA_PAYLOAD_FIELD_TYPES).map(([fieldType, spec]) => ({
|
|
2824
|
+
field_type: fieldType,
|
|
2825
|
+
field_type_id: spec.id,
|
|
2826
|
+
fixed_length: spec.fixed_length || null,
|
|
2827
|
+
max_length: spec.max_length || null
|
|
2828
|
+
})),
|
|
2829
|
+
canonical_rules: [
|
|
2830
|
+
"binary_not_json",
|
|
2831
|
+
"schema_ref_hash_is_committed",
|
|
2832
|
+
"fields_sorted_by_uint16_field_id_then_type_id",
|
|
2833
|
+
"duplicate_field_id_type_pairs_rejected",
|
|
2834
|
+
"unknown_field_ids_can_be_rejected_by_verifier_policy",
|
|
2835
|
+
"integers_are_big_endian_fixed_width",
|
|
2836
|
+
"floats_null_undefined_functions_and_symbol_values_are_not_supported",
|
|
2837
|
+
"payload_hash_is_sha256_domain_separator_plus_canonical_bytes"
|
|
2838
|
+
],
|
|
2839
|
+
output_artifacts: [
|
|
2840
|
+
"canonical_bytes_hex",
|
|
2841
|
+
"payload_hash_sha256",
|
|
2842
|
+
"schema_hash_sha256",
|
|
2843
|
+
"field_count"
|
|
2844
|
+
],
|
|
2845
|
+
example_profile: encodeXoonyaNativePayloadProfileV1({
|
|
2846
|
+
schema_ref: "xoonya.payload.example.v1",
|
|
2847
|
+
fields: [
|
|
2848
|
+
{ field_id: 1, field_type: "bytes32", value_hex: "11".repeat(32) },
|
|
2849
|
+
{ field_id: 2, field_type: "uint64", value: "42" },
|
|
2850
|
+
{ field_id: 3, field_type: "utf8", value: "example" },
|
|
2851
|
+
{ field_id: 4, field_type: "bool", value: true }
|
|
2852
|
+
]
|
|
2853
|
+
}),
|
|
2854
|
+
linked_surfaces: {
|
|
2855
|
+
native_standard_ref: "/v1/proof-center/native-standard",
|
|
2856
|
+
payload_profile_summary_ref: "/v1/proof-center/native-payload-profile/summary",
|
|
2857
|
+
native_atom_spec_ref: "/v1/proof-center/native-atom-spec"
|
|
2858
|
+
}
|
|
2859
|
+
};
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
function summarizeXoonyaNativePayloadProfilePack() {
|
|
2863
|
+
const pack = buildXoonyaNativePayloadProfilePack();
|
|
2864
|
+
return {
|
|
2865
|
+
ok: true,
|
|
2866
|
+
product: pack.product,
|
|
2867
|
+
category: "xoonya-native-payload-profile-summary",
|
|
2868
|
+
summary_version: "xoonya-native-payload-profile-summary-v1",
|
|
2869
|
+
profile_version: pack.profile_version,
|
|
2870
|
+
status: pack.status,
|
|
2871
|
+
binary_magic: pack.binary_magic,
|
|
2872
|
+
field_type_count: pack.field_types.length,
|
|
2873
|
+
canonical_rule_count: pack.canonical_rules.length,
|
|
2874
|
+
output_artifact_count: pack.output_artifacts.length,
|
|
2875
|
+
example_payload_hash_sha256: pack.example_profile.payload_hash_sha256,
|
|
2876
|
+
linked_surfaces: pack.linked_surfaces
|
|
2877
|
+
};
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
function buildXoonyaNativeLineRateFramePack() {
|
|
2881
|
+
const exampleAtom = createXoonyaNativeAtomV1("01" + "22".repeat(33), Buffer.from("line-rate-example", "utf8"));
|
|
2882
|
+
const exampleFrame = createXoonyaNativeLineRateFrameV1(exampleAtom.atom_hex);
|
|
2883
|
+
return {
|
|
2884
|
+
ok: true,
|
|
2885
|
+
product: "xoonya",
|
|
2886
|
+
category: "xoonya-native-line-rate-frame-pack",
|
|
2887
|
+
profile_version: XOONYA_NATIVE_LINE_RATE_FRAME_V1,
|
|
2888
|
+
status: "implemented_optional_transport_profile",
|
|
2889
|
+
posture: "fast_reject_transport_wrapper_around_existing_xnya_atoms_without_changing_atom_layout",
|
|
2890
|
+
checksum_rule: "first_2_bytes_sha256(domain_separator || atom_bytes)",
|
|
2891
|
+
domain_separator: XNYA_DS_LINE_RATE_FRAME_V1,
|
|
2892
|
+
supported_frame_sizes_bytes: [60, 72],
|
|
2893
|
+
wrapped_atom_sizes_bytes: [58, 70],
|
|
2894
|
+
validation_steps: [
|
|
2895
|
+
"reject_non_hex",
|
|
2896
|
+
"reject_unsupported_frame_length",
|
|
2897
|
+
"parse_wrapped_xnya_atom",
|
|
2898
|
+
"verify_2_byte_checksum_before_heavier_policy_checks",
|
|
2899
|
+
"optionally_verify_identity_material_and_payload_bytes_against_wrapped_atom"
|
|
2900
|
+
],
|
|
2901
|
+
boundary: "line_rate_frame_is_a_transport_fast_reject_profile_not_a_signature_encryption_or_finality_claim",
|
|
2902
|
+
example_frame: exampleFrame,
|
|
2903
|
+
linked_surfaces: {
|
|
2904
|
+
native_standard_ref: "/v1/proof-center/native-standard",
|
|
2905
|
+
line_rate_frame_summary_ref: "/v1/proof-center/native-line-rate-frame/summary",
|
|
2906
|
+
native_atom_spec_ref: "/v1/proof-center/native-atom-spec"
|
|
2907
|
+
}
|
|
2908
|
+
};
|
|
2909
|
+
}
|
|
2910
|
+
|
|
2911
|
+
function summarizeXoonyaNativeLineRateFramePack() {
|
|
2912
|
+
const pack = buildXoonyaNativeLineRateFramePack();
|
|
2913
|
+
return {
|
|
2914
|
+
ok: true,
|
|
2915
|
+
product: pack.product,
|
|
2916
|
+
category: "xoonya-native-line-rate-frame-summary",
|
|
2917
|
+
summary_version: "xoonya-native-line-rate-frame-summary-v1",
|
|
2918
|
+
profile_version: pack.profile_version,
|
|
2919
|
+
status: pack.status,
|
|
2920
|
+
supported_frame_sizes_bytes: pack.supported_frame_sizes_bytes,
|
|
2921
|
+
wrapped_atom_sizes_bytes: pack.wrapped_atom_sizes_bytes,
|
|
2922
|
+
validation_step_count: pack.validation_steps.length,
|
|
2923
|
+
checksum_rule: pack.checksum_rule,
|
|
2924
|
+
boundary: pack.boundary,
|
|
2925
|
+
linked_surfaces: pack.linked_surfaces
|
|
2926
|
+
};
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
function buildXoonyaNativeStandardizationPack() {
|
|
2930
|
+
return {
|
|
2931
|
+
ok: true,
|
|
2932
|
+
product: "xoonya",
|
|
2933
|
+
category: "xoonya-native-standardization-pack",
|
|
2934
|
+
pack_version: "xoonya-native-standardization-pack-v1",
|
|
2935
|
+
standard: XOONYA_NATIVE_PROOF_FORMAT_VERSION,
|
|
2936
|
+
canonical_magic: XOONYA_NATIVE_ATOM_MAGIC_ASCII,
|
|
2937
|
+
posture: "formalize_xnya_as_optional_deterministic_machine_evidence_standard",
|
|
2938
|
+
standardization_state: "package_embedded_reference_standard_ready_for_external_feedback",
|
|
2939
|
+
public_claim: "minimal_deterministic_replayable_chain_neutral_machine_evidence_standard",
|
|
2940
|
+
repo_strategy: "ship_inside_xoonya_until_external_adoption_or_governance_pressure_justifies_a_standards_repo",
|
|
2941
|
+
conformance_mark_policy: {
|
|
2942
|
+
mark: "XNYA-compatible",
|
|
2943
|
+
allowed_only_when: [
|
|
2944
|
+
"canonical_magic_is_XNYA",
|
|
2945
|
+
"atom_version_and_fixed_size_match",
|
|
2946
|
+
"payload_and_identity_hash_derivation_match_vectors",
|
|
2947
|
+
"required_native_methods_verify_or_are_explicitly_declared_unsupported",
|
|
2948
|
+
"adversarial_vectors_fail_with_stable_error_codes"
|
|
2949
|
+
],
|
|
2950
|
+
not_allowed_when: [
|
|
2951
|
+
"magic_or_atom_layout_is_changed",
|
|
2952
|
+
"algorithm_none_is_accepted_as_production_proof",
|
|
2953
|
+
"external_issuer_truth_is_claimed_without_external_verifier",
|
|
2954
|
+
"pqc_or_hybrid_support_is_claimed_without_validators_and_vectors"
|
|
2955
|
+
]
|
|
2956
|
+
},
|
|
2957
|
+
standard_artifacts: [
|
|
2958
|
+
"XOONYA_NATIVE_PROOF_FORMAT.md",
|
|
2959
|
+
"vectors/native-atom-vectors.json",
|
|
2960
|
+
"vectors/native-payload-profile-vectors.json",
|
|
2961
|
+
"vectors/conformance-vectors.json",
|
|
2962
|
+
"vectors/adversarial-vectors.json",
|
|
2963
|
+
"proof_sdk.js reference validator",
|
|
2964
|
+
"/v1/proof-center/native-standard",
|
|
2965
|
+
"/v1/proof-center/native-atom-conformance",
|
|
2966
|
+
"/v1/proof-center/native-hybrid-readiness",
|
|
2967
|
+
"/v1/proof-center/native-payload-profile",
|
|
2968
|
+
"/v1/proof-center/native-line-rate-frame"
|
|
2969
|
+
],
|
|
2970
|
+
adoption_steps: [
|
|
2971
|
+
"keep_xoonya_package_as_reference_implementation",
|
|
2972
|
+
"publish_exact_vectors_and_error_codes_with_each_release",
|
|
2973
|
+
"invite_external_verifier_implementations_against_vectors",
|
|
2974
|
+
"open_a_standards_repo_only_after_real_external_adoption_pressure",
|
|
2975
|
+
"define_conformance_mark_usage_before_third_party_claims",
|
|
2976
|
+
"pursue_trademark_patent_or_defensive_publication_guidance_with_qualified_counsel"
|
|
2977
|
+
],
|
|
2978
|
+
competitor_boundaries: {
|
|
2979
|
+
jwt: "JWT remains better for broad web signed claims; XNYA optimizes byte-stable replayable machine evidence.",
|
|
2980
|
+
did_vc: "DID/VC remains better for rich credentials; XNYA optimizes compact proof roots and deterministic receipts.",
|
|
2981
|
+
cose_jws: "COSE/JWS remain envelope standards; XNYA can carry or bind them without becoming them.",
|
|
2982
|
+
chain_specific_proofs: "Chain-native proofs remain authoritative for their chains; XNYA links cross-runtime proof continuity."
|
|
2983
|
+
},
|
|
2984
|
+
linked_surfaces: {
|
|
2985
|
+
native_standard_ref: "/v1/proof-center/native-standard",
|
|
2986
|
+
native_standardization_summary_ref: "/v1/proof-center/native-standardization/summary",
|
|
2987
|
+
native_hybrid_readiness_ref: "/v1/proof-center/native-hybrid-readiness",
|
|
2988
|
+
native_payload_profile_ref: "/v1/proof-center/native-payload-profile",
|
|
2989
|
+
native_line_rate_frame_ref: "/v1/proof-center/native-line-rate-frame",
|
|
2990
|
+
import_adapter_ref: "/v1/proof-center/import-adapter"
|
|
2991
|
+
}
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
function summarizeXoonyaNativeStandardizationPack() {
|
|
2996
|
+
const pack = buildXoonyaNativeStandardizationPack();
|
|
2997
|
+
return {
|
|
2998
|
+
ok: true,
|
|
2999
|
+
product: pack.product,
|
|
3000
|
+
category: "xoonya-native-standardization-summary",
|
|
3001
|
+
summary_version: "xoonya-native-standardization-summary-v1",
|
|
3002
|
+
standard: pack.standard,
|
|
3003
|
+
canonical_magic: pack.canonical_magic,
|
|
3004
|
+
standardization_state: pack.standardization_state,
|
|
3005
|
+
public_claim: pack.public_claim,
|
|
3006
|
+
conformance_allowed_condition_count: pack.conformance_mark_policy.allowed_only_when.length,
|
|
3007
|
+
conformance_forbidden_condition_count: pack.conformance_mark_policy.not_allowed_when.length,
|
|
3008
|
+
artifact_count: pack.standard_artifacts.length,
|
|
3009
|
+
adoption_step_count: pack.adoption_steps.length,
|
|
3010
|
+
repo_strategy: pack.repo_strategy,
|
|
3011
|
+
linked_surfaces: pack.linked_surfaces
|
|
3012
|
+
};
|
|
3013
|
+
}
|
|
3014
|
+
|
|
3015
|
+
function buildXoonyaNativeAnchorProfile() {
|
|
3016
|
+
return {
|
|
3017
|
+
ok: true,
|
|
3018
|
+
product: "xoonya",
|
|
3019
|
+
category: "xoonya-native-anchor-profile",
|
|
3020
|
+
profile_version: "xoonya-native-anchor-profile/v1",
|
|
3021
|
+
method: XOONYA_NATIVE_ANCHORED_METHOD,
|
|
3022
|
+
status: "implemented",
|
|
3023
|
+
posture: "optional_anchor_binding_without_external_finality_assertion",
|
|
3024
|
+
verification_posture: "native_anchor_binding_verified",
|
|
3025
|
+
core_boundary: "anchors_are_bound_to_receipt_and_event_commitment_without_changing_the_xnya_atom",
|
|
3026
|
+
base_method: XOONYA_NATIVE_SHA256_METHOD,
|
|
3027
|
+
supported_anchor_kinds: [
|
|
3028
|
+
"chain_tx",
|
|
3029
|
+
"batch_inclusion",
|
|
3030
|
+
"finality_ref",
|
|
3031
|
+
"external_attestation",
|
|
3032
|
+
"content_hash"
|
|
3033
|
+
],
|
|
3034
|
+
required_anchor_fields: [
|
|
3035
|
+
"anchor_id",
|
|
3036
|
+
"anchor_kind",
|
|
3037
|
+
"anchor_ref",
|
|
3038
|
+
"anchor_hash_sha256"
|
|
3039
|
+
],
|
|
3040
|
+
optional_anchor_fields: [
|
|
3041
|
+
"network",
|
|
3042
|
+
"finality_state",
|
|
3043
|
+
"observed_at_iso",
|
|
3044
|
+
"provider_ref",
|
|
3045
|
+
"inclusion_proof_ref"
|
|
3046
|
+
],
|
|
3047
|
+
native_proof_shape: {
|
|
3048
|
+
method: XOONYA_NATIVE_ANCHORED_METHOD,
|
|
3049
|
+
base_method: XOONYA_NATIVE_SHA256_METHOD,
|
|
3050
|
+
anchor_refs: "non_empty_sorted_canonical_anchor_refs",
|
|
3051
|
+
proof_material: [
|
|
3052
|
+
"anchor_root_sha256",
|
|
3053
|
+
"binding_material_sha256"
|
|
3054
|
+
],
|
|
3055
|
+
compact_signature: `${XOONYA_NATIVE_ANCHORED_METHOD}:<binding_material_sha256>`
|
|
3056
|
+
},
|
|
3057
|
+
validation_semantics: [
|
|
3058
|
+
"normalize_anchor_refs_deterministically",
|
|
3059
|
+
"require_bundle_anchors_to_match_native_proof_anchor_refs",
|
|
3060
|
+
"verify_anchor_root_sha256",
|
|
3061
|
+
"verify_binding_material_sha256",
|
|
3062
|
+
"verify_compact_signature_binding",
|
|
3063
|
+
"do_not_claim_external_chain_or_provider_finality"
|
|
3064
|
+
],
|
|
3065
|
+
failure_reasons: [
|
|
3066
|
+
"native_anchor_bundle_missing",
|
|
3067
|
+
"native_anchor_bundle_mismatch",
|
|
3068
|
+
"native_anchor_root_mismatch",
|
|
3069
|
+
"native_anchor_binding_hash_mismatch",
|
|
3070
|
+
"signature_native_anchored_mismatch"
|
|
3071
|
+
],
|
|
3072
|
+
linked_surfaces: {
|
|
3073
|
+
native_standard_ref: "/v1/proof-center/native-standard",
|
|
3074
|
+
native_anchor_profile_summary_ref: "/v1/proof-center/native-anchor-profile/summary",
|
|
3075
|
+
native_atom_spec_ref: "/v1/proof-center/native-atom-spec",
|
|
3076
|
+
proof_center_ref: "/v1/proof-center"
|
|
3077
|
+
}
|
|
3078
|
+
};
|
|
3079
|
+
}
|
|
3080
|
+
|
|
3081
|
+
function summarizeXoonyaNativeAnchorProfile() {
|
|
3082
|
+
const profile = buildXoonyaNativeAnchorProfile();
|
|
3083
|
+
return {
|
|
3084
|
+
ok: true,
|
|
3085
|
+
product: profile.product,
|
|
3086
|
+
category: "xoonya-native-anchor-profile-summary",
|
|
3087
|
+
summary_version: "xoonya-native-anchor-profile-summary-v1",
|
|
3088
|
+
method: profile.method,
|
|
3089
|
+
status: profile.status,
|
|
3090
|
+
posture: profile.posture,
|
|
3091
|
+
verification_posture: profile.verification_posture,
|
|
3092
|
+
base_method: profile.base_method,
|
|
3093
|
+
supported_anchor_kind_count: profile.supported_anchor_kinds.length,
|
|
3094
|
+
required_anchor_field_count: profile.required_anchor_fields.length,
|
|
3095
|
+
optional_anchor_field_count: profile.optional_anchor_fields.length,
|
|
3096
|
+
failure_reason_count: profile.failure_reasons.length,
|
|
3097
|
+
linked_surfaces: profile.linked_surfaces
|
|
3098
|
+
};
|
|
3099
|
+
}
|
|
3100
|
+
|
|
796
3101
|
function buildDefaultProofLoops() {
|
|
797
3102
|
const center = buildDefaultProofCenter();
|
|
798
3103
|
return [
|
|
@@ -2897,6 +5202,15 @@ module.exports = {
|
|
|
2897
5202
|
buildDefaultProofCenter,
|
|
2898
5203
|
buildDefaultProofLoopCatalog,
|
|
2899
5204
|
buildDefaultProofLoops,
|
|
5205
|
+
buildExternalProofImportAdapterPack,
|
|
5206
|
+
buildXoonyaNativeHybridReadinessPack,
|
|
5207
|
+
buildXoonyaNativeLineRateFramePack,
|
|
5208
|
+
buildXoonyaNativePayloadProfilePack,
|
|
5209
|
+
buildXoonyaNativeStandardizationPack,
|
|
5210
|
+
buildXoonyaNativeAtomSpec,
|
|
5211
|
+
buildXoonyaNativeAtomConformancePack,
|
|
5212
|
+
buildXoonyaNativeProofStandard,
|
|
5213
|
+
buildXoonyaNativeAnchorProfile,
|
|
2900
5214
|
buildInteractionResultPackageHandoffCenter,
|
|
2901
5215
|
buildInteractionSpineProofHandoffCenter,
|
|
2902
5216
|
buildTransactionProofHandoffCenter,
|
|
@@ -2905,10 +5219,15 @@ module.exports = {
|
|
|
2905
5219
|
buildTransactionProofHandoffEvent,
|
|
2906
5220
|
canonicalizeInteractionResultPackageHandoff,
|
|
2907
5221
|
canonicalizeInteractionSpineProofHandoff,
|
|
5222
|
+
normalizeExternalProofImport,
|
|
2908
5223
|
getDefaultProofLoop,
|
|
2909
5224
|
canonicalizeTransactionProofHandoff,
|
|
2910
5225
|
runDefaultProofLoop,
|
|
5226
|
+
runExternalProofImport,
|
|
2911
5227
|
reviewInteractionResultPackageHandoff,
|
|
5228
|
+
reviewExternalProofImport,
|
|
5229
|
+
summarizeExternalProofImportReview,
|
|
5230
|
+
summarizeExternalProofImportRun,
|
|
2912
5231
|
summarizeReviewedInteractionResultPackageHandoff,
|
|
2913
5232
|
summarizeReviewExtensionReadiness,
|
|
2914
5233
|
summarizeReviewExtensionBoundary,
|
|
@@ -2955,6 +5274,15 @@ module.exports = {
|
|
|
2955
5274
|
runTransactionProofHandoff,
|
|
2956
5275
|
summarizeDefaultProofCenter,
|
|
2957
5276
|
summarizeDefaultProofLoops,
|
|
5277
|
+
summarizeExternalProofImportAdapterPack,
|
|
5278
|
+
summarizeXoonyaNativeHybridReadinessPack,
|
|
5279
|
+
summarizeXoonyaNativeLineRateFramePack,
|
|
5280
|
+
summarizeXoonyaNativePayloadProfilePack,
|
|
5281
|
+
summarizeXoonyaNativeStandardizationPack,
|
|
5282
|
+
summarizeXoonyaNativeAtomSpec,
|
|
5283
|
+
summarizeXoonyaNativeAtomConformancePack,
|
|
5284
|
+
summarizeXoonyaNativeProofStandard,
|
|
5285
|
+
summarizeXoonyaNativeAnchorProfile,
|
|
2958
5286
|
summarizeGuidedProofLoopBundle,
|
|
2959
5287
|
summarizeInteractionResultPackageHandoff,
|
|
2960
5288
|
summarizeInteractionResultPackageHandoffCenter,
|
|
@@ -2965,11 +5293,30 @@ module.exports = {
|
|
|
2965
5293
|
canonicalizeEvent,
|
|
2966
5294
|
hashEvent,
|
|
2967
5295
|
emitReceipt,
|
|
5296
|
+
listProofVerificationMethods,
|
|
5297
|
+
getProofVerificationMethod,
|
|
5298
|
+
listNativeSignatureSuites,
|
|
5299
|
+
getNativeSignatureSuite,
|
|
5300
|
+
listXoonyaNativeIdentityTypes,
|
|
5301
|
+
getXoonyaNativeIdentityType,
|
|
5302
|
+
buildNativeReceiptSignature,
|
|
5303
|
+
buildNativeSignedReceiptProof,
|
|
5304
|
+
buildNativeAnchoredReceiptProof,
|
|
2968
5305
|
buildProofBundle,
|
|
2969
5306
|
verifyProofBundle,
|
|
2970
5307
|
parseReceipt,
|
|
2971
5308
|
makeIdentityMaterial,
|
|
2972
5309
|
createIdentity,
|
|
5310
|
+
createXoonyaNativeAtomV1,
|
|
5311
|
+
createXoonyaNativeAtomV2,
|
|
5312
|
+
parseXoonyaNativeAtom,
|
|
5313
|
+
verifyXoonyaNativeAtom,
|
|
5314
|
+
encodeXoonyaNativePayloadProfileV1,
|
|
5315
|
+
parseXoonyaNativePayloadProfileV1,
|
|
5316
|
+
verifyXoonyaNativePayloadProfileV1,
|
|
5317
|
+
createXoonyaNativeLineRateFrameV1,
|
|
5318
|
+
parseXoonyaNativeLineRateFrameV1,
|
|
5319
|
+
verifyXoonyaNativeLineRateFrameV1,
|
|
2973
5320
|
createReceipt,
|
|
2974
5321
|
verifyReceipt,
|
|
2975
5322
|
createReceiptV2,
|