Saltar a contenido

Prompt T-3 — Firma did:web del DPP (capa de credenciales verificables)

Arte Taxco / ICEDE-USC · 1 Ago 2026 · prompt acotado para el chat de código. Paridad con PROMPT-T0-PERFIL-TEXTIL.md y PROMPT-T1-ESQUELETO-TEXTIL.md.

Alcance de este chat. SOLO la firma did:web de lo que el DPP ya emite: emisor único (Arte Taxco), Ed25519 + JWS, VCs por atributo, y verificación de vuelta contra el documento DID servido por HTTPS. Es la fase T-3(a) de RUTA-DEMOSTRADOR-TEXTIL.md. NO hace la conformidad EN completa (EN 18219/18216/18222, PDF/A-3 estricto) ni los DIDs por-actor — eso queda fuera (§ FUERA DE ALCANCE), igual que T-1 acotó su alcance.


Eres el asistente técnico del proyecto Arte Taxco. Antes de tocar nada, LEE en este orden: - docs/SYSTEM-PROMPT.md, docs/FIXES.md (reglas de trabajo; español; aditivo; NUNCA prisma migrate dev) - docs/DECISIONES-INTEROPERABILIDAD-DPP.mdQ4 (la decisión ya tomada: did:web v1 anclado por HTTPS/DNS, sin blockchain, faseado; AT firma; DIDs por-actor = después) - docs/RUTA-DEMOSTRADOR-TEXTIL.md (la ruta; T-3 es "Conformidad EN" — este chat es su primer trozo: la firma did:web) - docs/MAPA-ECOSISTEMA-DPP.md (VC/firmas como transversal; gate anti-sobreafirmación) - docs/ARQUITECTURA-DPP-CADENA-PROPIEDAD.md (cada registro = una claim firmable / VC-ready) - apps/web/lib/dpp/atributos.ts (AtributoVista, Estatus ya con ATESTADO, PERFILES) - apps/web/lib/dpp/atestacion.ts (write-path T-1 registrarAtributoAtestado — dónde firmar) - apps/web/lib/dpp/export.ts (dónde se emite el DPP: XML/EPCIS/PDF) - apps/web/app/api/dpp/[folio]/route.ts (endpoint de export — para añadir f=vc) - apps/web/public/dpp/dpp-1.0.xsd (para extender el XSD de forma aditiva) - el modelo AtributoDPP y el enum EstatusAtributo en apps/web/prisma/schema.prisma

CONTEXTO: T-0 dio el perfil textil (nivelExigido por atributo) y T-1 la cadena de atestación (CONFECCION/MARCA escriben AtributoDPP con emisorRol y estatus acotado: ATESTADO para hechos de cadena, DECLARADO para el resto). Hoy el DPP se emite en XML/EPCIS/PDF con el estatus y el emisor por atributo, pero sin firma: un tercero no puede probar criptográficamente que ese registro lo emitió Arte Taxco y no fue alterado. T-3(a) añade esa capa: una identidad did:web de Arte Taxco y una firma por atributo (Verifiable Credential), verificable resolviendo el DID por HTTPS. Es lo que convierte el "atestado por CONFECCION" de T-1 en una claim verificable por máquina.

REGLA DE HONESTIDAD (la línea roja de todo el proyecto): la firma prueba (a) integridad del registro y (b) identidad del emisor (la plataforma Arte Taxco) — NO la veracidad del hecho atestado. Un DECLARADO firmado sigue siendo declarado; el gap nivelExigido↔estatus sigue visible. Firmar NO sube el estatus. Y v1 = un solo emisor (AT); que cada operador firme con su propia llave (DID por-actor) es incremento posterior.

TAREA T-3(a) — en pasos, cada uno con su commit:

0) DEPENDENCIA Y SUITE DE FIRMA. Añade jose a apps/web (JWS puro, sin binarios nativos). Suite: Ed25519 (EdDSA) + JWS compacto. Decisión documentada: JWS (no W3C Data Integrity/JSON-LD) en v1 — se verifica resolviendo did:web por HTTPS, sin canonicalización RDF. Data Integrity queda como incremento posterior.

1) IDENTIDAD did:web (documento DID). - Script one-off scripts/generar-clave-didweb.ts: genera UNA vez el par Ed25519 e imprime la JWK pública y la privada. La privada NUNCA se commitea — va a env (DIDWEB_PRIVATE_JWK en .env local + Vercel). La pública a DIDWEB_PUBLIC_JWK. - Ruta app/.well-known/did.json/route.ts (GET) que sirve el DID Document: id: did:web:certificados.artetaxco.mx, un verificationMethod con la JWK pública (leída de env), assertionMethod apuntando a esa clave. did:web:certificados. artetaxco.mx resuelve por spec a https://certificados.artetaxco.mx/.well-known/did.json. - DECISIÓN A RESOLVER (recomendación incluida): el dominio del DID. Q4 dice "anclado en artetaxco.mx", pero ese dominio es Shopify y no sirve /.well-known arbitrario; la app Next que emite el DPP vive en certificados.artetaxco.mx. Recomendado: did:web:certificados.artetaxco.mx. Documenta la divergencia con Q4 y su razón.

2) PRIMITIVA DE FIRMA — punto único lib/dpp/firma.ts: - firmarClaim(payload): Promise<string> → JWS compacto EdDSA, kid = did:web:…#key-1. - verificarClaim(jws): Promise<payload|null> → resuelve la clave pública (de env o del did.json) y valida firma + expiración. Nunca lanza en verificación fallida: devuelve null.

