Consent protocol: Internet-Draft -03

XCIM records explicit consent from the person controlling a recipient email address to an identified sender for specified types of communication. An independent third party attests the consent, with immutable evidence anchored in a blockchain.

Revision -03 specifies EVP, OAuth with authenticated provider API verification, and OpenID Connect (OIDC) as alternative methods to establish control of the email address giving consent. An issuer may use any one admitted method after its required checks. Address verification alone does not grant permission: the same recipient must separately and explicitly accept the identified sender and communication types.

Corrected scope and revision status · eXplicit Consent-Identified Mail (XCIM): draft-saez-xcim-03 · Published text.

This is an individual Internet-Draft with intended status Experimental. Publication does not imply IETF endorsement, working-group adoption or an approved RFC. Amoy provisioning and live-node trials remain paused.

Authority and fresh revocable state

AS-01 adopted direction for G04-G06: contracts, alternatives, fixtures and closure criteria.

A1-A6 and D01-D06 adopted as project direction. AS01-F01 adds offline schemas and signed fixtures. Live anchor/DNS/actor verification, durable recovery and SMTP/MX operation remain pending; no production PASS is claimed.

Recommendation: provision receiver-local trust; authenticate a role manifest from that root; require a control head and checkpoint signed with different keys; commit permission and authority from the same write cut; independently verify the newly selected anchor profile. Existing P1 and frozen WD bytes keep their meaning.

DecisionRecommendationClosure gate
D04: authorityExplicit local pins first, root/recovery quorums, scoped roles and lifecycle.Exact DNS/possession/recovery contracts, schemas and independent implementation.
D05: current stateAtomic cut, durable floors, proven absence, conservative expiry.Boundary/concurrency/rollback vectors and measured continuous renewal.
D06: publicationNew anchored composite checkpoint; no silent reuse of Amoy 0.1.Exact adapter/ABI/genesis/finality and full proof verifier.

Trial hypotheses: state age up to 300 seconds, snapshot cadence 60 seconds, root-manifest age up to 24 hours. Publication-key compromise is not covered by a five-minute revocation promise. These values and a 120-second p99 publication target are unmeasured proposals.

A1-A6 adoption is recorded in the decision record. AS01-F01 executes 97 scenarios plus 37 structural cases; its coverage register distinguishes the original 24-scenario plan from still-unimplemented operational cases. These checks are not independent operator interoperability.

Full proposal source · Decision ledger · Review bundle and existing P1 fixtures · Implementation evidence

AN01-P01 now proposes the exact anchor ABI, genesis, network and finality policy, with alternatives, N1–N6 closure gates and unmeasured limits. N1–N6 are now adopted; AN01-F01 adds contract, schemas and local EVM fixtures. No public contract is deployed.

AS-01 — propuesta de autoridad, revocación y frescura para P1

Diseño de referencia: AS-01-proposal-01, 2026-10-19. Estado actual: A1–A6 / D04–D06 adoptadas como dirección por instrucción explícita del usuario. AS01-F01 concreta schemas y fixtures; las dependencias y el cierre M/O siguen pendientes. Este texto conserva el razonamiento y alternativas del diseño. No cambia WD-02-E1, los objetos P1-01 ni sus 135 casos. Los sitios distribuyen material de desarrollo; no hay verificador de anchor AS ni autoridad operativa acreditada.

1. Recomendación concreta y decisión solicitada

Recomiendo desarrollar AS-01 como perfil nuevo explícito: raíz de confianza provisionada por el receiver, manifiesto de autoridad firmado por esa raíz, checkpoint que vincule permiso y autoridad del mismo corte y una cabeza de control firmada con otra clave. El checkpoint requiere publicación anclada independientemente verificada. La presentación puede adjuntar la evidencia o permitir recuperarla de mirrors; no exige consultar al issuer por mensaje.

Decisión Recomendación Alternativas Motivo y coste
D04 — bootstrap y autoridad Pins locales explícitos por issuer/log como mínimo; raíz de mantenimiento y recuperación separadas; roles y ámbitos verificables. Dejar una ruta de registry autenticado para una extensión posterior. Descubrimiento HTTPS autoautorizado; registry universal obligatorio; Web PKI/DNS como única identidad de app; pins sin lifecycle. Evita inventar una autoridad global. Requiere distribuir pins y updates autenticados; un certificado HTTPS no acredita al Consent Issuer.
D05 — estado y frescura Estados probados del mismo corte, expiración exclusiva, deadlines por evidencia, high-water marks persistentes y resultado sin señal positiva ante dependencia ausente. Status HTTP por mensaje; CRL/lista completa; sólo expiración de MSA/MP; extender caché en fallos. Permite caché/stapling acotados y revocación de permisos y claves. Cuesta generar y transportar pruebas; no ofrece revocación instantánea.
D06 — publicación Checkpoint compuesto nuevo con anclaje externo seleccionado explícitamente. Mantener Amoy como entorno experimental; diseñar su adaptador AS antes de probarlo. Sólo firma del issuer; log con monitores/testigos; nuevo perfil sin cadena; reinterpretar el anchor Amoy 0.1. Conserva la exigencia de publicación del core. Necesita adaptador/ABI y política de finality nuevos; una firma o log aislado no elimina split views.

Dirección adoptada: A1–A6 de §12, registrada en ACCEPTED-A1-A6.md. La recomendación es A1/A2/A3/A4 como aquí, A5 con parámetros iniciales medibles y A6 con pins locales primero. La adopción habilitó schemas y vectores AS; no cierra G04–G06 M/O.

2. Garantías y límites

El receiver debe poder responder cinco preguntas separadas:

  1. ¿Acepto a este issuer y este log bajo mi política, para este perfil?
  2. ¿Qué clave podía firmar cada objeto al emitirlo y conserva autoridad actual?
  3. ¿Siguen activos la app/epoch, los dominios, la MSA y su clave MP?
  4. ¿Sigue activo exactamente este permiso del destinatario/app/propósito?
  5. ¿Hasta cuándo es utilizable esta evidencia, y he observado algo posterior?

