DC ORIGIN IDENTITY UNIFICATION V1 (Larihana), Opción A + enmienda D-ID-7 mía.
Ratificado por David 2026-07-28. Firmado approve (pendientes Larihana + Mathi).
EL PROBLEMA (medido por Larihana, verificado por mí en ambos lados):
chain: blake3::derive_key("origin-chain/agent-did/v1", pk) → Did
OCF: blake3::hash(pk) → OitFingerprint
La MISMA pubkey Ed25519 producía 32 bytes DISTINTOS en cada capa. No era un bug
de criptografía: cada capa hizo domain separation correctamente por separado y
nadie decidió la relación entre las dos. Consecuencia: viendo un fingerprint en
un canal de chat NO se podía resolver el DID on-chain sin la pubkey completa —
un usuario tenía una identidad en el chat y otra en la blockchain. Directiva de
David: "que todo lo que creamos tenga una misma identidad para poder acceder".
EL CAMBIO:
- Nueva constante pública ORIGIN_IDENTITY_KDF_CONTEXT = "origin/identity/v1",
el contexto CANÓNICO compartido por todas las capas de Origin.
- derive_did pasa a derivar con ese contexto ⇒ el identificador de 32 bytes es
ahora EL MISMO en chain, chat (OCF), assets y credenciales.
- RUNTIME_VERSION 9→10: cambia la transición de estado de register_agent_did (el
DID calculado y almacenado) ⇒ spec bump obligatorio. Las FIRMAS de los
extrinsics NO cambian ⇒ TRANSACTION_VERSION intacto.
POR QUÉ SIN MIGRACIÓN (la verificación que el DC me delegó, medida no asumida):
- Sin GenesisConfig en el pallet → no se siembran identidades en génesis.
- Sin DIDs en los 3 presets de génesis.
- Sin golden vectors ni DID hex hardcodeado en el repo.
- StorageVersion = 0, nunca migrado — greenfield puro.
- derive_did = UNA función, UN call-site; los tests lo invocan (no pinnean bytes).
⇒ Ningún estado on-chain dependía del esquema viejo. La ventana pre-mainnet
estaba abierta y el costo fue una constante de string.
ENMIENDA D-ID-7 — golden vectors cross-repo (lo que aporté al DC):
El DC arreglaba la INSTANCIA pero no la CLASE. Origin Chain es submódulo y NO
puede depender de arkhe-fabric-core (dep-direction submódulo→monorepo = ILEGAL,
la misma ley que impide el swap del attestation SSOT), así que las dos capas no
pueden compartir la constante por Cargo — y sin ancla podían volver a divergir en
silencio, que es justo el bug que cerramos. Añadidos 3 vectores pinneados a bytes
(2 patrones + 1 pubkey Ed25519 real) para que fabric-core pinnee LOS MISMOS.
Si cualquiera de los dos lados cambia el contexto o la función, su test falla.
Mismo patrón que ya nos salvó con el attestation SSOT: paridad por matemática,
no por disciplina humana.
NO VACUO — verificado empíricamente: saboteé el contexto a "v2-DRIFT" y AMBOS
tests fallaron con el diagnóstico correcto; restaurado, verdes de nuevo. (Un test
que pasa no prueba nada hasta que se le ve fallar sin el fix.)
TRADE-OFF asumido y dejado explícito en el acta del DC: un identificador único en
chat + chain + assets + credenciales implica que ver el fingerprint de alguien en
un canal permite resolver sus activos y transacciones on-chain — no hay frontera
de seudonimato entre capas. Es INHERENTE a "una identidad para todo"; la
alternativa (derivación por-contexto tipo HD) reintroduce los dos identificadores
en dos pantallas que justamente eliminamos. Decisión consciente, no efecto
secundario descubierto después.
Verificado: workspace completo verde (0 fallos), 20/20 en agent-identity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>