xoonya 2.15.0 → 3.0.1

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/proof_sdk.js CHANGED
@@ -124,13 +124,15 @@ const NATIVE_SIGNATURE_SUITES = Object.freeze({
124
124
  id: "ed25519",
125
125
  maturity: "implemented",
126
126
  public_key_format: "spki-pem",
127
- verification_posture: "native_verified"
127
+ verification_posture: "native_verified",
128
+ key_type: "ed25519"
128
129
  }),
129
130
  secp256k1: Object.freeze({
130
131
  id: "secp256k1",
131
132
  maturity: "implemented",
132
133
  public_key_format: "spki-pem",
133
134
  verification_posture: "native_verified",
135
+ key_type: "ec",
134
136
  curve: "secp256k1",
135
137
  signing_hash: "sha256"
136
138
  }),
@@ -139,6 +141,7 @@ const NATIVE_SIGNATURE_SUITES = Object.freeze({
139
141
  maturity: "implemented",
140
142
  public_key_format: "spki-pem",
141
143
  verification_posture: "native_verified",
144
+ key_type: "ec",
142
145
  curve: "prime256v1",
143
146
  signing_hash: "sha256"
144
147
  }),
@@ -165,6 +168,20 @@ const NATIVE_SIGNATURE_SUITES = Object.freeze({
165
168
  maturity: "planned_pqc",
166
169
  public_key_format: "suite_defined",
167
170
  verification_posture: "registry_declared_not_yet_verified"
171
+ }),
172
+ "ml-dsa-65": Object.freeze({
173
+ id: "ml-dsa-65",
174
+ maturity: "implemented",
175
+ public_key_format: "spki-pem",
176
+ verification_posture: "native_verified",
177
+ key_type: "ml-dsa-65"
178
+ }),
179
+ "slh-dsa-sha2-128f": Object.freeze({
180
+ id: "slh-dsa-sha2-128f",
181
+ maturity: "implemented",
182
+ public_key_format: "spki-pem",
183
+ verification_posture: "native_verified",
184
+ key_type: "slh-dsa-sha2-128f"
168
185
  })
169
186
  });