No se prueba la veracidad del consentimiento frente a un issuer deshonesto. Un anchor autentica compromisos y orden bajo su política; no valida la autorización del cambio de estado ni la verdad de sus hojas. El receiver sigue confiando en las atestaciones de autoridad/consentimiento y, salvo que replique y compruebe todo el log, en la proyección firmada del estado. Se requieren monitores para detectar transiciones inválidas. Separar claves dentro del mismo operador no equivale a operadores independientes.

Una revocación desconocida puede quedar oculta durante la ventana de evidencia todavía válida. La propuesta ofrece una cota de antigüedad, no conocimiento instantáneo del último estado mundial. Si se observa una revocación o cabeza más nueva, no se puede seguir usando una anterior aunque aún no haya vencido.

3. Contratos candidatos y bytes

Se proponen siete contratos principales C1–C7 y un registro de lifecycle C8. Los schemas y fixtures ejecutables actuales se publican en AS01-F01, con concreciones de C1/C7 documentadas en su CONTRACT.md. Falta el Proof verifier con anchor vivo; los checks de AS y P1 son offline y no emiten XCIM_PASS.

Para nuevos objetos AS: JSON estricto/E1, JCS y enteros seguros; tiempos iat, exp, this_update, next_update, effective_at en segundos Unix UTC. Intervalos [inicio, fin). Identificadores existentes se comparan exactamente; hashes/thumbprints nuevos son base64url canónico de 32 octetos. No emitir direcciones ni PII en los objetos públicos. Los objetos son cerrados salvo uniones enumeradas aquí; un campo crítico desconocido no se ignora.

Payloads firmados usan proposal_version: "as-01", object_type exacto, issuer_id y log_id donde corresponda. JWS flattened de P1 para una firma; para quórum, objeto cerrado {payload, signatures} y firmas cerradas {protected, signature}, ambas cadenas base64url. Cada protected es {alg, kid, typ}, JCS, alg: "Ed25519"; kid selecciona una clave previamente autorizada, nunca una URL. Distintos firmantes se cuentan por thumbprint, no por cantidad de firmas. typ candidato application/xcim-as-{object_type}+jcs, sin registro IANA ni sufijo aprobado. G07/G10 deben revisar estos bytes.

H = SHA-256; J = JCS; U = UTF-8; b64u = base64url sin padding
commit(type, payload) = b64u(H(U("XCIM-AS-01-" + type + "\0") || J(payload)))

Tags exactos de tipo: GENESIS, MANIFEST, CHECKPOINT, CONTROL-HEAD, EVENT, STATE-VALUE, LOCATOR, MATERIAL. El compromiso es del payload validado, no del JWS completo. Los compromisos RBA/MSA/MP de P1 no cambian. MATERIAL compromete el objeto canónico {format, value}: format es p1-jws-envelope para la MSA completa firmada, o as-record para registros app/clave/dominio. Cualquier comparación debe identificar ambos tipo y bytes.

C1 — ReceiverTrustPolicy (configuración local)

No se recibe como autoridad desde un email. Campos locales obligatorios: policy_id, policy_epoch, issuer_id, log_id, profile_id, root_keys, root_threshold, recovery_keys, recovery_threshold, trusted_genesis_commitment, accepted_manifest_epoch_floor, anchor_policy, fetch_origins, valid_until, max_clock_uncertainty y los límites de §7. profile_id: "as-01-anchored" es nombre candidato. Cada pin identifica alg/key/thumbprint y rol. Sin pin público por defecto.

El genesis AS es el payload cerrado {issuer_id, log_id, profile_id, origin_nonce, anchor_policy_id}. Su compromiso usa tag GENESIS, nonce de 32 octetos y política de anchor ya aceptada; no incluye hashes de manifiestos o checkpoints que lo referencien. C2/C3/C4 incluyen genesis_commitment además de sus campos enumerados abajo y deben coincidir con C1. Así el origen se liga al perfil sin compromisos circulares. Un nuevo log_id/genesis exige nueva aceptación local; no lo elige libremente un mensaje.

Recomendación inicial: raíz de mantenimiento con quórum 2 de 3 y recuperación 2 de 3 disjunta; las claves online no pertenecen a esos conjuntos. Un equipo puede configurar otro quórum explícitamente, documentando menor tolerancia. Se requiere al menos un ancla inicial de historia aceptada y el control de la distribución local de políticas; reinstalar no permite resetear floors.

Una rotación ordinaria de raíz requiere quórum de raíz vieja y nueva sobre el mismo documento de transición {issuer_id, old_policy_epoch, new_policy_epoch, old_set_commitment, new_set_commitment, effective_at}. La recuperación utiliza el conjunto de recuperación ya provisionado y eleva policy_epoch; suspende positivos hasta instalar nueva raíz/genesis o un sucesor verificado. No se acepta una recovery key anunciada por la raíz comprometida. Si se compromete también el quórum de recuperación, hace falta reprovisionamiento externo; la especificación no puede reconstruir confianza.

Registry opcional futuro: raíz de registry aceptada localmente → acreditación vigente y acotada a issuer/perfil → raíz del issuer. Profundidad máxima dos delegaciones después de la raíz local, sin ciclos ni fallback automático a otro registry. El contrato de estado del registry y sus propias revocaciones debe diseñarse antes de habilitar esa ruta. No se presupone que exista hoy.

C2 — AuthorityManifest (raíz → roles online)

Payload cerrado: campos comunes, manifest_epoch, previous_manifest_commitment (null sólo en origen aceptado), root_policy_epoch, keys, publication_profile, fetch_origins, iat, exp. keys es lista finita única por kid/thumbprint con {kid, alg, public_jwk, thumbprint, role, valid_from, valid_until, status}; status es active, retired o revoked. Una clave tiene un solo rol AS.

Roles: receipt, recipient_binding, authority_attestation, state_checkpoint y control_head. Claves state_checkpoint y control_head deben tener thumbprints distintos. app_control/message_presentation no se obtienen de discovery: sus autoridades específicas están en C5. La raíz autoriza el manifiesto por quórum; verificar hash de JWK y límites de cada descriptor. El manifiesto nunca autoriza a sus claves a reemplazar la raíz.

