diff --git a/arkhe-origin-chain b/arkhe-origin-chain new file mode 120000 index 0000000..46172d0 --- /dev/null +++ b/arkhe-origin-chain @@ -0,0 +1 @@ +/Users/davidherran/originmetaverse/external/arkhe-origin-chain/ \ No newline at end of file diff --git a/crates/origin-chain-agent-identity/src/tests_integration.rs b/crates/origin-chain-agent-identity/src/tests_integration.rs index d61bc68..bb70d9d 100644 --- a/crates/origin-chain-agent-identity/src/tests_integration.rs +++ b/crates/origin-chain-agent-identity/src/tests_integration.rs @@ -368,3 +368,71 @@ fn scenario_12_genuine_did_collision_rejected_canonical() { assert!(Identities::::get(&second_acct).is_none()); }); } + +// ═══════════════════════════════════════════════════════════════ +// CONDICIÓN DE MATHI al retirar la #4 (DC ORIGIN IDENTITY UNIFICATION V1, +// ruling 2026-09-01): el prefijo `did:origin::` es ETIQUETA DE DISPLAY, +// JAMÁS autoridad. Su exigencia textual: «ningún consumidor puede decidir +// leyendo el prefijo, y debe existir un test que lo demuestre». +// +// En MI capa eso se prueba de raíz: si el DID no PORTA el kind, ningún +// consumidor puede inferirlo de él aunque quiera — la única fuente posible +// es la atestación on-chain firmada. Esto no es una convención: es una +// imposibilidad aritmética, y este test la fija. +// ═══════════════════════════════════════════════════════════════ + +#[test] +fn kind_authority_is_the_attestation_never_the_did() { + new_test_ext().execute_with(|| { + // Alice se registra como HYBRID (el Inmutable #41 exige co-autor). + let sig = sign_registration(&alice_pair(), &alice_account()); + assert_ok!(Pallet::register_agent_did( + alice_origin(), + alice_pubkey(), + AgentKind::Hybrid, + alloc::vec![bob_pubkey()], + sig, + )); + let identity = Identities::::get(&alice_account()).expect("registrada"); + + // ── 1. EL DID NO SABE NADA DEL KIND ──────────────────────────── + // Es byte-idéntico al que produce la derivación PURA de la pubkey. + // Un Human con esta misma llave tendría EXACTAMENTE este DID. + assert_eq!( + identity.did, + derive_did(&alice_pubkey()), + "el DID debe depender SOLO de la pubkey; si depende del kind, \ + la condición #4 se coló y un cambio de rol rotaría la identidad" + ); + + // ── 2. LA AUTORIDAD ES LA ATESTACIÓN ─────────────────────────── + // El kind vive en el registro firmado on-chain, y ahí es donde un + // consumidor DEBE preguntarlo. + assert_eq!(identity.kind, AgentKind::Hybrid); + + // ── 3. EL CONTRAFACTUAL (la mitad que hace que esto pruebe algo) ─ + // Así se vería el DID si el `kind` HUBIERA entrado al material + // hasheado, que es exactamente lo que la condición #4 proponía. + // DEBE DIFERIR del real: si algún día coincidieran, el kind se + // habría colado a la derivación y este test se pone rojo. + let mut material_con_kind = alice_pubkey().to_vec(); + material_con_kind.push(2u8); // discriminante de Hybrid + let did_si_el_kind_entrara = + blake3::derive_key(crate::ORIGIN_IDENTITY_KDF_CONTEXT, &material_con_kind); + assert_ne!( + identity.did.as_bytes(), + &did_si_el_kind_entrara, + "el DID real coincide con el que produciría meter el kind al KDF: \ + la condición #4 RETIRADA volvió a entrar por la puerta de atrás" + ); + + // ── 4. Y LA CONSECUENCIA QUE MATHI QUERÍA PROTEGER ───────────── + // Como el DID es el mismo para cualquier kind, un consumidor que + // decidiera «por el prefijo» estaría decidiendo sobre un dato que + // el identificador NO contiene. Cambiar de Human a Hybrid deja el + // DID intacto — la identidad SOBREVIVE a la transición que el + // Inmutable #41 permite. + let did_antes_de_cualquier_rol = derive_did(&alice_pubkey()); + assert_eq!(identity.did, did_antes_de_cualquier_rol); + }); +}