xoonya 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CROSS_RUNTIME_POSTURE.md +32 -2
- package/README.md +14 -1
- package/RELEASE_NOTES.md +14 -0
- package/SERVICE_CONTRACT.md +4 -0
- package/XNYA_CONFORMANCE_MARK.md +78 -0
- package/XNYA_REFERENCE_IMPLEMENTATIONS.md +157 -0
- package/XOONYA_NATIVE_PROOF_FORMAT.md +2 -0
- package/XOONYA_NATIVE_STANDARD_GOVERNANCE.md +4 -1
- package/bin/xoonya-release.js +19 -1
- package/bin/xoonya.js +1 -0
- package/lib/release_history.js +14 -0
- package/package.json +11 -2
- package/proof_sdk.js +605 -2
- package/reference/python/README.md +35 -0
- package/reference/python/requirements-optional.txt +1 -0
- package/reference/python/verify_vectors.py +209 -0
- package/reference/python/xnya_reference.py +810 -0
- package/reference/rust/Cargo.toml +11 -0
- package/reference/rust/README.md +28 -0
- package/reference/rust/src/lib.rs +87 -0
- package/scripts/verify_all.js +35 -0
- package/scripts/verify_external_proof_import_gate.js +84 -0
- package/scripts/verify_native_hybrid_design_gate.js +108 -0
- package/scripts/verify_reference_promotion_gate.js +74 -0
- package/scripts/verify_reference_python.js +49 -0
- package/scripts/verify_reference_python_crypto.js +87 -0
- package/scripts/verify_reference_rust_scaffold.js +50 -0
- package/scripts/verify_release_candidate.js +19 -0
- package/scripts/verify_service.js +24 -0
- package/scripts/verify_tooling.js +23 -0
- package/server.js +20 -0
- package/vectors/adversarial-vectors.json +27 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# XNYA Rust Candidate Scaffold
|
|
2
|
+
|
|
3
|
+
This directory is a source-only candidate scaffold for a future independent
|
|
4
|
+
Rust XNYA reference implementation.
|
|
5
|
+
|
|
6
|
+
It is not a full XNYA-compatible reference implementation yet. The JavaScript
|
|
7
|
+
package remains the canonical implementation, and the Python candidate remains
|
|
8
|
+
the only verified non-JavaScript scaffold today.
|
|
9
|
+
|
|
10
|
+
Current scope:
|
|
11
|
+
|
|
12
|
+
- fixed-size `XNYA` atom constants
|
|
13
|
+
- v1/v2 atom byte-length checks
|
|
14
|
+
- record-type checks
|
|
15
|
+
- deterministic atom parser error codes
|
|
16
|
+
|
|
17
|
+
Not claimed yet:
|
|
18
|
+
|
|
19
|
+
- SHA-256 or RIPEMD-160 verification parity
|
|
20
|
+
- XNYP payload-profile parity
|
|
21
|
+
- canonical-event or proof-bundle parity
|
|
22
|
+
- signature-suite validation
|
|
23
|
+
- adversarial vector parity
|
|
24
|
+
- `XNYA-compatible` conformance mark eligibility
|
|
25
|
+
|
|
26
|
+
Future promotion requires a real Rust toolchain check that compiles the crate
|
|
27
|
+
and passes every required positive and adversarial vector set independently.
|
|
28
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//! Source-only Rust candidate scaffold for XNYA atom parsing.
|
|
2
|
+
//!
|
|
3
|
+
//! This crate is intentionally not promoted as an independent XNYA-compatible
|
|
4
|
+
//! reference. It gives future Rust work a stable parser/error-code starting
|
|
5
|
+
//! point while vector parity, hashing, payload, proof-bundle, and signature
|
|
6
|
+
//! validation remain gated.
|
|
7
|
+
|
|
8
|
+
pub const XNYA_MAGIC: [u8; 4] = *b"XNYA";
|
|
9
|
+
pub const VERSION_V1: u8 = 0x01;
|
|
10
|
+
pub const VERSION_V2: u8 = 0x02;
|
|
11
|
+
pub const ATOM_V1_LEN: usize = 58;
|
|
12
|
+
pub const ATOM_V2_LEN: usize = 70;
|
|
13
|
+
|
|
14
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
15
|
+
pub enum XnyaError {
|
|
16
|
+
AtomBadMagic,
|
|
17
|
+
AtomUnsupportedLength,
|
|
18
|
+
AtomUnsupportedRecordType,
|
|
19
|
+
AtomVersionLengthMismatch,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
impl XnyaError {
|
|
23
|
+
pub fn code(&self) -> &'static str {
|
|
24
|
+
match self {
|
|
25
|
+
XnyaError::AtomBadMagic => "atom_bad_magic",
|
|
26
|
+
XnyaError::AtomUnsupportedLength => "atom_unsupported_length",
|
|
27
|
+
XnyaError::AtomUnsupportedRecordType => "atom_unsupported_record_type",
|
|
28
|
+
XnyaError::AtomVersionLengthMismatch => "atom_version_length_mismatch",
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
34
|
+
pub struct ParsedAtom<'a> {
|
|
35
|
+
pub version: u8,
|
|
36
|
+
pub record_type: u8,
|
|
37
|
+
pub identity_commitment: &'a [u8],
|
|
38
|
+
pub payload_hash_sha256: &'a [u8],
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
pub fn parse_atom(bytes: &[u8]) -> Result<ParsedAtom<'_>, XnyaError> {
|
|
42
|
+
if bytes.len() != ATOM_V1_LEN && bytes.len() != ATOM_V2_LEN {
|
|
43
|
+
return Err(XnyaError::AtomUnsupportedLength);
|
|
44
|
+
}
|
|
45
|
+
if bytes[0..4] != XNYA_MAGIC {
|
|
46
|
+
return Err(XnyaError::AtomBadMagic);
|
|
47
|
+
}
|
|
48
|
+
let version = bytes[4];
|
|
49
|
+
let record_type = bytes[5];
|
|
50
|
+
if !matches!(record_type, 0x01 | 0x02 | 0x03) {
|
|
51
|
+
return Err(XnyaError::AtomUnsupportedRecordType);
|
|
52
|
+
}
|
|
53
|
+
let identity_len = match version {
|
|
54
|
+
VERSION_V1 if bytes.len() == ATOM_V1_LEN => 20,
|
|
55
|
+
VERSION_V2 if bytes.len() == ATOM_V2_LEN => 32,
|
|
56
|
+
VERSION_V1 | VERSION_V2 => return Err(XnyaError::AtomVersionLengthMismatch),
|
|
57
|
+
_ => return Err(XnyaError::AtomVersionLengthMismatch),
|
|
58
|
+
};
|
|
59
|
+
let identity_start = 6;
|
|
60
|
+
let identity_end = identity_start + identity_len;
|
|
61
|
+
let payload_end = identity_end + 32;
|
|
62
|
+
Ok(ParsedAtom {
|
|
63
|
+
version,
|
|
64
|
+
record_type,
|
|
65
|
+
identity_commitment: &bytes[identity_start..identity_end],
|
|
66
|
+
payload_hash_sha256: &bytes[identity_end..payload_end],
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#[cfg(test)]
|
|
71
|
+
mod tests {
|
|
72
|
+
use super::*;
|
|
73
|
+
|
|
74
|
+
#[test]
|
|
75
|
+
fn rejects_bad_length() {
|
|
76
|
+
assert_eq!(parse_atom(&[]).unwrap_err().code(), "atom_unsupported_length");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[test]
|
|
80
|
+
fn rejects_bad_magic() {
|
|
81
|
+
let mut atom = [0u8; ATOM_V1_LEN];
|
|
82
|
+
atom[4] = VERSION_V1;
|
|
83
|
+
atom[5] = 0x01;
|
|
84
|
+
assert_eq!(parse_atom(&atom).unwrap_err().code(), "atom_bad_magic");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
package/scripts/verify_all.js
CHANGED
|
@@ -251,6 +251,15 @@ 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,
|
|
256
|
+
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");
|
|
262
|
+
|
|
254
263
|
const tamperedNativeReceipt = {
|
|
255
264
|
...nativeReceipt,
|
|
256
265
|
signature: nativeReceipt.signature.replace(/.$/, "0")
|
|
@@ -345,6 +354,18 @@ function verifyProofBundleConformance() {
|
|
|
345
354
|
});
|
|
346
355
|
ensure(externalImportReviewSummary.ok === true, "external import review summary should pass");
|
|
347
356
|
ensure(externalImportReviewSummary.method === "did-vc-v1", "external import review method mismatch");
|
|
357
|
+
const externalImportGate = sdk.validateExternalProofImportEvidence({
|
|
358
|
+
method: "did-vc-v1",
|
|
359
|
+
external_proof: {
|
|
360
|
+
proof: "demo"
|
|
361
|
+
},
|
|
362
|
+
claim_external_issuer_truth: true
|
|
363
|
+
});
|
|
364
|
+
ensure(externalImportGate.import_allowed === false, "external import truth claim should require external verifier");
|
|
365
|
+
ensure(
|
|
366
|
+
externalImportGate.rejection_codes.includes("external_issuer_truth_claim_requires_external_verifier"),
|
|
367
|
+
"external import truth rejection code mismatch"
|
|
368
|
+
);
|
|
348
369
|
|
|
349
370
|
let hashMismatchRejected = false;
|
|
350
371
|
try {
|
|
@@ -514,6 +535,10 @@ function main() {
|
|
|
514
535
|
ensure(typeof sdk.summarizeXoonyaNativeHybridReadinessPack === "function", "missing summarizeXoonyaNativeHybridReadinessPack");
|
|
515
536
|
ensure(typeof sdk.buildXoonyaNativeStandardizationPack === "function", "missing buildXoonyaNativeStandardizationPack");
|
|
516
537
|
ensure(typeof sdk.summarizeXoonyaNativeStandardizationPack === "function", "missing summarizeXoonyaNativeStandardizationPack");
|
|
538
|
+
ensure(typeof sdk.buildXoonyaNativeConformanceMarkPack === "function", "missing buildXoonyaNativeConformanceMarkPack");
|
|
539
|
+
ensure(typeof sdk.summarizeXoonyaNativeConformanceMarkPack === "function", "missing summarizeXoonyaNativeConformanceMarkPack");
|
|
540
|
+
ensure(typeof sdk.buildXoonyaNativeReferenceImplementationPack === "function", "missing buildXoonyaNativeReferenceImplementationPack");
|
|
541
|
+
ensure(typeof sdk.summarizeXoonyaNativeReferenceImplementationPack === "function", "missing summarizeXoonyaNativeReferenceImplementationPack");
|
|
517
542
|
ensure(typeof sdk.buildXoonyaNativePayloadProfilePack === "function", "missing buildXoonyaNativePayloadProfilePack");
|
|
518
543
|
ensure(typeof sdk.summarizeXoonyaNativePayloadProfilePack === "function", "missing summarizeXoonyaNativePayloadProfilePack");
|
|
519
544
|
ensure(typeof sdk.buildXoonyaNativeLineRateFramePack === "function", "missing buildXoonyaNativeLineRateFramePack");
|
|
@@ -548,6 +573,16 @@ function main() {
|
|
|
548
573
|
const standardization = sdk.summarizeXoonyaNativeStandardizationPack();
|
|
549
574
|
ensure(standardization.canonical_magic === "XNYA", "native standardization magic mismatch");
|
|
550
575
|
ensure(standardization.conformance_forbidden_condition_count >= 4, "native standardization forbidden conditions missing");
|
|
576
|
+
const conformanceMark = sdk.summarizeXoonyaNativeConformanceMarkPack();
|
|
577
|
+
ensure(conformanceMark.mark === "XNYA-compatible", "native conformance mark mismatch");
|
|
578
|
+
ensure(conformanceMark.forbidden_claim_count >= 3, "native conformance mark forbidden claims missing");
|
|
579
|
+
ensure(conformanceMark.implemented_signature_suites.includes("secp256k1"), "native conformance mark secp256k1 suite missing");
|
|
580
|
+
const referenceImplementations = sdk.summarizeXoonyaNativeReferenceImplementationPack();
|
|
581
|
+
ensure(referenceImplementations.status === "js_reference_implemented_independent_references_planned", "native reference implementation status mismatch");
|
|
582
|
+
ensure(referenceImplementations.implemented_reference_count === 1, "native reference implementation count mismatch");
|
|
583
|
+
ensure(referenceImplementations.planned_reference_count >= 2, "native planned reference implementation count mismatch");
|
|
584
|
+
ensure(referenceImplementations.verified_candidate_scaffold_count >= 1, "native verified candidate scaffold missing");
|
|
585
|
+
ensure(referenceImplementations.deterministic_rejection_code_count >= 11, "native reference promotion rejection codes missing");
|
|
551
586
|
verifyCanonicalEventConformance();
|
|
552
587
|
verifyProofBundleConformance();
|
|
553
588
|
verifyNativeAtomConformance();
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const {
|
|
5
|
+
buildExternalProofImportAdapterPack,
|
|
6
|
+
validateExternalProofImportEvidence
|
|
7
|
+
} = require("../proof_sdk");
|
|
8
|
+
|
|
9
|
+
function validImport() {
|
|
10
|
+
return {
|
|
11
|
+
method: "jwt-assertion-v1",
|
|
12
|
+
import_ref: "external-import-gate-demo",
|
|
13
|
+
issuer_ref: "did:example:issuer",
|
|
14
|
+
subject_ref: "txn:xytara:demo",
|
|
15
|
+
external_proof: "eyJhbGciOiJFZERTQSJ9.eyJzdWIiOiJ0eG4teHl0YXJhLWRlbW8ifQ.signature",
|
|
16
|
+
evidence_refs: ["memory://external/import-gate-demo"]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function assertRejected(input, expectedCode) {
|
|
21
|
+
const validation = validateExternalProofImportEvidence(input);
|
|
22
|
+
assert.strictEqual(validation.import_allowed, false, `expected ${expectedCode} to block external proof import`);
|
|
23
|
+
assert.strictEqual(
|
|
24
|
+
validation.rejection_codes.includes(expectedCode),
|
|
25
|
+
true,
|
|
26
|
+
`missing deterministic rejection code ${expectedCode}`
|
|
27
|
+
);
|
|
28
|
+
return validation;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function main() {
|
|
32
|
+
const pack = buildExternalProofImportAdapterPack();
|
|
33
|
+
const validValidation = validateExternalProofImportEvidence(validImport());
|
|
34
|
+
|
|
35
|
+
assert.strictEqual(pack.category, "xoonya-external-proof-import-adapter", "external import adapter category mismatch");
|
|
36
|
+
assert.strictEqual(pack.deterministic_rejection_codes.length >= 11, true, "external import rejection code count missing");
|
|
37
|
+
assert.strictEqual(validValidation.import_allowed, true, "valid structural external import should pass");
|
|
38
|
+
assert.deepStrictEqual(validValidation.rejection_codes, [], "valid structural external import should not carry rejection codes");
|
|
39
|
+
|
|
40
|
+
assertRejected({ ...validImport(), method: "" }, "verification_method_required");
|
|
41
|
+
assertRejected({ ...validImport(), method: "unknown-method-v1" }, "verification_method_unsupported");
|
|
42
|
+
assertRejected({ ...validImport(), method: "xoonya-native-sha256-v1" }, "verification_method_not_external_importable");
|
|
43
|
+
assertRejected({ method: "jwt-assertion-v1" }, "external_proof_material_required");
|
|
44
|
+
assertRejected({ ...validImport(), external_proof: " " }, "external_proof_material_empty");
|
|
45
|
+
assertRejected({ ...validImport(), declared_hash_sha256: "00".repeat(32) }, "external_proof_hash_mismatch");
|
|
46
|
+
assertRejected({ ...validImport(), claim_external_issuer_truth: true }, "external_issuer_truth_claim_requires_external_verifier");
|
|
47
|
+
assertRejected({ ...validImport(), claim_external_signature_truth: true }, "external_signature_truth_claim_requires_external_verifier");
|
|
48
|
+
assertRejected({ ...validImport(), claim_external_revocation_status: true }, "external_revocation_status_claim_requires_external_verifier");
|
|
49
|
+
assertRejected({ ...validImport(), method: "did-vc-v1", claim_did_resolution_truth: true }, "did_resolution_truth_claim_requires_external_verifier");
|
|
50
|
+
assertRejected({ ...validImport(), external_verifier_api_key: "sk_live_accidental_secret" }, "secret_material_forbidden");
|
|
51
|
+
|
|
52
|
+
const externallyVerified = validateExternalProofImportEvidence({
|
|
53
|
+
...validImport(),
|
|
54
|
+
method: "did-vc-v1",
|
|
55
|
+
external_proof: {
|
|
56
|
+
"@context": ["https://www.w3.org/ns/credentials/v2"],
|
|
57
|
+
type: ["VerifiableCredential"],
|
|
58
|
+
issuer: "did:example:issuer",
|
|
59
|
+
credentialSubject: { id: "did:example:agent" }
|
|
60
|
+
},
|
|
61
|
+
claim_external_issuer_truth: true,
|
|
62
|
+
claim_external_signature_truth: true,
|
|
63
|
+
claim_external_revocation_status: true,
|
|
64
|
+
claim_did_resolution_truth: true,
|
|
65
|
+
external_issuer_verifier_ref: "external.verifier.issuer.did-vc.2026-04-22",
|
|
66
|
+
external_signature_verifier_ref: "external.verifier.signature.did-vc.2026-04-22",
|
|
67
|
+
external_revocation_verifier_ref: "external.verifier.revocation.did-vc.2026-04-22",
|
|
68
|
+
did_resolution_verifier_ref: "external.verifier.did_resolution.did-vc.2026-04-22"
|
|
69
|
+
});
|
|
70
|
+
assert.strictEqual(externallyVerified.import_allowed, true, "external verifier-backed truth claims should pass structural validation");
|
|
71
|
+
|
|
72
|
+
const output = {
|
|
73
|
+
ok: true,
|
|
74
|
+
product: "xoonya",
|
|
75
|
+
category: "xoonya-external-proof-import-gate-verification",
|
|
76
|
+
status: "external_import_binds_evidence_without_claiming_external_truth_unless_external_verifier_refs_exist",
|
|
77
|
+
deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
|
|
78
|
+
adversarial_case_count: 11,
|
|
79
|
+
boundary: "xoonya_imports_external_evidence_but_external_issuer_signature_revocation_and_did_truth_stay_with_external_verifiers"
|
|
80
|
+
};
|
|
81
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
main();
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const sdk = require("..");
|
|
5
|
+
|
|
6
|
+
function buildHybridAttemptBundle() {
|
|
7
|
+
const event = sdk.canonicalizeEvent({
|
|
8
|
+
version: "canonical-event-bundle/v1",
|
|
9
|
+
domain_id: "hybrid.gate",
|
|
10
|
+
sequence: "1",
|
|
11
|
+
actor_id: "agent-hybrid",
|
|
12
|
+
adapter_source: "verify_native_hybrid_design_gate",
|
|
13
|
+
event_type: "native.hybrid.attempt",
|
|
14
|
+
event_hash: "89".repeat(32)
|
|
15
|
+
});
|
|
16
|
+
const receipt = sdk.emitReceipt(event, {
|
|
17
|
+
agent_identity: "agent-hybrid-signing",
|
|
18
|
+
algorithm: "xoonya-native-sha256-v1"
|
|
19
|
+
});
|
|
20
|
+
return sdk.buildProofBundle({
|
|
21
|
+
ceb: event,
|
|
22
|
+
receipt: {
|
|
23
|
+
...receipt,
|
|
24
|
+
algorithm: "xoonya-native-hybrid-v1",
|
|
25
|
+
signature: "xoonya-native-hybrid-v1:design-gated-placeholder"
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function runNativeHybridDesignGateVerification() {
|
|
31
|
+
const readiness = sdk.summarizeXoonyaNativeHybridReadinessPack();
|
|
32
|
+
assert.strictEqual(readiness.status, "design_gated", "hybrid readiness must stay design gated");
|
|
33
|
+
assert.strictEqual(
|
|
34
|
+
readiness.current_decision.includes("do_not_claim_pqc"),
|
|
35
|
+
true,
|
|
36
|
+
"hybrid readiness must forbid premature PQ claims"
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const verification = sdk.verifyProofBundle(buildHybridAttemptBundle());
|
|
40
|
+
assert.strictEqual(verification.valid, false, "hybrid method must not verify before validators exist");
|
|
41
|
+
assert.strictEqual(
|
|
42
|
+
verification.reason,
|
|
43
|
+
"native_hybrid_design_gated",
|
|
44
|
+
"hybrid method must fail with deterministic design-gate reason"
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const downgradeEvent = sdk.canonicalizeEvent({
|
|
48
|
+
version: "canonical-event-bundle/v1",
|
|
49
|
+
domain_id: "hybrid.downgrade",
|
|
50
|
+
sequence: "1",
|
|
51
|
+
actor_id: "agent-hybrid",
|
|
52
|
+
adapter_source: "verify_native_hybrid_design_gate",
|
|
53
|
+
event_type: "native.hybrid.downgrade",
|
|
54
|
+
event_hash: "90".repeat(32)
|
|
55
|
+
});
|
|
56
|
+
const detachedReceipt = sdk.emitReceipt(downgradeEvent, {
|
|
57
|
+
agent_identity: "agent-hybrid-signing",
|
|
58
|
+
algorithm: "detached-assertion-v1",
|
|
59
|
+
signature: "xoonya-native-hybrid-v1:attempted-downgrade"
|
|
60
|
+
});
|
|
61
|
+
const downgradeVerification = sdk.verifyProofBundle(sdk.buildProofBundle({
|
|
62
|
+
ceb: downgradeEvent,
|
|
63
|
+
receipt: detachedReceipt
|
|
64
|
+
}));
|
|
65
|
+
assert.strictEqual(downgradeVerification.valid, false, "hybrid-looking signature must not verify as detached");
|
|
66
|
+
assert.strictEqual(
|
|
67
|
+
downgradeVerification.reason,
|
|
68
|
+
"signature_method_mismatch",
|
|
69
|
+
"hybrid-looking external signature must fail as method mismatch"
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
product: "xoonya",
|
|
75
|
+
category: "xoonya-native-hybrid-design-gate-verification",
|
|
76
|
+
method: "xoonya-native-hybrid-v1",
|
|
77
|
+
readiness_status: readiness.status,
|
|
78
|
+
deterministic_reject_reason: verification.reason,
|
|
79
|
+
downgrade_reject_reason: downgradeVerification.reason,
|
|
80
|
+
boundary: "pq_or_hybrid_verification_is_not_claimed_until_real_validators_vectors_and_error_codes_exist"
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function main() {
|
|
85
|
+
const json = process.argv.includes("--json");
|
|
86
|
+
const summary = runNativeHybridDesignGateVerification();
|
|
87
|
+
if (json) {
|
|
88
|
+
process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
process.stdout.write(
|
|
92
|
+
[
|
|
93
|
+
"xoonya verify:native-hybrid-gate passed",
|
|
94
|
+
`method: ${summary.method}`,
|
|
95
|
+
`readiness: ${summary.readiness_status}`,
|
|
96
|
+
`deterministic reject: ${summary.deterministic_reject_reason}`,
|
|
97
|
+
`downgrade reject: ${summary.downgrade_reject_reason}`
|
|
98
|
+
].join("\n") + "\n"
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (require.main === module) {
|
|
103
|
+
main();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = {
|
|
107
|
+
runNativeHybridDesignGateVerification
|
|
108
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const {
|
|
5
|
+
buildXoonyaNativeReferenceImplementationPack,
|
|
6
|
+
summarizeXoonyaNativeReferenceImplementationPack,
|
|
7
|
+
validateXoonyaNativeReferencePromotionEvidence
|
|
8
|
+
} = require("../proof_sdk");
|
|
9
|
+
|
|
10
|
+
function buildValidPromotionEvidence(pack, language = "python") {
|
|
11
|
+
return {
|
|
12
|
+
language,
|
|
13
|
+
candidate_repository_ref: `xoonya-native-${language}@candidate`,
|
|
14
|
+
vector_sets_passed: pack.required_vector_sets.slice(),
|
|
15
|
+
deterministic_error_code_parity_ref: `xnya.reference.error_codes.${language}.2026-04-22`,
|
|
16
|
+
independent_parser_ref: `xnya.reference.parser.${language}.2026-04-22`,
|
|
17
|
+
signature_crypto_parity_ref: `xnya.reference.crypto.${language}.2026-04-22`,
|
|
18
|
+
round_trip_ref: `xnya.reference.round_trip.${language}.2026-04-22`,
|
|
19
|
+
conformance_mark_review_ref: `xnya.reference.conformance_mark.${language}.2026-04-22`,
|
|
20
|
+
forbidden_claim_review_ref: `xnya.reference.claim_boundary.${language}.2026-04-22`,
|
|
21
|
+
wraps_javascript_runtime: false
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function assertRejected(pack, evidence, expectedCode) {
|
|
26
|
+
const validation = validateXoonyaNativeReferencePromotionEvidence(pack, evidence);
|
|
27
|
+
assert.strictEqual(validation.promotion_allowed, false, `expected ${expectedCode} to block reference promotion`);
|
|
28
|
+
assert.strictEqual(
|
|
29
|
+
validation.rejection_codes.includes(expectedCode),
|
|
30
|
+
true,
|
|
31
|
+
`missing deterministic rejection code ${expectedCode}`
|
|
32
|
+
);
|
|
33
|
+
return validation;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function main() {
|
|
37
|
+
const pack = buildXoonyaNativeReferenceImplementationPack();
|
|
38
|
+
const summary = summarizeXoonyaNativeReferenceImplementationPack();
|
|
39
|
+
const validPythonEvidence = buildValidPromotionEvidence(pack, "python");
|
|
40
|
+
const validPythonPromotion = validateXoonyaNativeReferencePromotionEvidence(pack, validPythonEvidence);
|
|
41
|
+
|
|
42
|
+
assert.strictEqual(pack.category, "xoonya-native-reference-implementation-pack", "native reference pack category mismatch");
|
|
43
|
+
assert.strictEqual(summary.category, "xoonya-native-reference-implementation-summary", "native reference summary category mismatch");
|
|
44
|
+
assert.strictEqual(pack.implemented_reference_implementations.length, 1, "only JavaScript should be implemented today");
|
|
45
|
+
assert.strictEqual(pack.deterministic_rejection_codes.length >= 11, true, "reference promotion rejection codes missing");
|
|
46
|
+
assert.strictEqual(summary.deterministic_rejection_code_count, pack.deterministic_rejection_codes.length, "summary rejection code count mismatch");
|
|
47
|
+
assert.strictEqual(validPythonPromotion.promotion_allowed, true, "complete Python promotion evidence should pass validation");
|
|
48
|
+
assert.deepStrictEqual(validPythonPromotion.rejection_codes, [], "complete Python evidence should not carry rejection codes");
|
|
49
|
+
|
|
50
|
+
assertRejected(pack, buildValidPromotionEvidence(pack, "javascript"), "reference_language_not_registered");
|
|
51
|
+
assertRejected(pack, { ...validPythonEvidence, candidate_repository_ref: null }, "candidate_repository_missing");
|
|
52
|
+
assertRejected(pack, { ...validPythonEvidence, vector_sets_passed: pack.required_vector_sets.slice(0, 1) }, "required_vector_set_missing");
|
|
53
|
+
assertRejected(pack, { ...validPythonEvidence, deterministic_error_code_parity_ref: null }, "deterministic_error_code_parity_missing");
|
|
54
|
+
assertRejected(pack, { ...validPythonEvidence, independent_parser_ref: null }, "independent_parser_evidence_missing");
|
|
55
|
+
assertRejected(pack, { ...validPythonEvidence, signature_crypto_parity_ref: null }, "signature_crypto_parity_missing");
|
|
56
|
+
assertRejected(pack, { ...validPythonEvidence, round_trip_ref: null }, "round_trip_evidence_missing");
|
|
57
|
+
assertRejected(pack, { ...validPythonEvidence, conformance_mark_review_ref: null }, "conformance_mark_review_missing");
|
|
58
|
+
assertRejected(pack, { ...validPythonEvidence, forbidden_claim_review_ref: null }, "forbidden_claim_review_missing");
|
|
59
|
+
assertRejected(pack, { ...validPythonEvidence, wraps_javascript_runtime: true }, "javascript_wrapper_forbidden");
|
|
60
|
+
assertRejected(pack, { ...validPythonEvidence, npm_token: "npm_accidental_secret" }, "secret_material_forbidden");
|
|
61
|
+
|
|
62
|
+
const output = {
|
|
63
|
+
ok: true,
|
|
64
|
+
product: "xoonya",
|
|
65
|
+
category: "xoonya-native-reference-promotion-gate-verification",
|
|
66
|
+
status: "reference_promotion_requires_independent_vector_crypto_round_trip_and_mark_evidence",
|
|
67
|
+
deterministic_rejection_code_count: pack.deterministic_rejection_codes.length,
|
|
68
|
+
adversarial_case_count: 11,
|
|
69
|
+
boundary: "python_and_rust_reference_claims_remain_gated_until_independent_promotion_evidence_is_complete"
|
|
70
|
+
};
|
|
71
|
+
process.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
main();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { spawnSync } = require("child_process");
|
|
6
|
+
|
|
7
|
+
function runPython(command, args) {
|
|
8
|
+
return spawnSync(command, args, {
|
|
9
|
+
cwd: path.resolve(__dirname, ".."),
|
|
10
|
+
encoding: "utf8"
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function main() {
|
|
15
|
+
const script = path.resolve(__dirname, "..", "reference", "python", "verify_vectors.py");
|
|
16
|
+
let result = runPython("python", [script]);
|
|
17
|
+
if (result.error && result.error.code === "ENOENT") {
|
|
18
|
+
result = runPython("py", ["-3", script]);
|
|
19
|
+
}
|
|
20
|
+
if (result.error) {
|
|
21
|
+
throw result.error;
|
|
22
|
+
}
|
|
23
|
+
if (result.status !== 0) {
|
|
24
|
+
process.stderr.write(result.stdout || "");
|
|
25
|
+
process.stderr.write(result.stderr || "");
|
|
26
|
+
throw new Error("Python XNYA reference vector verification failed");
|
|
27
|
+
}
|
|
28
|
+
const summary = JSON.parse(result.stdout);
|
|
29
|
+
assert.strictEqual(summary.ok, true, "Python XNYA reference summary did not pass");
|
|
30
|
+
assert.strictEqual(summary.category, "xnya-python-reference-vector-parity", "Python XNYA reference category mismatch");
|
|
31
|
+
assert.strictEqual(summary.atom_vector_count >= 4, true, "Python XNYA atom vectors missing");
|
|
32
|
+
assert.strictEqual(summary.atom_adversarial_count >= 9, true, "Python XNYA adversarial vectors missing");
|
|
33
|
+
assert.strictEqual(summary.payload_profile_vector_count, 1, "Python XNYP payload vector missing");
|
|
34
|
+
assert.strictEqual(summary.proof_bundle_vector_count >= 10, true, "Python proof bundle vectors missing");
|
|
35
|
+
assert.strictEqual(summary.proof_bundle_verified_vector_count >= 9, true, "Python proof bundle verified vectors missing");
|
|
36
|
+
assert.strictEqual(
|
|
37
|
+
summary.native_signed_crypto_gated_vector_count + summary.native_signed_crypto_verified_vector_count,
|
|
38
|
+
1,
|
|
39
|
+
"Python native signed crypto vector accounting mismatch"
|
|
40
|
+
);
|
|
41
|
+
assert.strictEqual(
|
|
42
|
+
summary.verified_signature_suite_count === 0 || summary.verified_signature_suite_count === 1,
|
|
43
|
+
true,
|
|
44
|
+
"Python verified signature suite count mismatch"
|
|
45
|
+
);
|
|
46
|
+
process.stdout.write("xoonya verify:reference-python passed\n");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
main();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const os = require("os");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { spawnSync } = require("child_process");
|
|
8
|
+
|
|
9
|
+
const rootDir = path.resolve(__dirname, "..");
|
|
10
|
+
|
|
11
|
+
function run(command, args, options = {}) {
|
|
12
|
+
return spawnSync(command, args, {
|
|
13
|
+
cwd: rootDir,
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
...options
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function findPython() {
|
|
20
|
+
const direct = run("python", ["--version"]);
|
|
21
|
+
if (!direct.error && direct.status === 0) {
|
|
22
|
+
return { command: "python", prefixArgs: [] };
|
|
23
|
+
}
|
|
24
|
+
const launcher = run("py", ["-3", "--version"]);
|
|
25
|
+
if (!launcher.error && launcher.status === 0) {
|
|
26
|
+
return { command: "py", prefixArgs: ["-3"] };
|
|
27
|
+
}
|
|
28
|
+
throw new Error("Python 3 is required for the XNYA Python crypto reference check");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function venvPythonPath(venvDir) {
|
|
32
|
+
return process.platform === "win32"
|
|
33
|
+
? path.join(venvDir, "Scripts", "python.exe")
|
|
34
|
+
: path.join(venvDir, "bin", "python");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function assertOk(result, label) {
|
|
38
|
+
if (result.error) {
|
|
39
|
+
throw result.error;
|
|
40
|
+
}
|
|
41
|
+
if (result.status !== 0) {
|
|
42
|
+
process.stderr.write(result.stdout || "");
|
|
43
|
+
process.stderr.write(result.stderr || "");
|
|
44
|
+
throw new Error(`${label} failed`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function main() {
|
|
49
|
+
const python = findPython();
|
|
50
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "xoonya-python-crypto-"));
|
|
51
|
+
const keepVenv = process.env.XOONYA_KEEP_REFERENCE_PYTHON_CRYPTO_VENV === "1";
|
|
52
|
+
try {
|
|
53
|
+
const venvDir = path.join(tempDir, "venv");
|
|
54
|
+
assertOk(
|
|
55
|
+
run(python.command, [...python.prefixArgs, "-m", "venv", venvDir]),
|
|
56
|
+
"Python venv creation"
|
|
57
|
+
);
|
|
58
|
+
const venvPython = venvPythonPath(venvDir);
|
|
59
|
+
assertOk(
|
|
60
|
+
run(venvPython, [
|
|
61
|
+
"-m",
|
|
62
|
+
"pip",
|
|
63
|
+
"install",
|
|
64
|
+
"--disable-pip-version-check",
|
|
65
|
+
"-r",
|
|
66
|
+
path.join(rootDir, "reference", "python", "requirements-optional.txt")
|
|
67
|
+
]),
|
|
68
|
+
"Python optional crypto dependency install"
|
|
69
|
+
);
|
|
70
|
+
const result = run(venvPython, [path.join(rootDir, "reference", "python", "verify_vectors.py")]);
|
|
71
|
+
assertOk(result, "Python crypto-enabled XNYA vector verification");
|
|
72
|
+
const summary = JSON.parse(result.stdout);
|
|
73
|
+
assert.strictEqual(summary.ok, true, "Python crypto-enabled XNYA summary did not pass");
|
|
74
|
+
assert.strictEqual(summary.native_signed_crypto_verified_vector_count, 1, "Python Ed25519 vector was not verified");
|
|
75
|
+
assert.strictEqual(summary.verified_signature_suite_count, 1, "Python verified signature suite count mismatch");
|
|
76
|
+
assert.strictEqual(summary.native_signature_crypto_dependency_missing_count, 0, "Python crypto dependency should be present in isolated venv");
|
|
77
|
+
process.stdout.write("xoonya verify:reference-python-crypto passed\n");
|
|
78
|
+
} finally {
|
|
79
|
+
if (!keepVenv) {
|
|
80
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
81
|
+
} else {
|
|
82
|
+
process.stdout.write(`kept Python crypto venv at ${tempDir}\n`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
main();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const assert = require("assert");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const root = path.resolve(__dirname, "..");
|
|
8
|
+
|
|
9
|
+
function read(relativePath) {
|
|
10
|
+
return fs.readFileSync(path.join(root, relativePath), "utf8");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function ensureContains(body, pattern, label) {
|
|
14
|
+
assert.strictEqual(body.includes(pattern), true, `${label} missing ${pattern}`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function main() {
|
|
18
|
+
const readme = read("reference/rust/README.md");
|
|
19
|
+
const cargo = read("reference/rust/Cargo.toml");
|
|
20
|
+
const lib = read("reference/rust/src/lib.rs");
|
|
21
|
+
|
|
22
|
+
ensureContains(readme, "not a full XNYA-compatible reference implementation yet", "rust readme boundary");
|
|
23
|
+
ensureContains(readme, "Future promotion requires a real Rust toolchain check", "rust readme promotion gate");
|
|
24
|
+
ensureContains(cargo, "publish = false", "rust cargo publish boundary");
|
|
25
|
+
ensureContains(cargo, "name = \"xoonya-native-rust\"", "rust cargo name");
|
|
26
|
+
ensureContains(lib, "pub const XNYA_MAGIC: [u8; 4] = *b\"XNYA\";", "rust magic constant");
|
|
27
|
+
ensureContains(lib, "pub const ATOM_V1_LEN: usize = 58;", "rust atom v1 length");
|
|
28
|
+
ensureContains(lib, "pub const ATOM_V2_LEN: usize = 70;", "rust atom v2 length");
|
|
29
|
+
ensureContains(lib, "atom_bad_magic", "rust deterministic error code");
|
|
30
|
+
ensureContains(lib, "atom_unsupported_length", "rust deterministic error code");
|
|
31
|
+
ensureContains(lib, "atom_unsupported_record_type", "rust deterministic error code");
|
|
32
|
+
ensureContains(lib, "atom_version_length_mismatch", "rust deterministic error code");
|
|
33
|
+
|
|
34
|
+
const summary = {
|
|
35
|
+
ok: true,
|
|
36
|
+
product: "xoonya",
|
|
37
|
+
category: "xnya-rust-reference-scaffold-check",
|
|
38
|
+
status: "source_scaffold_packaged_not_vector_verified",
|
|
39
|
+
checked_files: [
|
|
40
|
+
"reference/rust/README.md",
|
|
41
|
+
"reference/rust/Cargo.toml",
|
|
42
|
+
"reference/rust/src/lib.rs"
|
|
43
|
+
],
|
|
44
|
+
boundary: "rust_candidate_is_source_only_until_cargo_vector_parity_and_round_trip_checks_exist"
|
|
45
|
+
};
|
|
46
|
+
process.stdout.write(`${JSON.stringify(summary, null, 2)}\n`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
main();
|
|
50
|
+
|