El receiver conserva el mayor epoch/commitment aceptado. Mismo epoch con otro compromiso implica conflicto; epoch menor no restaura autoridad. Nuevos epochs requieren la cadena completa de manifiestos o un floor reprovisionado por raíz aceptada; no se salta un revocado. Discovery sólo localiza bytes. El manifiesto define orígenes de transporte, limitados además por la allowlist local.

Límite de seguridad: las claves C3/C4 se revocan en C2 o mediante política de recuperación C1, nunca por una hoja que ellas mismas autentican. C2 tiene edad máxima candidata de 24 horas. Un atacante que oculte un C2 más nuevo puede conservar un C2 anterior aún válido hasta ese límite. No se promete retirar esas claves en cinco minutos; raíz/recuperación y sus canales deben ensayarse.

C3 — ControlHead (cabeza reciente, firma separada)

Payload cerrado: campos comunes, head_sequence, previous_head_commitment, manifest_epoch, manifest_commitment, checkpoint_sequence, checkpoint_commitment, checkpoint_key_thumbprint, this_update, next_update. La primera cabeza referencia null sólo en el origen aceptado; las demás avanzan exactamente en uno con historial recuperable.

Se firma con control_head bajo C2 vigente. Cada cabeza referencia un solo checkpoint C4 exacto del mismo issuer/log/manifiesto. No puede declarar vigente otro C2. checkpoint_key_thumbprint debe coincidir con el firmante C4 autorizado. No es una prueba de terceros ni una nueva raíz: limita la capacidad de una clave de checkpoint comprometida de inventar por sí sola una publicación actual. Comprometer ambos roles anula esa separación; C1/C2 siguen siendo necesarios.

this_update de C3 debe ser igual al this_update C4, y next_update no lo excede. Una cabeza creada después no renueva el corte. Para renovar se genera un nuevo C4, aun sin eventos, y se verifica nuevamente su anclaje.

C4 — StateCheckpoint (corte consistente y publicación)

Payload cerrado: campos comunes, checkpoint_sequence, previous_checkpoint_commitment, manifest_epoch, manifest_commitment, snapshot_id (32 octetos aleatorios), permission_batch, authority_history, authority_state_root, this_update, next_update, publication_profile. Firma state_checkpoint; secuencia inicia en uno y avanza en uno, con null predecesor sólo en genesis aceptado. No hay URL ni evidencia de anchor dentro del payload que será comprometido por ese mismo anchor.

permission_batch es objeto cerrado {batch_sequence, batch_manifest_commitment, tree_size, event_root, state_root, created_at}. Identifica el payload exacto de un batch WD 0.1 verificado con su clave batch autorizada por la política de compatibilidad; se agrega rol legacy_batch explícito en C1 para ese caso, sin confundirlo con state_checkpoint. Se conserva el compromiso establecido XCIM-BATCH-MANIFEST-0.1\0; no se renombra como hash AS. Validar schema, firma, todos los campos, continuidad y pruebas de receipt/permiso WD existentes.

authority_history es {tree_size, event_root} de la historia AS (§5). Permisos conservan su árbol/estado WD; app, dominios, MSA y claves usan un árbol AS separado. No se introducen tipos nuevos en los schemas/raíces WD cerrados. permission_batch.created_at == this_update C4; ambos se sellan sobre el mismo corte lógico de escritura. El productor debe impedir cambios concurrentes a cualquiera de las dos proyecciones hasta sellarlas o abortar y reintentar. La firma atestigua esa atomicidad: por sí sola no la demuestra a un tercero.

Un checkpoint sin eventos nuevos requiere nuevo batch WD de cero eventos y nuevo C4/anclaje. Debe comprobarse que raíces/tamaños no cambiaron; no se permite referenciar un viejo batch y cambiarle sólo el reloj. next_update candidato como máximo this_update + 300. Un timestamp de wrapper/descarga no lo extiende.

Anchor AS nuevo: el adaptador elegido debe autenticar al menos (profile_id, issuer_id, log_id, checkpoint_sequence, checkpoint_commitment, previous_checkpoint_commitment) y comprobar red, contrato/código, firmante, transacción/evento exactos, bloque canónico, finalidad y variantes conflictivas. El hash C4 ya compromete ambas proyecciones y sus raíces; no hay ciclo. La identidad/genesis del adaptador está fijada en C1 y referida por C2/C4.

No se define aquí un ABI final ni se despliega un contrato. El anchor Amoy 0.1 no se reinterpreta como anchor AS. Su validación histórica continúa intacta. Seleccionar red/contrato/finalidad y fijar los bytes exactos del adaptador es una dependencia bloqueante de G06-M, no un detalle de configuración oculto.

C5 — AuthorityStateValue y materiales

La hoja de estado AS es cerrada: proposal_version, object_type: "authority_state_value", issuer_id, log_id, locator, state_epoch, status, effective_at, valid_until, material_commitment, latest_event_commitment. El locator se deriva del objeto esperado, nunca se copia sin verificar de la prueba. No hay next_update autodeclarado por hoja. Frescura viene de C4/C3; valid_until agrega un deadline, no lo prolonga.

Tipo / locator cerrado Material autenticado que se debe presentar Regla decisiva
application: {kind, app_id} {app_id, app_epoch, authority_epoch, control_key_thumbprint} Hoja actual de la app, no buscada sólo por viejo epoch. El epoch esperado por MSA/MP debe ser el actual.
key: {kind, owner_id, kid} {owner_id, kid, thumbprint, public_jwk, alg, role, app_epoch, authority_epoch, valid_from, valid_until} kid nunca se reutiliza para otro material; issuer roles usan epochs null, app roles epochs enteros. Comparar rol y propietario exactos.
domain: {kind, app_id, domain, role} {app_id, app_epoch, domain, domain_epoch, role, observation_commitment, observed_at, recheck_by} Dominio A-label exacto y role WD exacto; evidencia de challenge observada por autoridad aceptada. Vence también en recheck_by.
msa: {kind, app_id, authorization_id} Envelope MSA P1 completo mediante MATERIAL Hash, scope, app/authority epochs, kid y thumbprint idénticos. No basta una hoja por ID con otra MSA.

