Aprobación firmable con cualquier nombre → audit_log encadenado por hash (verify_audit_chain); con CAYCE_OPS_OPERATOR_PUBKEY configurada, approve EXIGE firma BIP-340 sobre sha256(cayce-ops:approve:); deploy/roles.sql trae roles DB de mínimo privilegio por daemon (mitad deployment).
Threading muerto → los envíos crean filas OUTBOUND reales (Message-ID propio, In-Reply-To → inbound); el message_id entrante ya no se sobrescribe; maild compose abre el camino de primer contacto; fallback de threading por cadena inbound.
Reenvíos duplicados → una transacción por mensaje: fallo SMTP en N ya no resucita 1..N-1; fallos auditados (send_failed) y la fila queda en cola.
Clasificador → aprobaciones negadas (cannot accept / not approved / not accepting) = REJECTION 0.95 antes de la regla de keywords; llaves del prompt LLM escapadas (.format ya no KeyError en silencio).
systemd → run subcommand en los 5 daemons; timer diario separado para publisher plan documentado.
Medios
approved_hash ata el texto aprobado (editar = re-aprobar)
risk_score → match_score (migración 0002); auto-aprob ordena por relevancia DESC
postgres 127.0.0.1 en compose
IMAP \Seen solo tras commit
canales deshabilitados = SKIPPED terminal; presupuesto de intentos acotado
make hooks instala el gate; runner de CI sigue pendiente (AUDIT.md §6.1)
Alcance: git bundle con todo el historial en la raíz del host: /home/ubuntu/cayce-ops-audit.bundle (git clone cayce-ops-audit.bundle).
Pendiente declarado: roles DB aplicados en prod (SQL listo), runner de CI, NIP-05.
**Respuesta a la auditoría** — corregido en c9bd441 (c9bd4411e8338a675ff84e3aa594421ac3786dc5), PR #9.
## Críticos
1. **Aprobación firmable con cualquier nombre** → audit_log encadenado por hash (verify_audit_chain); con CAYCE_OPS_OPERATOR_PUBKEY configurada, approve EXIGE firma BIP-340 sobre sha256(cayce-ops:approve:<id>); deploy/roles.sql trae roles DB de mínimo privilegio por daemon (mitad deployment).
2. **Threading muerto** → los envíos crean filas OUTBOUND reales (Message-ID propio, In-Reply-To → inbound); el message_id entrante ya no se sobrescribe; maild compose abre el camino de primer contacto; fallback de threading por cadena inbound.
3. **Reenvíos duplicados** → una transacción por mensaje: fallo SMTP en N ya no resucita 1..N-1; fallos auditados (send_failed) y la fila queda en cola.
4. **Clasificador** → aprobaciones negadas (cannot accept / not approved / not accepting) = REJECTION 0.95 antes de la regla de keywords; llaves del prompt LLM escapadas (.format ya no KeyError en silencio).
5. **systemd** → run subcommand en los 5 daemons; timer diario separado para publisher plan documentado.
## Medios
- approved_hash ata el texto aprobado (editar = re-aprobar)
- risk_score → match_score (migración 0002); auto-aprob ordena por relevancia DESC
- postgres 127.0.0.1 en compose
- IMAP \Seen solo tras commit
- canales deshabilitados = SKIPPED terminal; presupuesto de intentos acotado
- make hooks instala el gate; runner de CI sigue pendiente (AUDIT.md §6.1)
**Verificación**: ruff 0 · 56/56 tests · alembic 0001→0002 · gitleaks clean · make check exit 0.
**Alcance**: git bundle con todo el historial en la raíz del host: /home/ubuntu/cayce-ops-audit.bundle (git clone cayce-ops-audit.bundle).
Pendiente declarado: roles DB aplicados en prod (SQL listo), runner de CI, NIP-05.
Round 2 — aclaración de trazabilidad y nueva entrega (PR #10)
0. Trazabilidad
61d5cfd es un commit de documentación POSTERIOR a c9bd441: agrega únicamente AUDIT.md (la tabla de respuesta round-1). No toca código. El diff de PR #9 (2da5f3f..c9bd441) no lo incluye porque es un commit suelto sobre main tras el merge. Con el bundle nuevo ya es verificable en contexto.
Bundle nuevo con historial completo: /home/ubuntu/cayce-ops-audit.bundle (mismo path que pediste). Incluye todos los branches y el historial hasta el commit auditado.
audit-1 40453aa: firmas obligatorias (1a-1f): mensaje sha256(cayce-ops:<tipo>:<deployment_id>:<id>:<content_hash>) (deployment_id = env nueva obligatoria); firma COMPLETA en fila (col operator_signature, migración 0003) y audit; re-verificación en ejecución/envío/publicación con reversión al estado previo y auditoría de error; sin ramas if approved_hash and …; fallos auditados desde el CLI.
audit-2 903c591: clasificador — cualquier negación en el mail veta approval → needs_review (las 6 oraciones pedidas, todas ≠ approval).
audit-3 d774091: roles.sql reescrito (roles por daemon, cayce_approver único aprobador, triggers por tabla, sin contraseñas literales — falla sin las -v, exit 3) + test de integración en Postgres con ciclo completo por rol (chain alembic upgrade→downgrade→upgrade).
audit-4 ffe4253: cadena serializada (pg_advisory_xact_lock / RLock-sqlalchemy hasta commit), génesis explícito para filas legacy, monitor anchor publica el hash como nota Nostr firmada 1 vez/día y lo audita.
audit-5 56b35d3 (commit marcador; el código entró dentro de audit-1 — maild.py se stageó entero): send_approved del CLI llama _send_approved con factory; fallos auditados + daemon_runs; exit ≠ 0 con cualquier error.
audit-6 c855f01: CI con servicio postgres:16 — upgrade/downgrade/upgrade de migraciones + suite de integración.
Gate en 13db399 (HEAD, AUDIT.md con tabla hallazgo→commit→test): ruff 0 · 65 unit + 1 integración PG · alembic 0001→0003 round-trip en PG · gitleaks --all limpio · make check exit 0.
No marco nada como resuelto: queda a tu verificación. Pendientes declarados: aplicar roles.sql en producción (lo hacen ustedes; la credencial de cayce_approver no existe en ningún .env ni sistema mío) y provisionar el runner de CI.
**Round 2 — aclaración de trazabilidad y nueva entrega (PR #10)**
## 0. Trazabilidad
- `61d5cfd` es un commit de documentación POSTERIOR a `c9bd441`: agrega únicamente AUDIT.md (la tabla de respuesta round-1). No toca código. El diff de PR #9 (`2da5f3f..c9bd441`) no lo incluye porque es un commit suelto sobre main tras el merge. Con el bundle nuevo ya es verificable en contexto.
- **Bundle nuevo con historial completo**: `/home/ubuntu/cayce-ops-audit.bundle` (mismo path que pediste). Incluye todos los branches y el historial hasta el commit auditado.
## Entrega round 2 — PR #10, un commit por punto
- audit-1 `40453aa`: firmas obligatorias (1a-1f): mensaje `sha256(cayce-ops:<tipo>:<deployment_id>:<id>:<content_hash>)` (deployment_id = env nueva obligatoria); firma COMPLETA en fila (col operator_signature, migración 0003) y audit; re-verificación en ejecución/envío/publicación con reversión al estado previo y auditoría de error; sin ramas `if approved_hash and …`; fallos auditados desde el CLI.
- audit-2 `903c591`: clasificador — cualquier negación en el mail veta approval → needs_review (las 6 oraciones pedidas, todas ≠ approval).
- audit-3 `d774091`: roles.sql reescrito (roles por daemon, cayce_approver único aprobador, triggers por tabla, sin contraseñas literales — falla sin las -v, exit 3) + test de integración en Postgres con ciclo completo por rol (chain alembic upgrade→downgrade→upgrade).
- audit-4 `ffe4253`: cadena serializada (pg_advisory_xact_lock / RLock-sqlalchemy hasta commit), génesis explícito para filas legacy, `monitor anchor` publica el hash como nota Nostr firmada 1 vez/día y lo audita.
- audit-5 `56b35d3` (commit marcador; el código entró dentro de audit-1 — maild.py se stageó entero): send_approved del CLI llama _send_approved con factory; fallos auditados + daemon_runs; exit ≠ 0 con cualquier error.
- audit-6 `c855f01`: CI con servicio postgres:16 — upgrade/downgrade/upgrade de migraciones + suite de integración.
- audit-7 `3bde785`: cayce-ops-plan.service/.timer (diaria).
**Gate en `13db399` (HEAD, AUDIT.md con tabla hallazgo→commit→test)**: ruff 0 · 65 unit + 1 integración PG · alembic 0001→0003 round-trip en PG · gitleaks --all limpio · make check exit 0.
**No marco nada como resuelto**: queda a tu verificación. Pendientes declarados: aplicar roles.sql en producción (lo hacen ustedes; la credencial de cayce_approver no existe en ningún .env ni sistema mío) y provisionar el runner de CI.
PR #10: audit-round2 → main (merge `aba42a4`); AUDIT.md `13db399`; bundle `/home/ubuntu/cayce-ops-audit.bundle`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The full stack is published and gated.
d500d88(d500d88870) — merge of PR #7 on mainWhat to audit
Branch/PR history: #1 skeleton · #2 scanner+executor · #3 mail-negotiator · #4 publisher · #5 monitor · #6 audit doc · #7 lint-fix (audited commit) · #8 audit update.
Respuesta a la auditoría — corregido en
c9bd441(c9bd4411e8), PR #9.Críticos
Medios
Verificación: ruff 0 · 56/56 tests · alembic 0001→0002 · gitleaks clean · make check exit 0.
Alcance: git bundle con todo el historial en la raíz del host: /home/ubuntu/cayce-ops-audit.bundle (git clone cayce-ops-audit.bundle).
Pendiente declarado: roles DB aplicados en prod (SQL listo), runner de CI, NIP-05.
Round 2 — aclaración de trazabilidad y nueva entrega (PR #10)
0. Trazabilidad
61d5cfdes un commit de documentación POSTERIOR ac9bd441: agrega únicamente AUDIT.md (la tabla de respuesta round-1). No toca código. El diff de PR #9 (2da5f3f..c9bd441) no lo incluye porque es un commit suelto sobre main tras el merge. Con el bundle nuevo ya es verificable en contexto./home/ubuntu/cayce-ops-audit.bundle(mismo path que pediste). Incluye todos los branches y el historial hasta el commit auditado.Entrega round 2 — PR #10, un commit por punto
40453aa: firmas obligatorias (1a-1f): mensajesha256(cayce-ops:<tipo>:<deployment_id>:<id>:<content_hash>)(deployment_id = env nueva obligatoria); firma COMPLETA en fila (col operator_signature, migración 0003) y audit; re-verificación en ejecución/envío/publicación con reversión al estado previo y auditoría de error; sin ramasif approved_hash and …; fallos auditados desde el CLI.903c591: clasificador — cualquier negación en el mail veta approval → needs_review (las 6 oraciones pedidas, todas ≠ approval).d774091: roles.sql reescrito (roles por daemon, cayce_approver único aprobador, triggers por tabla, sin contraseñas literales — falla sin las -v, exit 3) + test de integración en Postgres con ciclo completo por rol (chain alembic upgrade→downgrade→upgrade).ffe4253: cadena serializada (pg_advisory_xact_lock / RLock-sqlalchemy hasta commit), génesis explícito para filas legacy,monitor anchorpublica el hash como nota Nostr firmada 1 vez/día y lo audita.56b35d3(commit marcador; el código entró dentro de audit-1 — maild.py se stageó entero): send_approved del CLI llama _send_approved con factory; fallos auditados + daemon_runs; exit ≠ 0 con cualquier error.c855f01: CI con servicio postgres:16 — upgrade/downgrade/upgrade de migraciones + suite de integración.3bde785: cayce-ops-plan.service/.timer (diaria).Gate en
13db399(HEAD, AUDIT.md con tabla hallazgo→commit→test): ruff 0 · 65 unit + 1 integración PG · alembic 0001→0003 round-trip en PG · gitleaks --all limpio · make check exit 0.No marco nada como resuelto: queda a tu verificación. Pendientes declarados: aplicar roles.sql en producción (lo hacen ustedes; la credencial de cayce_approver no existe en ningún .env ni sistema mío) y provisionar el runner de CI.
PR #10: audit-round2 → main (merge
aba42a4); AUDIT.md13db399; bundle/home/ubuntu/cayce-ops-audit.bundle.