3) FIRMAR CADA AtributoDPP COMO VC. Construye una VC mínima por atributo (issuer = did:web AT, credentialSubject = {folio, clave, valor, estatus, nivelExigido, emisorRol}, issuanceDate) y fírmala → guarda el JWS. - Almacenamiento aditivo (prisma db push, NUNCA migrate dev): columnas nuevas pruebaJws String? y firmadoEn DateTime? en AtributoDPP. - Cablea la firma dentro de registrarAtributoAtestado (best-effort, como el bloque epistémico de verificarOferta: si falla, NO rompe la escritura del atributo). - Script scripts/backfill-firmas-didweb.ts (--dry-run/--limit) para firmar los atributos ya persistidos (incluida la prenda demo ATA-DEMO-TEXTIL-T1). - Comentario anti-sobreafirmación: la firma NO altera estatus ni nivelExigido.

4) EMITIR LA FIRMA + VERIFICAR. - Export: en f=xml, por atributo firmado, un <Prueba tipo="JWS-EdDSA" did="did:web:…"/> con el JWS; extiende AtributoType en el XSD de forma aditiva (atributo/elemento opcional → documentos previos siguen válidos; xmllint --schema en verde). - Nuevo formato f=vc en app/api/dpp/[folio]/route.ts: devuelve las VCs firmadas (JSON) de esa pieza. - scripts/verificar-didweb.ts <folio>: resuelve el did.json servido, verifica cada JWS, reporta válidas/inválidas y demuestra que manipular un valor invalida la firma.

5) VERIFICACIÓN END-TO-END de la prenda demo: firma sus 6 atributos (backfill), sirve el did.json, y corre verificar-didweb.ts ATA-DEMO-TEXTIL-T1 → todas válidas; altera un valor a mano y comprueba que la verificación falla.

RESTRICCIONES DURAS: - 100% aditivo. Enum/columnas nuevas: npx prisma db push, NUNCA migrate dev. (Recuerda el gotcha de red 5432; si está bloqueado, aplicar db push desde hotspot con la URL directa.) - La clave privada NUNCA en el repo — solo env (.env local + Vercel). El .env no se toca salvo AÑADIR las dos claves nuevas (comentar, nunca borrar variables). - No toques joyería, PERFILES.joyeria, ni el flujo de recertificación (verificarOferta) salvo lo mínimo para adjuntar la firma. - Anti-sobreafirmación: la firma prueba integridad + emisor, NO veracidad; el gap nivelExigido↔estatus sigue visible; v1 = un solo emisor (AT). - Español en código, comentarios y commits. Documenta en docs/FIXES.md (sugerido FEAT-DPP-TEXTIL-T3-001) y anota la decisión de dominio del DID en DECISIONES-INTEROPERABILIDAD-DPP.md (cierre de Q4-firmas v1).

CRITERIO DE ACEPTACIÓN: - npx tsc --noEmit → 0 errores (el proyecto está en 0; mantenerlo). - GET /.well-known/did.json sirve un DID Document válido con la clave pública de AT. - Las VCs de la prenda demo ATA-DEMO-TEXTIL-T1 verifican contra ese DID (script en verde); alterar cualquier valor invalida la firma. - El export f=xml lleva la <Prueba> por atributo firmado y valida con xmllint --schema; f=vc devuelve las VCs. Joyería y recertificación intactos. - MUÉSTRAME EL DIFF ANTES DE HACER PUSH. Dame el comando de commit explícito, en español.

FUERA DE ALCANCE (son T-3 posteriores u otras fases — NO los hagas aquí): - DIDs por-actor (cada operador firma con su propia llave) — v2 de firmas. - W3C Data Integrity / JSON-LD (proof eddsa-rdfc-2022) — alternativa al JWS, después. - EN 18219 (GS1 Digital Link), EN 18216/18222 (API contra norma), PDF/A-3 estricto (XMP + OutputIntent) — el resto de la conformidad EN de T-3. - eIDAS/EUDI wallet, revocación/estado de credencial, blockchain, timestamping externo. - Laboratorio (T-2), endpoint de la planta de clasificación (T-4), empresas reales.


Decisiones (resueltas para este chat)

  • Suite → Ed25519 + JWS compacto (lib jose). Verificable con did:web por HTTPS, sin deps nativas ni canonicalización RDF. Data Integrity = incremento posterior.
  • Un solo emisor (AT) en v1. DIDs por-actor diferidos (Q4). AT firma el REGISTRO de cada atributo; el emisorRol del operador viaja DENTRO de la VC como dato, no como firmante.
  • Dominio del DID → did:web:certificados.artetaxco.mx (la app Next sirve /.well-known/did.json; artetaxco.mx es Shopify y no puede). Divergencia documentada de la letra de Q4, fiel a su intención (anclaje HTTPS/DNS, bajo-ops).
  • Prenda de prueba → la demo T-1 ya sembrada (ATA-DEMO-TEXTIL-T1), reutilizada como banco de pruebas de la firma.

Arte Taxco / ICEDE-USC · Prompt T-3(a) firma did:web · 1 Ago 2026 · alcance, no implementación. Deriva de RUTA-DEMOSTRADOR-TEXTIL.md (T-3) y cierra Q4-firmas v1.