owner_id identifica issuer o app sin inferirlo del dominio. Un rol no se expande a otro. Para P1 se requieren dominio rfc5322_from y dkim_signing, además de consent_presentation_delegate cuando corresponda a la delegación. Los nombres organizacionales no sustituyen esos roles. La clave DKIM real se verifica bajo DKIM/DNS y política del receiver; una hoja XCIM de dominio no reemplaza esa comprobación. DNSSEC no se presume.

El registro de dominio se atestigua con authority_attestation después de un challenge contextual de 32 octetos, vida candidata 600 s, ligado a issuer/app, dominio/rol y clave de control. Requiere consulta DNS por el observador, nombre de registro y respuesta exactos, sin aceptar un resultado aportado por sender. Nombre TXT, payload firmado de observación, resolvers/validación y política ante transferencia deben fijarse antes de G04-M; aquí no se inventa prueba DNS. Rechequeo candidato cada 86400 s: no garantiza detectar una transferencia entre observaciones; ese riesgo debe aceptarse o reducirse explícitamente.

Al MSA la firma la clave app_control vigente de su app; no el issuer ni el ESP por afirmación propia. Su alta exige prueba de posesión de la clave MP sobre {issuer_id, app_id, app_epoch, authority_epoch, authorization_id, msa_commitment_p1, challenge, expires_at}; challenge de un uso y hasta 600 s. La evidencia de posesión no otorga consentimiento. authority_attestation valida y atestigua el registro; C5 autentica su estado vigente.

Permisos siguen usando el estado WD: comprobar receipt, permission_id, app/epoch, pairwise ID, propósito/clase y evento de emisión. Para cada permiso exigir además la app actual, su authority_epoch, las claves y MSA actuales. No hay una hoja global por dirección de email ni búsqueda pública de direcciones.

C6 — StateWitness (prueba, no firma ni trust root)

Objeto cerrado: proposal_version, object_type: "authority_state_witness", issuer_id, log_id, checkpoint_commitment, locator, present, value, siblings. present booleano; value es C5 sólo si true, null si false; siblings contiene exactamente 256 hashes de 32 octetos, orden hoja→raíz. Pruebas comprimidas/multiproof quedan para otra revisión; no mezclar formatos.

K = H(U("XCIM-AS-01-STATE-KEY\0") || J({issuer_id, log_id, locator}))
L(value) = H(U("XCIM-AS-01-STATE-LEAF\0") || K ||
             H(U("XCIM-AS-01-STATE-VALUE\0") || J(value)))
E[0] = H(U("XCIM-AS-01-STATE-EMPTY\0"))
N(l,r) = H(U("XCIM-AS-01-STATE-NODE\0") || l || r)
E[n+1] = N(E[n], E[n])

Árbol binario sparse de profundidad 256; camino raíz→hoja por bits de K MSB-first, cero a izquierda. Al reconstruir hoja→raíz usar primero el bit menos significativo (índice 255 en el camino) y consumir cada sibling una vez. Ausencia parte de E[0], no de una hoja «unknown»; raíz vacía E[256]. No duplicar el hash STATE-VALUE: es la misma fórmula que commit de §3, decodificada a 32 octetos. Verificar checkpoint/raíz, locator, status y material.

Ausencia válida significa que el estado requerido no está registrado en ese corte. No significa activo, ni necesariamente revocado. Falta de prueba no significa ausencia probada. Revocados conservan tombstones; un activo no puede reaparecer por borrado. La ausencia de la MSA actual nunca permite usar otra por coincidencia de clave. Las pruebas de permiso WD usan su propio algoritmo.

C7 — EvidenceSet y recuperación

Wrapper cerrado: proposal_version, object_type: "authority_evidence_set", profile_id, manifest, control_head, checkpoint, anchor_evidence, permission_evidence, authority_evidence, history_evidence. manifest es JWS/quórum C2; C3/C4 JWS. Cada entrada de autoridad es {witness, material, event, event_inclusion}. Todo objeto debe pertenecer al mismo corte C4 o a la historia autenticada que lo precede; objetos válidos de cortes distintos no se pueden combinar. El wrapper no está firmado y no crea frescura.

permission_evidence transporta componentes WD de receipt/evento/pruebas/batch; su autenticación externa viene del nuevo perfil AS que compromete el batch exacto. No se etiqueta ese wrapper como proof WD/Amoy 0.1. Su schema final y la matriz de compatibilidad son dependencias de G06/G07. anchor_evidence e history_evidence se seleccionan estrictamente por perfil, sin JSON arbitrario tratado como válido. history_evidence debe llevar continuidad de C2/C3/C4, consistencia de ambos logs y pruebas de transición necesarias para los floors que el receiver ya conoce. No seguir enlaces desde headers a orígenes libres.

Transporte propuesto en orígenes aceptados: GET /as-01/manifest, GET /as-01/head, GET /as-01/objects/{type}/{commitment} y POST /as-01/evidence con {checkpoint_commitment, locators}. Son rutas candidatas de un issuer/mirror, no endpoints implementados en xcim.org. El cliente selecciona previamente issuer/log y endpoints; HTTPS protege transporte, las firmas/pruebas autentican contenido. Soporte de POST y acceso deben declararse; no hay búsqueda de email. Consultas por locators opacos siguen pudiendo correlacionar permisos; preferir caché compartida y prueba adjunta.

Límites iniciales para ensayo: HTTPS sólo puerto 443, sin redirects, userinfo, fragmentos ni direcciones privadas/loopback/link-local/multicast; comprobar resoluciones y destino de conexión contra DNS rebinding. Nada de URL desde kid, JWK, receipt, Reference o Proof. Hasta 8 conexiones, 2 s por operación, 5 s totales, 1 MiB descomprimido por EvidenceSet y profundidad JSON 32. No hay fallback a un endpoint comercial ni dependencia de API privada.