170
187
  const XOONYA_NATIVE_IDENTITY_TYPES = Object.freeze({
@@ -642,6 +659,60 @@ function getNativeSignatureSuite(suiteId) {
642
659
  return suite ? { ...suite } : null;
643
660
  }
644
661
 
662
+ function listImplementedClassicalNativeSignatureSuites() {
663
+ return listNativeSignatureSuites().filter((suite) => suite.maturity === "implemented" && !suite.id.startsWith("ml-dsa-") && !suite.id.startsWith("slh-dsa-"));
664
+ }
665
+
666
+ function listImplementedPqNativeSignatureSuites() {
667
+ return listNativeSignatureSuites().filter((suite) => suite.maturity === "implemented" && (suite.id.startsWith("ml-dsa-") || suite.id.startsWith("slh-dsa-")));
668
+ }
669
+
670
+ function buildNativeHybridSuiteId(classicalSuiteId, pqSuiteId) {
671
+ const classicalSuite = getNativeSignatureSuite(classicalSuiteId);
672
+ if (!classicalSuite || classicalSuite.maturity !== "implemented") {
673
+ throw new Error("native hybrid classical signature suite not implemented");
674
+ }
675
+ if (classicalSuite.id.startsWith("ml-dsa-") || classicalSuite.id.startsWith("slh-dsa-")) {
676
+ throw new Error("native hybrid classical signature suite must be classical");
677
+ }
678
+ const pqSuite = getNativeSignatureSuite(pqSuiteId);
679
+ if (!pqSuite || pqSuite.maturity !== "implemented") {
680
+ throw new Error("native hybrid pq signature suite not implemented");
681
+ }
682
+ if (!pqSuite.id.startsWith("ml-dsa-") && !pqSuite.id.startsWith("slh-dsa-")) {
683
+ throw new Error("native hybrid pq signature suite must be pq");
684
+ }
685
+ return `${classicalSuite.id}+${pqSuite.id}`;
686
+ }
687
+
688
+ function parseNativeHybridSuite(hybridSuiteId) {
689
+ const normalized = normalizeString(hybridSuiteId);
690
+ const [classicalSuiteId, pqSuiteId, extra] = normalized.split("+");
691
+ if (!classicalSuiteId || !pqSuiteId || extra) {
692
+ throw new Error("native hybrid signature suite unsupported");
693
+ }
694
+ return {
695
+ id: buildNativeHybridSuiteId(classicalSuiteId, pqSuiteId),
696
+ classical_suite: getNativeSignatureSuite(classicalSuiteId),
697
+ pq_suite: getNativeSignatureSuite(pqSuiteId)
698
+ };
699
+ }
700
+
701
+ function listImplementedNativeHybridSuites() {
702
+ const suites = [];
703
+ for (const classicalSuite of listImplementedClassicalNativeSignatureSuites()) {
704
+ for (const pqSuite of listImplementedPqNativeSignatureSuites()) {
705
+ suites.push({
706
+ id: buildNativeHybridSuiteId(classicalSuite.id, pqSuite.id),
707
+ classical_suite: classicalSuite.id,
708
+ pq_suite: pqSuite.id,
709
+ posture: "dual_signature_verified"
710
+ });
711
+ }
712
+ }
713
+ return suites;
714
+ }
715
+
645
716
  function listxoonyaNativeIdentityTypes() {
646
717
  return Object.values(XOONYA_NATIVE_IDENTITY_TYPES).map((entry) => ({ ...entry }));
647
718
  }
@@ -708,11 +779,21 @@ function nativePublicKeyRefFromPem(publicKeyPem, signatureSuite = "ed25519") {
708
779
  return `${suite.id}-spki-sha256:${sha256Hex(der)}`;
709
780
  }
710
781
 
782
+ function nativeHybridPublicKeyRefFromPems(classicalPublicKeyPem, pqPublicKeyPem, hybridSuiteId) {
783
+ parseNativeHybridSuite(hybridSuiteId);
784
+ const classicalDer = crypto.createPublicKey(normalizePublicKeyPem(classicalPublicKeyPem)).export({ type: "spki", format: "der" });
785
+ const pqDer = crypto.createPublicKey(normalizePublicKeyPem(pqPublicKeyPem)).export({ type: "spki", format: "der" });
786
+ return `${hybridSuiteId}-hybrid-spki-sha256:${sha256Hex(Buffer.concat([classicalDer, pqDer]))}`;
787
+ }
788
+
711
789
  function nativeSigningHashForSuite(suite) {
712
790
  return suite && suite.signing_hash ? suite.signing_hash : null;
713
791
  }
714
792
 
715
793
  function assertNativeKeyMatchesSuite(keyObject, suite, label) {
794
+ if (suite && suite.key_type && keyObject.asymmetricKeyType !== suite.key_type) {
795
+ throw new Error(`${label} key type must be ${suite.key_type}`);
796
+ }
716
797
  if (suite && suite.curve) {
717
798
  const details = keyObject.asymmetricKeyDetails || {};
718
799
  if (details.namedCurve !== suite.curve) {
@@ -779,6 +860,132 @@ function buildNativeSignedReceiptProof(receipt, canonicalEvent, options = {}) {
779
860
  };
780
861
  }
781
862
 
863
+ function buildNativeHybridProofMaterial(receipt, canonicalEvent, proofDescriptor) {
864
+ return {
865
+ identity_ref: proofDescriptor.identity_ref,
866
+ method: XOONYA_NATIVE_HYBRID_METHOD,
867
+ hybrid_suite: proofDescriptor.hybrid_suite,
868
+ hybrid_public_key_ref: proofDescriptor.hybrid_public_key_ref,
869
+ classical_public_key_ref: proofDescriptor.classical_public_key_ref,
870
+ pq_public_key_ref: proofDescriptor.pq_public_key_ref,
871
+ receipt_signing_material: buildCanonicalReceiptSigningMaterial(receipt),
872
+ event_commitment: hashEvent(canonicalEvent),
873
+ standard_version: XOONYA_NATIVE_PROOF_FORMAT_VERSION
874
+ };
875
+ }
876
+
877
+ function runtimeSupportsNativeHybridSuite(hybridSuiteId) {
878
+ try {
879
+ const hybridSuite = parseNativeHybridSuite(hybridSuiteId);
880
+ const classicalPair = hybridSuite.classical_suite.id === "secp256k1"
881
+ ? crypto.generateKeyPairSync("ec", { namedCurve: "secp256k1" })
882
+ : hybridSuite.classical_suite.id === "p256"
883
+ ? crypto.generateKeyPairSync("ec", { namedCurve: "P-256" })
884
+ : crypto.generateKeyPairSync(hybridSuite.classical_suite.key_type);
885
+ const pqPair = crypto.generateKeyPairSync(hybridSuite.pq_suite.key_type);
886
+ const probe = Buffer.from(`xoonya-hybrid-runtime-probe:${hybridSuiteId}`, "utf8");
887
+ const classicalSignature = crypto.sign(nativeSigningHashForSuite(hybridSuite.classical_suite), probe, classicalPair.privateKey);
888
+ const pqSignature = crypto.sign(nativeSigningHashForSuite(hybridSuite.pq_suite), probe, pqPair.privateKey);
889
+ return (
890
+ crypto.verify(nativeSigningHashForSuite(hybridSuite.classical_suite), probe, classicalPair.publicKey, classicalSignature) &&
891
+ crypto.verify(nativeSigningHashForSuite(hybridSuite.pq_suite), probe, pqPair.publicKey, pqSignature)
892
+ );
893
+ } catch (_error) {
894
+ return false;
895
+ }
896
+ }
897
+
898
+ function buildNativeHybridReceiptProof(receipt, canonicalEvent, options = {}) {
899
+ const classicalSignatureSuite = normalizeString(
900
+ options.classical_signature_suite ||
901
+ options.hybrid_classical_signature_suite ||
902
+ options.native_classical_signature_suite ||
903
+ "ed25519"
904
+ );
905
+ const pqSignatureSuite = normalizeString(
906
+ options.pq_signature_suite ||
907
+ options.hybrid_pq_signature_suite ||
908
+ options.native_pq_signature_suite ||
909
+ "ml-dsa-65"
910
+ );
911
+ const hybridSuite = parseNativeHybridSuite(buildNativeHybridSuiteId(classicalSignatureSuite, pqSignatureSuite));
912
+ if (!runtimeSupportsNativeHybridSuite(hybridSuite.id)) {
913
+ throw new Error("native hybrid runtime validator unavailable");
914
+ }
915
+ const classicalPublicKeyPem = normalizePublicKeyPem(
916
+ options.classical_public_key_pem ||
917
+ options.hybrid_classical_public_key_pem ||
918
+ options.native_classical_public_key_pem
919
+ );
920
+ const classicalPrivateKeyPem = normalizePrivateKeyPem(
921
+ options.classical_private_key_pem ||
922
+ options.hybrid_classical_private_key_pem ||
923
+ options.native_classical_private_key_pem
924
+ );
925
+ const pqPublicKeyPem = normalizePublicKeyPem(
926
+ options.pq_public_key_pem ||
927
+ options.hybrid_pq_public_key_pem ||
928
+ options.native_pq_public_key_pem
929
+ );
930
+ const pqPrivateKeyPem = normalizePrivateKeyPem(
931
+ options.pq_private_key_pem ||
932
+ options.hybrid_pq_private_key_pem ||
933
+ options.native_pq_private_key_pem
934
+ );
935
+ const classicalPublicKey = crypto.createPublicKey(classicalPublicKeyPem);
936
+ const classicalPrivateKey = crypto.createPrivateKey(classicalPrivateKeyPem);
937
+ const pqPublicKey = crypto.createPublicKey(pqPublicKeyPem);
938
+ const pqPrivateKey = crypto.createPrivateKey(pqPrivateKeyPem);
939
+ assertNativeKeyMatchesSuite(classicalPublicKey, hybridSuite.classical_suite, "native hybrid classical public key");
940
+ assertNativeKeyMatchesSuite(classicalPrivateKey, hybridSuite.classical_suite, "native hybrid classical private key");
941
+ assertNativeKeyMatchesSuite(pqPublicKey, hybridSuite.pq_suite, "native hybrid pq public key");
942
+ assertNativeKeyMatchesSuite(pqPrivateKey, hybridSuite.pq_suite, "native hybrid pq private key");
943
+ const identityRef = normalizeString(options.identity_ref || options.native_identity_ref || receipt.agent_identity);
944
+ if (!identityRef) {
945
+ throw new Error("native identity_ref required");
946
+ }
947
+ const classicalPublicKeyRef = nativePublicKeyRefFromPem(classicalPublicKeyPem, hybridSuite.classical_suite.id);
948
+ const pqPublicKeyRef = nativePublicKeyRefFromPem(pqPublicKeyPem, hybridSuite.pq_suite.id);
949
+ const hybridPublicKeyRef = nativeHybridPublicKeyRefFromPems(classicalPublicKeyPem, pqPublicKeyPem, hybridSuite.id);
950
+ const descriptor = {
951
+ identity_ref: identityRef,
952
+ hybrid_suite: hybridSuite.id,
953
+ hybrid_public_key_ref: hybridPublicKeyRef,
954
+ classical_public_key_ref: classicalPublicKeyRef,
955
+ pq_public_key_ref: pqPublicKeyRef
956
+ };
957
+ const signingMaterial = buildNativeHybridProofMaterial(receipt, canonicalEvent, descriptor);
958
+ const signingBytes = Buffer.from(canonicalize(signingMaterial), "utf8");
959
+ const classicalSignature = base64urlEncode(
960
+ crypto.sign(nativeSigningHashForSuite(hybridSuite.classical_suite), signingBytes, classicalPrivateKey)
961
+ );
962
+ const pqSignature = base64urlEncode(
963
+ crypto.sign(nativeSigningHashForSuite(hybridSuite.pq_suite), signingBytes, pqPrivateKey)
964
+ );
965
+ return {
966
+ method: XOONYA_NATIVE_HYBRID_METHOD,
967
+ hybrid_suite: hybridSuite.id,
968
+ identity_ref: identityRef,
969
+ hybrid_public_key_ref: hybridPublicKeyRef,
970
+ classical_public_key_ref: classicalPublicKeyRef,
971
+ pq_public_key_ref: pqPublicKeyRef,
972
+ classical_public_key_material: {
973
+ format: hybridSuite.classical_suite.public_key_format,
974
+ value: classicalPublicKeyPem
975
+ },
976
+ pq_public_key_material: {
977
+ format: hybridSuite.pq_suite.public_key_format,
978
+ value: pqPublicKeyPem
979
+ },
980
+ proof_material: {
981
+ signing_material_sha256: sha256Hex(signingBytes),
982
+ classical_signature: classicalSignature,
983
+ pq_signature: pqSignature
984
+ },
985
+ compact_signature: `${XOONYA_NATIVE_HYBRID_METHOD}:${hybridSuite.id}:${classicalSignature}.${pqSignature}`
986
+ };
987
+ }
988
+
782
989
  function normalizeNativeAnchorRefs(anchorRefs, label = "native anchors") {
783
990
  if (!Array.isArray(anchorRefs) || anchorRefs.length === 0) {
784
991
  throw new Error(`${label} must be a non-empty array`);
@@ -918,6 +1125,101 @@ function verifyNativeSignedReceiptProof(receipt, ceb) {
918
1125
  }
919
1126
  }
920
1127
 
1128
+ function verifyNativeHybridReceiptProof(receipt, ceb) {
1129
+ try {
1130
+ const proof = receipt.native_proof;
1131
+ if (!proof || typeof proof !== "object" || Array.isArray(proof)) {
1132
+ return { valid: false, reason: "native_proof_missing" };
1133
+ }
1134
+ if (normalizeString(proof.method) !== XOONYA_NATIVE_HYBRID_METHOD) {
1135
+ return { valid: false, reason: "native_proof_method_mismatch" };
1136
+ }
1137
+ const hybridSuite = parseNativeHybridSuite(proof.hybrid_suite);
1138
+ if (!runtimeSupportsNativeHybridSuite(hybridSuite.id)) {
1139
+ return { valid: false, reason: "native_hybrid_runtime_validator_unavailable" };
1140
+ }
1141
+ const identityRef = normalizeString(proof.identity_ref);
1142
+ if (!identityRef) {
1143
+ return { valid: false, reason: "native_identity_ref_missing" };
1144
+ }
1145
+ const classicalPublicKeyMaterial = proof.classical_public_key_material;
1146
+ const pqPublicKeyMaterial = proof.pq_public_key_material;
1147
+ if (!classicalPublicKeyMaterial || typeof classicalPublicKeyMaterial !== "object" || Array.isArray(classicalPublicKeyMaterial)) {
1148
+ return { valid: false, reason: "native_hybrid_classical_public_key_material_missing" };
1149
+ }
1150
+ if (!pqPublicKeyMaterial || typeof pqPublicKeyMaterial !== "object" || Array.isArray(pqPublicKeyMaterial)) {
1151
+ return { valid: false, reason: "native_hybrid_pq_public_key_material_missing" };
1152
+ }
1153
+ if (normalizeString(classicalPublicKeyMaterial.format) !== hybridSuite.classical_suite.public_key_format) {
1154
+ return { valid: false, reason: "native_hybrid_classical_public_key_format_mismatch" };
1155
+ }
1156
+ if (normalizeString(pqPublicKeyMaterial.format) !== hybridSuite.pq_suite.public_key_format) {
1157
+ return { valid: false, reason: "native_hybrid_pq_public_key_format_mismatch" };
1158
+ }
1159
+ const classicalPublicKeyPem = normalizePublicKeyPem(classicalPublicKeyMaterial.value);
1160
+ const pqPublicKeyPem = normalizePublicKeyPem(pqPublicKeyMaterial.value);
1161
+ const classicalPublicKey = crypto.createPublicKey(classicalPublicKeyPem);
1162
+ const pqPublicKey = crypto.createPublicKey(pqPublicKeyPem);
1163
+ assertNativeKeyMatchesSuite(classicalPublicKey, hybridSuite.classical_suite, "native hybrid classical public key");
1164
+ assertNativeKeyMatchesSuite(pqPublicKey, hybridSuite.pq_suite, "native hybrid pq public key");
1165
+ const expectedClassicalPublicKeyRef = nativePublicKeyRefFromPem(classicalPublicKeyPem, hybridSuite.classical_suite.id);
1166
+ const expectedPqPublicKeyRef = nativePublicKeyRefFromPem(pqPublicKeyPem, hybridSuite.pq_suite.id);
1167
+ const expectedHybridPublicKeyRef = nativeHybridPublicKeyRefFromPems(classicalPublicKeyPem, pqPublicKeyPem, hybridSuite.id);
1168
+ if (normalizeString(proof.classical_public_key_ref) !== expectedClassicalPublicKeyRef) {
1169
+ return { valid: false, reason: "native_hybrid_classical_public_key_ref_mismatch" };
1170
+ }
1171
+ if (normalizeString(proof.pq_public_key_ref) !== expectedPqPublicKeyRef) {
1172
+ return { valid: false, reason: "native_hybrid_pq_public_key_ref_mismatch" };
1173
+ }
1174
+ if (normalizeString(proof.hybrid_public_key_ref) !== expectedHybridPublicKeyRef) {
1175
+ return { valid: false, reason: "native_hybrid_public_key_ref_mismatch" };
1176
+ }
1177
+ const proofMaterial = proof.proof_material;
1178
+ if (!proofMaterial || typeof proofMaterial !== "object" || Array.isArray(proofMaterial)) {
1179
+ return { valid: false, reason: "native_proof_material_missing" };
1180
+ }
1181
+ const classicalSignature = normalizeString(proofMaterial.classical_signature);
1182
+ const pqSignature = normalizeString(proofMaterial.pq_signature);
1183
+ if (!classicalSignature) {
1184
+ return { valid: false, reason: "native_hybrid_classical_signature_missing" };
1185
+ }
1186
+ if (!pqSignature) {
1187
+ return { valid: false, reason: "native_hybrid_pq_signature_missing" };
1188
+ }
1189
+ const expectedCompactSignature = `${XOONYA_NATIVE_HYBRID_METHOD}:${hybridSuite.id}:${classicalSignature}.${pqSignature}`;
1190
+ if (normalizeString(receipt.signature) !== expectedCompactSignature) {
1191
+ return { valid: false, reason: "signature_native_hybrid_mismatch" };
1192
+ }
1193
+ const signingMaterial = buildNativeHybridProofMaterial(receipt, ceb, {
1194
+ identity_ref: identityRef,
1195
+ hybrid_suite: hybridSuite.id,
1196
+ hybrid_public_key_ref: expectedHybridPublicKeyRef,
1197
+ classical_public_key_ref: expectedClassicalPublicKeyRef,
1198
+ pq_public_key_ref: expectedPqPublicKeyRef
1199
+ });
1200
+ const signingBytes = Buffer.from(canonicalize(signingMaterial), "utf8");
1201
+ const expectedSigningHash = sha256Hex(signingBytes);
1202
+ if (normalizeString(proofMaterial.signing_material_sha256).toLowerCase() !== expectedSigningHash) {
1203
+ return { valid: false, reason: "native_hybrid_signing_material_hash_mismatch" };
1204
+ }
1205
+ const classicalSignatureBytes = base64urlDecode(classicalSignature, "native hybrid classical signature");
1206
+ const pqSignatureBytes = base64urlDecode(pqSignature, "native hybrid pq signature");
1207
+ if (!crypto.verify(nativeSigningHashForSuite(hybridSuite.classical_suite), signingBytes, classicalPublicKey, classicalSignatureBytes)) {
1208
+ return { valid: false, reason: "native_hybrid_classical_signature_invalid" };
1209
+ }
1210
+ if (!crypto.verify(nativeSigningHashForSuite(hybridSuite.pq_suite), signingBytes, pqPublicKey, pqSignatureBytes)) {
1211
+ return { valid: false, reason: "native_hybrid_pq_signature_invalid" };
1212
+ }
1213
+ return {
1214
+ valid: true,
1215
+ verification_state: "verified_native_hybrid_signature",
1216
+ signature_suite: hybridSuite.id
1217
+ };
1218
+ } catch (error) {
1219
+ return { valid: false, reason: error.message };
1220
+ }
1221
+ }
1222
+
921
1223
  function verifyNativeAnchoredReceiptProof(receipt, ceb, bundle) {
922
1224
  try {
923
1225
  const proof = receipt.native_proof;
@@ -1026,6 +1328,11 @@ function emitReceipt(event, options = {}) {
1026
1328
  signature = nativeProof.compact_signature;
1027
1329
  delete nativeProof.compact_signature;
1028
1330
  }
1331
+ if (!signature && unsignedReceipt.algorithm === XOONYA_NATIVE_HYBRID_METHOD) {
1332
+ nativeProof = buildNativeHybridReceiptProof(unsignedReceipt, canonicalEvent, options);
1333
+ signature = nativeProof.compact_signature;
1334
+ delete nativeProof.compact_signature;
1335
+ }
1029
1336
  if (!signature && unsignedReceipt.algorithm === XOONYA_NATIVE_ANCHORED_METHOD) {
1030
1337
  nativeProof = buildNativeAnchoredReceiptProof(unsignedReceipt, canonicalEvent, options);
1031
1338
  signature = nativeProof.compact_signature;
@@ -1057,7 +1364,21 @@ function verifyReceiptProofMethod(receipt, ceb, bundle) {
1057
1364
  return { valid: false, reason: "verification_method_none" };
1058
1365
  }
1059
1366
  if (algorithm === XOONYA_NATIVE_HYBRID_METHOD) {
1060
- return { valid: false, reason: "native_hybrid_design_gated" };
1367
+ const verification = verifyNativeHybridReceiptProof(receipt, ceb);
1368
+ if (!verification.valid) {
1369
+ return { valid: false, reason: verification.reason };
1370
+ }
1371
+ return {
1372
+ valid: true,
1373
+ method: {
1374
+ id: XOONYA_NATIVE_HYBRID_METHOD,
1375
+ family: "xoonya_native",
1376
+ verification_posture: "native_hybrid_signature_verified",
1377
+ description: "Verifies xoonya's native hybrid proof envelope with a classical and PQ signature bound to one deterministic signing material."
1378
+ },
1379
+ verification_state: verification.verification_state,
1380
+ signature_suite: verification.signature_suite
1381
+ };
1061
1382
  }
1062
1383
 
1063
1384
  const method = PROOF_VERIFICATION_METHODS[algorithm];
@@ -2699,15 +3020,14 @@ function buildxoonyaNativeProofStandard() {
2699
3020
  method: XOONYA_NATIVE_ANCHORED_METHOD,
2700
3021
  maturity: "implemented",
2701
3022
  purpose: "native anchor binding for chain, batch, finality, or external attestation references"
2702
- }
2703
- ],
2704
- planned_native_methods: [
3023
+ },
2705
3024
  {
2706
3025
  method: XOONYA_NATIVE_HYBRID_METHOD,
2707
- maturity: "future_extension",
2708
- purpose: "stronger-crypto or PQC-sensitive proof lane without changing the native object model"
3026
+ maturity: "implemented",
3027
+ purpose: "dual-signature classical-plus-pq native proof lane for stronger replay-sensitive verification"
2709
3028
  }
2710
3029
  ],
3030
+ planned_native_methods: [],
2711
3031
  supported_external_method_families: listProofVerificationMethods()
2712
3032
  .filter((method) => method.verification_posture === "structure_verified_external_signature")
2713
3033
  .map((method) => ({
@@ -2839,15 +3159,19 @@ function summarizexoonyaNativeProofStandard() {
2839
3159
  }
2840
3160
 
2841
3161
  function buildxoonyaNativeHybridReadinessPack() {
3162
+ const implementedHybridSuites = listImplementedNativeHybridSuites();
3163
+ const runtimeSupportedHybridSuites = implementedHybridSuites.filter((suite) => runtimeSupportsNativeHybridSuite(suite.id));
2842
3164
  return {
2843
3165
  ok: true,
2844
3166
  product: "xoonya",
2845
3167
  category: "xoonya-native-hybrid-readiness-pack",
2846
3168
  pack_version: "xoonya-native-hybrid-readiness-v1",
2847
3169
  method: XOONYA_NATIVE_HYBRID_METHOD,
2848
- status: "design_gated",
2849
- posture: "future_stronger_crypto_or_pqc_sensitive_lane_without_changing_xnya_atom_core",
2850
- current_decision: "do_not_claim_pqc_or_hybrid_verification_until_runtime_validators_and_vectors_exist",
3170
+ status: runtimeSupportedHybridSuites.length > 0 ? "implemented" : "runtime_gated",
3171
+ posture: "dual_signature_classical_plus_pq_lane_without_changing_xnya_atom_core",
3172
+ current_decision: runtimeSupportedHybridSuites.length > 0
3173
+ ? "claim_registered_native_hybrid_verification_only_for_runtime_supported_vector_covered_suites"
3174
+ : "runtime_support_missing_for_registered_native_hybrid_verification",
2851
3175
  implemented_classical_suites: listNativeSignatureSuites()
2852
3176
  .filter((suite) => suite.maturity === "implemented")
2853
3177
  .map((suite) => ({
@@ -2855,6 +3179,12 @@ function buildxoonyaNativeHybridReadinessPack() {
2855
3179
  public_key_format: suite.public_key_format,
2856
3180
  verification_posture: suite.verification_posture
2857
3181
  })),
3182
+ implemented_hybrid_suites: runtimeSupportedHybridSuites.map((suite) => ({
3183
+ suite: suite.id,
3184
+ classical_suite: suite.classical_suite,
3185
+ pq_suite: suite.pq_suite,
3186
+ verification_posture: suite.posture
3187
+ })),
2858
3188
  gated_candidate_suites: listNativeSignatureSuites()
2859
3189
  .filter((suite) => suite.maturity !== "implemented")
2860
3190
  .map((suite) => ({
@@ -2866,7 +3196,6 @@ function buildxoonyaNativeHybridReadinessPack() {
2866
3196
  promotion_requirements: [
2867
3197
  "runtime_validator_available_without_experimental_flags",
2868
3198
  "positive_conformance_vectors",
2869
- "design_gate_adversarial_vector",
2870
3199
  "wrong_key_adversarial_vectors",
2871
3200
  "tampered_signature_adversarial_vectors",
2872
3201
  "downgrade_and_method_confusion_vectors",
@@ -2877,9 +3206,9 @@ function buildxoonyaNativeHybridReadinessPack() {
2877
3206
  hybrid_object_model_boundary: {
2878
3207
  atom_rule: "XNYA_atom_remains_commitment_only",
2879
3208
  envelope_rule: "hybrid_or_pqc_material_lives_in_proof_envelope_or_profile",
2880
- current_deterministic_reject_reason: "native_hybrid_design_gated",
3209
+ current_deterministic_reject_reason: runtimeSupportedHybridSuites.length > 0 ? null : "native_hybrid_runtime_validator_unavailable",
2881
3210
  downgrade_rule: "hybrid_receipts_must_not_verify_as_classical_native_signed_receipts",
2882
- claim_rule: "claim_candidate_or_design_gated_until_validators_and_vectors_are_real"
3211
+ claim_rule: "claim_only_registered_runtime_supported_vector_covered_hybrid_suites"
2883
3212
  },
2884
3213
  linked_surfaces: {
2885
3214
  native_standard_ref: "/v1/proof-center/native-standard",
@@ -2902,6 +3231,8 @@ function summarizexoonyaNativeHybridReadinessPack() {
2902
3231
  posture: pack.posture,
2903
3232
  implemented_classical_suite_count: pack.implemented_classical_suites.length,
2904
3233
  implemented_classical_suites: pack.implemented_classical_suites.map((entry) => entry.suite),
3234
+ implemented_hybrid_suite_count: pack.implemented_hybrid_suites.length,
3235
+ implemented_hybrid_suites: pack.implemented_hybrid_suites.map((entry) => entry.suite),
2905
3236
  gated_candidate_suite_count: pack.gated_candidate_suites.length,
2906
3237
  promotion_requirement_count: pack.promotion_requirements.length,
2907
3238
  deterministic_reject_reason: pack.hybrid_object_model_boundary.current_deterministic_reject_reason,
@@ -3051,7 +3382,7 @@ function buildxoonyaNativeStandardizationPack() {
3051
3382
  "magic_or_atom_layout_is_changed",
3052
3383
  "algorithm_none_is_accepted_as_production_proof",
3053
3384
  "external_issuer_truth_is_claimed_without_external_verifier",
3054
- "pqc_or_hybrid_support_is_claimed_without_validators_and_vectors"
3385
+ "unregistered_or_runtime_unsupported_pqc_or_hybrid_support_is_claimed"
3055
3386
  ]
3056
3387
  },
3057
3388
  standard_artifacts: [
@@ -3287,7 +3618,7 @@ function buildxoonyaNativeReferenceImplementationPack() {
3287
3618
  "return_stable_error_codes_for_rejects",
3288
3619
  "reject_algorithm_none_for_production_native_proofs",
3289
3620
  "verify_ed25519_secp256k1_and_p256_only_when_suite_specific_validators_exist",
3290
- "treat_pq_hybrid_as_design_gated_until_validators_and_vectors_exist",
3621
+ "verify_registered_native_hybrid_suites_only_when_runtime_support_and_vectors_exist",
3291
3622
  "bind_external_methods_without_claiming_external_issuer_truth",
3292
3623
  "preserve_anchor_binding_boundary_without_claiming_external_finality_truth"
3293
3624
  ],
@@ -3336,7 +3667,6 @@ function buildxoonyaNativeReferenceImplementationPack() {
3336
3667
  wraps_javascript_runtime: false
3337
3668
  },
3338
3669
  explicit_non_claims: [
3339
- "no_pq_or_hybrid_runtime_validation_claim",
3340
3670
  "no_live_external_provider_claim",
3341
3671
  "no_identity_auth_custody_transport_or_settlement_claim",
3342
3672
  "no_python_or_rust_full_reference_claim_until_signature_suite_crypto_full_vector_parity_and_round_trip",
@@ -3513,7 +3843,8 @@ function buildxoonyaNativeConformanceMarkPack() {
3513
3843
  "registered_native_methods_verify",
3514
3844
  "algorithm_none_is_rejected",
3515
3845
  "signature_suite_is_declared_and_registered",
3516
- "anchor_binding_is_verified_without_external_finality_overclaim"
3846
+ "anchor_binding_is_verified_without_external_finality_overclaim",
3847
+ "registered_native_hybrid_suites_verify_when_runtime_support_is_present"
3517
3848
  ]
3518
3849
  },
3519
3850
  {
@@ -3529,7 +3860,7 @@ function buildxoonyaNativeConformanceMarkPack() {
3529
3860
  {
3530
3861
  claim: "pqc_or_hybrid_verified",
3531
3862
  required_extra_evidence: [
3532
- "non_experimental_runtime_validator",
3863
+ "runtime_supported_registered_native_hybrid_suite",
3533
3864
  "suite_specific_public_key_rules",
3534
3865
  "positive_conformance_vectors",
3535
3866
  "adversarial_downgrade_vectors",
@@ -3568,7 +3899,7 @@ function buildxoonyaNativeConformanceMarkPack() {
3568
3899
  },
3569
3900
  mark_usage_rules: [
3570
3901
  "do_not_change_magic_layout_or_fixed_sizes_and_keep_the_mark",
3571
- "do_not_claim_pqc_hybrid_or_live_external_truth_without_extra_evidence",
3902
+ "do_not_claim_unregistered_or_runtime_unsupported_pqc_hybrid_or_live_external_truth_without_extra_evidence",
3572
3903
  "do_not_accept_algorithm_none_as_production_proof",
3573
3904
  "do_not_remove_adversarial_failures_from_compatibility_evidence",
3574
3905
  "do_not_use_the_mark_for_identity_auth_custody_transport_or_settlement_claims"
@@ -5904,6 +6235,7 @@ module.exports = {
5904
6235
  getxoonyaNativeIdentityType,
5905
6236
  buildNativeReceiptSignature,
5906
6237
  buildNativeSignedReceiptProof,
6238
+ buildNativeHybridReceiptProof,
5907
6239
  buildNativeAnchoredReceiptProof,
5908
6240
  buildProofBundle,
5909
6241
  verifyProofBundle,
@@ -111,6 +111,18 @@ def verify_proof_vectors() -> tuple[int, int, int, int]:
111
111
  canonical_event = canonicalize_event(event)
112
112
  assert_equal(hash_event(canonical_event), expected["event_commitment"], f"{vector['id']} event commitment")
113
113
  options = dict(vector.get("receipt_options", {}))
114
+ if expected["receipt"].get("algorithm") == "xoonya-native-hybrid-v1":
115
+ assert_equal(expected["receipt"]["native_proof"]["method"], "xoonya-native-hybrid-v1", f"{vector['id']} native hybrid method")
116
+ bundle = {
117
+ "version": expected["proof_bundle_version"],
118
+ "ceb": canonical_event,
119
+ "receipt": expected["receipt"],
120
+ }
121
+ verification = verify_proof_bundle(bundle)
122
+ assert_equal(verification["valid"], False, f"{vector['id']} python hybrid boundary")
123
+ assert_equal(verification["reason"], "native_hybrid_runtime_unavailable_in_python_candidate", f"{vector['id']} python hybrid reason")
124
+ positive_count += 1
125
+ continue
114
126
  if expected["receipt"].get("algorithm") == "xoonya-native-signed-v1":
115
127
  assert_equal(expected["receipt"]["native_proof"]["method"], "xoonya-native-signed-v1", f"{vector['id']} native signed method")
116
128
  assert_equal(expected["receipt"]["native_proof"]["signature_suite"], options.get("signature_suite"), f"{vector['id']} native signed suite")
@@ -164,6 +176,8 @@ def verify_proof_vectors() -> tuple[int, int, int, int]:
164
176
  continue
165
177
  result = verify_proof_bundle(vector["bundle"])
166
178
  expected_reason = vector["expected_reason"]
179
+ if vector["bundle"].get("receipt", {}).get("algorithm") == "xoonya-native-hybrid-v1":
180
+ expected_reason = "native_hybrid_runtime_unavailable_in_python_candidate"
167
181
  if expected_reason == "native_signature_invalid" and not ed25519_available:
168
182
  expected_reason = "native_signature_crypto_dependency_missing"
169
183
  assert_equal(result["valid"], False, f"{vector['id']} adversarial should fail")
@@ -755,7 +755,7 @@ def verify_proof_bundle(bundle: dict[str, Any]) -> dict[str, Any]:
755
755
  if algorithm == "none":
756
756
  return {"valid": False, "reason": "verification_method_none"}
757
757
  if algorithm == XOONYA_NATIVE_HYBRID_METHOD:
758
- return {"valid": False, "reason": "native_hybrid_design_gated"}
758
+ return {"valid": False, "reason": "native_hybrid_runtime_unavailable_in_python_candidate"}
759
759
  if algorithm == LEGACY_OPRETURN_METHOD:
760
760
  legacy_receipt = (receipt.get("compatibility") or {}).get("legacy_receipt")
761
761
  if not isinstance(legacy_receipt, dict):
@@ -251,14 +251,22 @@ function verifyProofBundleConformance() {
251
251
  ensure(unsupportedVerification.valid === false, "unknown proof method must not verify");
252
252
  ensure(unsupportedVerification.reason === "verification_method_unsupported", "unknown proof method reason mismatch");
253
253
 
254
- const hybridAttemptReceipt = {
255
- ...nativeReceipt,
254
+ const hybridClassical = crypto.generateKeyPairSync("ed25519");
255
+ const hybridPq = crypto.generateKeyPairSync("ml-dsa-65");
256
+ const hybridReceipt = sdk.emitReceipt(event, {
257
+ agent_identity: "native-hybrid-agent",
256
258
  algorithm: "xoonya-native-hybrid-v1",
257
- signature: "xoonya-native-hybrid-v1:design-gated-placeholder"
258
- };
259
- const hybridAttemptVerification = sdk.verifyProofBundle(sdk.buildProofBundle({ ceb: event, receipt: hybridAttemptReceipt }));
260
- ensure(hybridAttemptVerification.valid === false, "native hybrid method must stay design gated");
261
- ensure(hybridAttemptVerification.reason === "native_hybrid_design_gated", "native hybrid design gate reason mismatch");
259
+ identity_ref: "did:xoonya:native-hybrid-agent",
260
+ classical_signature_suite: "ed25519",
261
+ pq_signature_suite: "ml-dsa-65",
262
+ classical_public_key_pem: hybridClassical.publicKey.export({ type: "spki", format: "pem" }),
263
+ classical_private_key_pem: hybridClassical.privateKey.export({ type: "pkcs8", format: "pem" }),
264
+ pq_public_key_pem: hybridPq.publicKey.export({ type: "spki", format: "pem" }),
265
+ pq_private_key_pem: hybridPq.privateKey.export({ type: "pkcs8", format: "pem" })
266
+ });
267
+ const hybridVerification = sdk.verifyProofBundle(sdk.buildProofBundle({ ceb: event, receipt: hybridReceipt }));
268
+ ensure(hybridVerification.valid === true, "native hybrid method must verify");
269
+ ensure(hybridVerification.verification_state === "verified_native_hybrid_signature", "native hybrid verification state mismatch");
262
270
 
263
271
  const tamperedNativeReceipt = {
264
272
  ...nativeReceipt,
@@ -526,6 +534,7 @@ function main() {
526
534
  ensure(typeof sdk.verifyxoonyaNativeAtom === "function", "missing verifyxoonyaNativeAtom");
527
535
  ensure(typeof sdk.buildNativeReceiptSignature === "function", "missing buildNativeReceiptSignature");
528
536
  ensure(typeof sdk.buildNativeSignedReceiptProof === "function", "missing buildNativeSignedReceiptProof");
537
+ ensure(typeof sdk.buildNativeHybridReceiptProof === "function", "missing buildNativeHybridReceiptProof");
529
538
  ensure(typeof sdk.buildNativeAnchoredReceiptProof === "function", "missing buildNativeAnchoredReceiptProof");
530
539
  ensure(typeof sdk.buildxoonyaNativeAnchorProfile === "function", "missing buildxoonyaNativeAnchorProfile");
531
540
  ensure(typeof sdk.summarizexoonyaNativeAnchorProfile === "function", "missing summarizexoonyaNativeAnchorProfile");
@@ -567,9 +576,10 @@ function main() {
567
576
  ensure(fs.existsSync(path.resolve(__dirname, "..", "integrations", "registration-record.schema.json")), "missing integration registration schema");
568
577
  ensure(fs.existsSync(path.resolve(__dirname, "..", "integrations", "registry-snapshot.schema.json")), "missing integration registry snapshot schema");
569
578
  const hybridReadiness = sdk.summarizexoonyaNativeHybridReadinessPack();
570
- ensure(hybridReadiness.status === "design_gated", "native hybrid readiness must stay design gated");
579
+ ensure(hybridReadiness.status === "implemented", "native hybrid readiness must be implemented");
571
580
  ensure(hybridReadiness.implemented_classical_suites.includes("secp256k1"), "native hybrid readiness secp256k1 suite missing");
572
581
  ensure(hybridReadiness.implemented_classical_suites.includes("p256"), "native hybrid readiness p256 suite missing");
582
+ ensure(hybridReadiness.implemented_hybrid_suites.includes("ed25519+ml-dsa-65"), "native hybrid readiness ml-dsa suite missing");
573
583
  const standardization = sdk.summarizexoonyaNativeStandardizationPack();
574
584
  ensure(standardization.canonical_magic === "XNYA", "native standardization magic mismatch");
575
585
  ensure(standardization.conformance_forbidden_condition_count >= 4, "native standardization forbidden conditions missing");