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.
| Decision | Recommendation | Closure gate |
|---|---|---|
| D04: authority | Explicit local pins first, root/recovery quorums, scoped roles and lifecycle. | Exact DNS/possession/recovery contracts, schemas and independent implementation. |
| D05: current state | Atomic cut, durable floors, proven absence, conservative expiry. | Boundary/concurrency/rollback vectors and measured continuous renewal. |
| D06: publication | New 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:
- ¿Acepto a este issuer y este log bajo mi política, para este perfil?
- ¿Qué clave podía firmar cada objeto al emitirlo y conserva autoridad actual?
- ¿Siguen activos la app/epoch, los dominios, la MSA y su clave MP?
- ¿Sigue activo exactamente este permiso del destinatario/app/propósito?
- ¿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
- Baseline WD-02-E1 core, §§4,7,10–16: confianza local, autoridad actual, árboles, anclaje y estado fresco.
- P1-01: bindings aceptados de destinatario/MSA/MP y límites de fixture.
- RFC 5280 §6.1.1: trust anchor como input a validación; AS no adopta una PKI X.509 propia.
- RFC 6960 §2.4: distingue observación de estado, próxima actualización y firma; AS define su propio deadline conservador.
- RFC 5011 §§2,8: actualización/compromiso de anclas y necesidad de recuperación externa en ciertos casos. No se reutiliza su algoritmo DNSSEC.
- RFC 9162 §§2.1,11.3: transparencia y límites ante vistas inconsistentes; no demuestra ausencia de equivocación por sí sola.
- RFC 6962 §2: orden/forma de los proofs ya usados por el baseline. RFC 9162 lo reemplaza para CT; conservar fórmulas históricas XCIM no es afirmar uso de CT moderno.
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.