Una prueba sparse sin comprimir puede requerir más de 8 KiB por hoja antes de base64/JSON. Evidencia de varias autoridades puede exceder Proof (49152 octetos raw) de P1. No subir ese límite silenciosamente: resolver por transporte acotado o diseñar multiproofs y medirlas en G16. Reference y sus compromisos P1 permanecen iguales. El checker actual sigue rechazando Proof con PROOF_VALIDATOR_PENDING; esta propuesta no cambia ese comportamiento.

C8 — LifecycleEvent (cambio autorizado e historial)

Payload cerrado: campos comunes, sequence_number, locator, state_epoch, previous_event_commitment (null sólo al alta), previous_state_commitment (null sólo al alta), new_state_core, effective_at, reason, authorization_evidence_commitment. new_state_core es C5 sin latest_event_commitment; éste se deriva del compromiso de C8 para construir la hoja. Así no se introduce un ciclo evento↔estado. Razones candidatas registration, rotation, recipient_revocation, owner_revocation, compromise, expiry, suspension, erasure.

El evento lo atestigua authority_attestation; se conserva la solicitud y evidencia firmada del actor autorizado de §6 bajo su compromiso, sin publicarla si revela PII. El receiver autentica evento/inclusión/hoja y confía en esa atestación de validación; el monitor puede exigir evidencias auditables con acceso autorizado. Una prueba de inclusión no demuestra que el actor tenía derecho al cambio. Grants/revocaciones del permiso siguen su lifecycle WD.

Locator/epochs/tiempos de C8 y su new_state_core deben coincidir; la hoja reproduce exactamente ese core más el compromiso C8.

4. Grafo de validación sin autoautorización

Política local C1 --quórum raíz--> Manifest C2
  |                                | roles separados
  |                           Head C3 + Checkpoint C4
  |                                   | commits
  +--genesis/anchor policy------------>| permiso WD + autoridad AS
                                      |
                           estados/pruebas C5/C6 + historia C8
                                      |
                 app actual -> control -> MSA + clave MP + dominios
                                      |
                    receipt + RBA + MSA + MP + DKIM de P1

La aceptación completa requiere todas las aristas. RBA/receipt se validan con sus roles C2 más su estado C5; la clave de app/control y la MP con su estado específico. C3/C4 se autorizan directamente desde C2, no mediante hojas firmadas por sí mismas. La clave batch legacy se configura explícitamente en C1; su futura migración a manifiesto nuevo requiere G07, no reutilizar el rol de checkpoint. Su descriptor local incluye vigencia/thumbprint y su estado key C5 puede retirar, pero nunca ampliar, esa autoridad provisionada. Una clave retirada puede servir a auditoría histórica sólo bajo una política histórica; no aporta autoridad actual para PASS P1.

5. Historia, cortes, rollback y equivocación

Historia AS: árbol acumulativo, sequence_number desde uno, índice cero-based sequence_number - 1. Payload C8 completo como hoja. Forma recursiva/split en la mayor potencia de dos estrictamente menor, sin duplicar hojas impares:

MTH([]) = H(U("XCIM-AS-01-EVENT-EMPTY\0"))
leaf(e) = H(U("XCIM-AS-01-EVENT-LEAF\0") || J(e))
node(l,r) = H(U("XCIM-AS-01-EVENT-NODE\0") || l || r)

Inclusion y consistency usan orden de RFC 6962 con tags AS. No son bytes CT; RFC 9162 es comparación de transparencia, no sustitución de fórmulas WD/AS. El checkpoint compromete raíz/tamaño AS y batch WD del mismo corte. Verificar consistencia de ambos árboles contra el origen/floor previamente aceptado, rechazando siblings extra, tamaño menor, secuencia duplicada con otro hash o predecesor inválido. Un log consistente no demuestra que la proyección sparse sea correcta: publicar eventos permite reconstrucción/auditoría por monitores.

Guardar durablemente por issuer/log policy_epoch, C2 epoch/hash, C3 sequence/hash, C4 sequence/hash, tamaños/raíces de ambos logs y máximo state_epoch/tombstones de cada locator observado. Ordenar primero por las cadenas autenticadas, no por timestamps de sender. Persistir floors antes de reutilizar positivamente la evidencia; un fallo del store retira la señal. Perder el store requiere resincronización contra un floor externo aceptado, no TOFU desde el mensaje.

El productor mantiene chains completas recuperables. Un receiver puede saltar varias publicaciones de red, pero debe validar los enlaces/pruebas omitidos o un checkpoint de recuperación aceptado fuera de banda. Una cabeza más nueva observada invalida la anterior para nuevas evaluaciones; el timestamp por sí solo no establece cuál es más nueva. Mismo número y distinto compromiso es evidencia de conflicto: poner en cuarentena ese issuer/log; no elegir el primer mirror. La restauración requiere resolución autenticada bajo C1, sin borrar la evidencia de conflicto.

Ante bifurcación/reorg, no bajar el floor para resucitar permiso. Detener señal positiva hasta establecer una continuación anclada y resolución aceptada. Dos RPC pueden coincidir y estar equivocados; se debe declarar si la finalidad se verifica con cliente de consenso/light client o corroboración RPC acotada.

6. Máquina de estados y revocaciones

Estados AS: active, suspended, revoked, expired, erased. La ausencia no es estado. Alta válida crea epoch 1; cada transición aumenta state_epoch en uno y enlaza el evento/estado anteriores. effective_at no puede moverse al pasado para ampliar autoridad. Una revocación por compromiso puede declarar una fecha de compromiso anterior en evidencia de incidente, pero no reescribe effective_at ni hace verificable una hora de firma no atestiguada.

Recurso Quién puede solicitar / atestiguar cambio Efecto que debe comprobar el receiver
Permiso Destinatario autenticado para revocar; issuer valida/atestigua. App no concede ni reactiva consentimiento. Revocado terminal para ese permission ID; nuevo consentimiento explícito requiere nuevo receipt/permiso, sin borrar historia.
MSA App control actual, o issuer por compromiso/suspensión de autoridad. MP no puede autorizarse a sí misma. Revocada terminal para authorization ID. Nueva MSA requiere nuevo ID y posesión; mismo kid no la reactiva.
Clave MP/control Control autorizado según transición y atestación issuer; compromiso de control exige recuperación de app verificada. revoked terminal por kid/thumbprint; no reutilizar kid. Bloquear firmas actuales aunque MP declare iat anterior.
App Clave de control y atestación de continuidad del issuer; recuperación exige revalidación. Cambio de control eleva authority_epoch y app_epoch según regla conservadora WD; consentimientos de otro app epoch no se heredan.
Dominio Control de app más challenge observado; issuer puede suspender por fallo/transferencia. Elevar domain_epoch al cambio de owner; requerir nuevos bindings. Vigencia pasada no prueba control presente.
Claves C3/C4 y raíz Manifiesto/raíz C2 o recuperación C1; no hoja de esas mismas claves. Retirar confianza al observar el cambio; cota de ocultamiento distinta (§7).

active → suspended/revoked/expired/erased; suspended → active sólo para app/dominio y con evidencia nueva/epoch superior. Para una MSA suspendida, reemitir otra con ID nuevo para evitar reanimación accidental. revoked, expired y erased no vuelven a active. Tombstones sobreviven a la eliminación de material privado; erasión no borra el hecho público ni revierte una negativa.

La elección inicial conservadora ante cambio de control puede exigir renovar consentimientos aunque el propietario siga siendo el mismo: es un coste real, no una obligación textual de WD de incrementar epoch en toda rotación. La alternativa es continuidad de control con firmas de ambas claves, posesión, atestación de mismo owner y authority_epoch nuevo conservando app_epoch. Requiere fijar cómo se conserva el binding app_key_id del receipt histórico; A6 debe aceptar el coste conservador o definir esa continuidad antes de M.

Rotación MP ordinaria: crear clave/ID MSA nuevos, publicar activación y probar ambas; overlap candidato máximo 3600 s si no hubo compromiso, acotado por todas las vigencias. Retirar vieja de forma terminal. Al comprometer una clave, no hay overlap ni aceptación de firma backdated: P1 exige autoridad actual y iat no es un sello temporal independiente. Conservar auditoría histórica sin confundirla con permiso para nueva entrega. Rotación de control sigue el comportamiento conservador WD; una alternativa que preserve grants tras rotación de control necesita decisión/versionado explícitos.

La solicitud de revocación no se da por «publicada» al escribir en una cola. El operador distingue received, authenticated, committed, anchored, available. Los ACK internos nunca son proofs ni resultados de protocolo. Un timeout del anchor no permite declarar vigente un checkpoint nuevo.

7. Frescura, reloj y propagación

Parámetros candidatos para ensayo, sin mediciones ni SLA productivo:

Parámetro Propuesta inicial Límite y criterio para ratificar
Incertidumbre del reloj u Hasta 60 s Ensayo con offset/rollback/NTP perdido. Si no se puede acotar, no hay positivo.
Edad de C2 / autoridad de C3/C4 Hasta 86400 s Medir firma por quórum, disponibilidad y recuperación. No venderla como revocación de cinco minutos.
Estado de permiso/autoridad C3/C4 Hasta 300 s desde el corte Anclaje final y publicación deben caber dentro; si no caben, ese perfil no es viable con esa ventana.
Cadencia de snapshot Objetivo 60 s Probar vacío y con carga, retrasos y revocaciones concurrentes. No renueva un snapshot viejo.
Propagación tras solicitud autenticada Objetivo p99 ≤ 120 s hasta evidence disponible/anclada Medir por separado cola, corte, anchor/finality y mirrors. No es cota garantizada ni reemplaza expiración.
DNS domain recheck Hasta 86400 s Revisar riesgo de transferencia; fallos no extienden observación previa.
MSA/RBA/MP Mantener límites P1-01 Hasta 604800 s MSA y 86400 s RBA/MP; no sustituyen estado de 300 s.

Sean t reloj local y u cota de incertidumbre. Para estado que afirma validez desde s, exigir s <= t-u; para toda expiración exclusiva e, exigir t+u < e. Un snapshot todavía «del futuro» puede reevaluarse al avanzar reloj, sin consumir nonce. Este criterio conservador usa todo el intervalo de incertidumbre, no añade grace a la expiración. Para las firmas P1 existentes con tolerancia iat <= now+60, conservar su gate de emisión, pero exigir además que la autoridad de cada firmante cubra el iat declarado; esa tolerancia no amplía expiración ni frescura de C3/C4.

state_deadline = min(C3.next_update, C4.next_update,
                     C4.this_update + min(300, local_max_state_age))
manifest_deadline = min(C2.exp, C2.iat + min(86400, local_max_manifest_age))
effective_deadline = min(state_deadline, manifest_deadline,
    C1.valid_until, receipt.exp, RBA.exp, MSA.exp, MP.exp,
    each_required_key.valid_until, each_required_state.valid_until,
    each_required_domain.recheck_by, selected_anchor_policy_deadline)

Convertir tiempos WD RFC3339 a instante exacto sin truncar fracciones ni reescribir bytes firmados. Si la política de anchor no define deadline temporal, usa infinito sólo para ese término: igualmente debe estar verificada y la finalidad no renueva el tiempo del corte. C3/C4/C2 deben cumplir s < e y sus edades máximas al evaluarse. Intersectar también las vigencias de claves al emitir y ahora; una clave puede estar autorizada a emitir hasta antes de que expire el objeto, pero no a sostener señal positiva tras su propio retiro.

Ejemplo: corte 12:00, vence 12:05, u=30 s; a 12:04:29 puede ser utilizable si todas las demás pruebas pasan; a 12:04:30 deja de ser positivo. Descargarlo 12:04:59 no lo renueva. Recibirlo a 12:00:10 con esa incertidumbre es demasiado temprano para afirmar que el corte ya ocurrió; se puede esperar/reevaluar.

Con autoridad honesta, reloj acotado y cortes atómicos, una revocación ocurrida inmediatamente después de un corte puede ocultarse hasta el deadline de ese corte, como máximo la ventana de 300 s propuesta. Detener publicaciones hace caducar la señal; no prolonga permiso. Si se compromete C3/C4 o su autoridad, esa cota deja de aplicar: el límite de C2 puede alcanzar 24 horas y un issuer o quórum raíz deshonesto puede emitir estado falso. Recuperación/denies locales pueden actuar antes, pero no se promete entrega instantánea de esa información.

Revalidar la intersección inmediatamente antes de aceptación SMTP/commit del nonce y al reutilizar un resultado exportado. Trabajo asíncrono, 304, ETag, Age, hora de descarga o manifest de release no extienden ningún término. Si se usan cachés entre MX, compartir floors, tombstones y política de invalidez; el ledger de replay sigue siendo otra transacción pendiente en G16.

8. Ausencia, fallos y resultado compuesto

Proponer internamente {validation, permission, authority, freshness, publication, replay, effective_deadline, diagnostics}. Son dimensiones locales de diagnóstico, no nuevos códigos registrados. Conservar todos los fallos válidamente comprobados; no transformar un error de transporte en revocación.

Orden candidato determinista para retirar la señal: parseo/límites/perfil → trust/firmas/compromisos → conflicto/rollback/prueba inválida → negativa autenticada de permiso/autoridad → evidencia vencida → dependencia ausente o inaccesible → todas las condiciones satisfechas. Cada etapa sólo produce hechos después de autenticar sus prerrequisitos; un estado «revoked» en JSON no autenticado no tiene precedencia. Si hay varios fallos de una etapa, ordenar por rol/locator canónico y conservar la lista completa.

Una revocación de permiso autenticada puede retirar permiso sin anchor, como permite el core, pero el resultado debe indicar que no es verificación de publicación completa. No permitir que un anchor caído tape esa negativa; tampoco emitir revocado si la prueba está ligada a otro contexto. Ausencia autenticada de MSA/clave/app retira autoridad y no se etiqueta XCIM_REVOKED del permiso.

Para el protocolo, conservar el registro vigente: XCIM_REVOKED sólo cuando corresponda al permiso, XCIM_STATUS_STALE para evidencia vencida, XCIM_STATUS_INDETERMINATE para insuficiencia, XCIM_ANCHOR_UNAVAILABLE cuando falte el anchor requerido y XCIM_LOG_PROOF_FAIL para una prueba inválida autenticablemente atribuible al contexto. D09/D12 deben ratificar el mapeo completo de conflictos/autoridad y multifallos antes de afirmar conformidad. El código P1 de fixture sigue sin emitir PASS.

9. Alternativas y condiciones para reconsiderarlas

Alternativa Qué gana Qué no resuelve / por qué no es el primer camino
Consulta firmada online por mensaje, estilo status responder Revocación de baja latencia y payload pequeño Disponibilidad, correlación y coste por mensaje; debe autenticar autoridad/frescura, no basta HTTP. Puede ser optimización opt-in futura.
Listas de revocación completas/deltas Caché/broadcast fáciles; menos consultas por locator Tamaño, composición de deltas y prueba de lista completa/actual; no basta «no aparece». Comparar con sparse para cohortes pequeñas.
Tokens muy cortos MSA/MP Menos estado separado Retiro sólo al vencer; seguiría faltando revocación de app/control/dominio y abuso de clave comprometida.
Un único firmante de checkpoint y «su estado» en la misma raíz Menos roles y firmas Autoatestación tras compromiso; no elegirlo como lifecycle suficiente. C3 agrega un dominio de compromiso, sin eliminar confianza en issuer.
Log y testigos independientes sin blockchain Posible menor latencia y coste Requiere quórum, operadores independientes, política de witness/gossip y análisis de split views; sería perfil nuevo sin cadena revisado, no omisión de core.
Sólo firma de issuer, sin publicación independiente Desarrollo inicial simple No cumple la publicación exigida; se podría ensayar como fixture sin señal pública, nunca llamarlo AS anchored.
Anclar sólo raíz de permisos WD y adjuntar autoridad sin compromiso Reutiliza el anchor de hoy Permite mezclar/manipular autoridad de otro corte. AS compromete ambas en C4; requiere adaptador nuevo explícito.

La separación thisUpdate/nextUpdate de OCSP inspira el vocabulario de estado, sin adoptar su ASN.1 ni su modelo de trust. La raíz como input local y las dificultades de recuperación se comparan con PKIX/DNSSEC. La propuesta AS es diseño XCIM, no un perfil ya validado por esos RFCs.

10. Criterios de cierre por brecha

Brecha / hito Entregable necesario Evidencia que permite cerrarlo
G04-M D04 aceptada; schemas cerrados C1/C2/C5/C8 y materiales; matriz exacta de roles/alg/typ; contratos DNS, posesión, rotación/recuperación y transporte Fixtures de cada lifecycle y límites de confianza; otro implementador reproduce bootstrap y cambio/compromiso de cada rol sin API privada. Sin resolver DNS/registry opcional no se afirma cobertura de esos caminos.
G05-M D05 aceptada; schemas C3/C4/C6/C7, fórmulas y algoritmo completo de vigencias/fallos, floors durables y ausencia Vectores con reloj/futuros/expiración exacta, cortes mezclados, revoked/absent/missing/stale, no-renovación por wrapper, conflicto y reinicio; mismos bytes/resultados en dos implementaciones.
G05-O Operación continuamente renovada y objetivo de revocación declarado Ensayo de 7 días propuesto con carga y clocks declarados; revocaciones bajo concurrencia y pérdida de publicación, p99/máximos/fallos reportados; ningún positivo tras deadline/negativa conocida. Recuperación sin borrar floors.
G06-M D06 aceptada, perfil/anchor adapter exactos, genesis/ABI/política de finality, relación WD→C4 sin ciclos y límites Verificador de evidencia completo que rechace wrong-chain, evento/firmante/hash/sequence falsos, forks/reorg/variantes, raíces inventadas y split view. Pruebas en otro verifier sin RPC privado.
G06-O (junto G14–G16) Monitor y ensayo de disponibilidad/latencia/DoS/finalidad Revisión externa de la construcción y ensayo con fallos inducidos, operadores declarados y medición de tamaño/CPU/red; sin llamar a Amoy red productiva.

Duración/carga/p99 son propuesta de ensayo, no garantías medidas. Una autoprueba puede completar evidencia interna, pero no satisface por sí sola «otro implementador», revisión externa ni operación entre equipos independientes. El primer envío S puede declarar estas brechas abiertas; no hay envío implícito.

11. Catálogo de pruebas por escribir, no resultados

Casos planificados AS-T01–AS-T24; no están sumados a los 135 casos P1 existentes:

ID Caso Criterio observable esperado
AS-T01 Bootstrap con pins aceptados y todo el grafo válido Evidencia fixture completa, sin autoridad de producción por usar claves sintéticas.
AS-T02 Manifest autoafirmado / registry no aceptado / otro issuer No crear trust ni seguir ruta de fallback.
AS-T03 Cambiar rol, kid o JWK conservando firma válida de otro rol Retirar autoridad, aun con firma matemáticamente correcta.
AS-T04 MSA material sustituido, mismo authorization ID Compromiso o scope no coincide; negar.
AS-T05 MP firmada por clave revocada con iat backdated No aceptar firma para nueva entrega.
AS-T06 Rotación MP con overlap y posterior retiro Sólo intervalos/scope vigentes; no reanimar la clave vieja.
AS-T07 Cambio de control/app epoch / transferencia de dominio No heredar grants de otro epoch ni bindings previos.
AS-T08 Reusar challenge / observar DNS aportado por sender Fallar registro/observación; no autoprobar control.
AS-T09 MSA, clave, app o dominio ausentes con proof válida Ausencia sin autoridad; distinguir de proof faltante.
AS-T10 Reordenar sibling, bit order, locator, issuer o root sparse Fallar prueba; no aceptar raíz suministrada por ella misma.
AS-T11 Mezclar permiso de un corte y autoridad de otro Fallar C4/roots/compromisos.
AS-T12 Revocación concurrente entre snapshot y firma Incluir consistentemente o abortar; ningún corte mixto publicado.
AS-T13 Wrapper nuevo, HTTP304 o re-download tras caducidad Deadline original; nunca renovar.
AS-T14 Bordes t-u == this_update, t+u == exp y reloj sin cota Igualdad de inicio admitida; igualdad de fin no positiva; reloj no acotado no positivo.
AS-T15 Checkpoint/key expirados y receipt válido por años Intersección retira señal; no priorizar sólo receipt.
AS-T16 Checkpoint sin eventos nuevo / reloj cambiado en uno viejo Nuevo corte/anclaje válido o rechazo; no refrescar batch viejo.
AS-T17 Checkpoint comprometido sin segunda firma C3 No fabricar evidencia actual sólo con esa clave.
AS-T18 Control head viejo retenido, nuevo ya observado Floor impide rollback aun antes de expiración.
AS-T19 Compromiso de ambos roles online / raíz recuperada Mostrar límite de confianza/24h; recuperación externa retira positivos, sin prometer solución por árbol.
AS-T20 Mismo sequence/epoch con distintos hashes, mirrors divididos Cuarentena/conflicto, no elegir primero.
AS-T21 Reorg, wrong chain, transacción exitosa sin evento exacto No publicar positivo; no retroceder floor.
AS-T22 Store de floors perdido/no disponible y reinicio Resync aceptada o sin positivo; no TOFU desde email.
AS-T23 Redirect/SSRF/DNS rebinding/decompression bomb / Proof enorme Cortar fetch/parsing con presupuestos antes de uso.
AS-T24 Múltiples MX, nonce concurrente y vencimiento antes de SMTP250 Reevaluar y aceptar atómicamente; G16 sigue pendiente hasta ese ensayo.

12. Dirección adoptada y concreciones pendientes

ID de trabajo Elección por cerrar Recomendación / puerta siguiente
A1 / D04 Bootstrap mínimo y registry Pins locales primero; registry sólo al definir su estado/recuperación. Aceptar roles C1/C2 y quórum explícito antes de schemas.
A2 / D04 Revocación de signers de publicación C3/C4 separados, revocados por C2/C1. Ratificar riesgo de ocultamiento de C2 ≤24h o diseñar otro canal de autoridad más corto.
A3 / D05 Dos proyecciones del mismo corte Mantener permiso WD + autoridad AS, checkpoint compuesto. Fijar transacción/snapshot y migración de batch legacy antes de verifier.
A4 / D06 Anchor inicial AS Nuevo perfil anclado y adaptador de ensayo Amoy explícito; sin reinterpretar evento viejo. Faltan ABI/contrato/red/finalidad exactos, sin despliegue autorizado por publicar esta propuesta.
A5 / D05/G16 300s/60s/24h y reloj conservador Usarlos como hipótesis de ensayo, medir viabilidad; no ampliar ventanas a escondidas si finality no cabe.
A6 / D04/G07/G09 DNS, recuperación, tipos/algoritmos y fallos Resolver payload de observación, roles legacy y matriz de fallos antes de cerrar M; fijar qué parte puede implementar el primer receiver.

Dirección A1–A6 adoptada; secuencia técnica: schemas AS y evidencia sintética cerrados → dos verificadores de fórmulas/temporización → adaptador/anclaje seleccionado → snapshots/rotación/revocación continuos → interop y revisión externas. En paralelo se puede revisar el diseño con expertos autorizados; no se enviaron mensajes ni se contactó a IETF por publicar este material.

13. Referencias y comparación con estándares

Referencias externas consultadas el 2026-10-19. Las construcciones AS adicionales son propuesta de proyecto y requieren revisión propia, no aprobación de esos RFCs.

14. Concreción propuesta del adaptador AN01-P01

AN01-P01 propone el ABI, genesis acíclico, red y finalidad del adaptador exigido por A4. Sus N1–N6 fueron adoptadas: contrato inmutable por issuer/log, Amoy opt-in y nodo de consenso del receiver. Incluye alternativas, gates y 20 casos EVM/red pendientes; AN01-F01 implementa contrato/schemas/EVM local, con cobertura parcial del plan y finalidad viva pendiente. No cambia la adopción A1–A6, C7 F01 sigue null y G04–G06 conservan sus dependencias M/O.