Fase 3 — diario de mutaciones (hammer-journal + fanotify + hammer journal)

Nuevo crate hammer-journal y watcher fanotify en hammerd. Cierra el contrato
del SDD 05 §3 ("toda mutación trazable/opaca registrada y consultable") y
liquida la deuda Fase 2 sobre el hook al diario en commit.

hammer-journal:
- MutationEvent (op, path, by, content_hash?, note?), MutationOp
  Create/Replace/Edit/Delete, Source enum tagged HammerHydrate /
  HammerCommit / External (distingue trazable de opaco para `export`).
- Journal: record append-only + sync_data, read_all/tail/follow (offset),
  resilencia a líneas malformadas (kernel-panic mid-write se ignora).
- RFC 3339 UTC sin chrono (Hinnant civil_from_days, válido para todo i64).
- 7 unit tests cubren append/read/tail/follow/malformed/serde/timestamp.

Watcher (hammerd):
- nix::sys::fanotify con FAN_CLASS_NOTIF + FAN_CLOSE_WRITE +
  FAN_EVENT_ON_CHILD sobre /bin /sbin /usr/bin /usr/sbin /lib /usr/lib /etc.
- Resuelve path por readlink(/proc/self/fd/<n>) — sin FAN_REPORT_DFID_NAME
  para Fase 3 v1; el refinamiento Create/Edit con metadata viene después.
- Filtro: hammer_overlay::status(state_root) → ignora paths bajo un overlay
  activo (el ruido del experimento no entra hasta el commit).
- Sin CAP_SYS_ADMIN, fanotify_init falla; hammerd lo reporta y sigue
  durmiendo (preparado para que Fase 5 monte el bus encima).
- 3 unit tests sobre defaults/filtros/uid lookup.

CLI:
- hammer journal [--dir] [--tail N] [--follow] [--format pretty|json].
- hammer commit registra cada archivo promocionado/removido vía
  commit_with_journal; --no-journal opt-out.

Hook overlay::commit:
- commit_with_journal(id, root, journal): para cada copied/removed emite un
  MutationEvent con Source::HammerCommit { overlay }. Test directo del hook
  sin overlayfs (lógica pura) más el e2e existente que ya cubre los mounts.

57 tests workspace, 0 fallos.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Sergio
2026-06-09 14:43:07 +00:00
co-authored by Claude Opus 4.7
parent fe1601e669
commit a87b16dd85
12 changed files with 911 additions and 26 deletions
+3
View File
@@ -4,6 +4,7 @@ members = [
"crates/hammer-core",
"crates/hammer-build",
"crates/hammer-overlay",
"crates/hammer-journal",
"crates/hammer-cli",
"crates/hammerd",
]
@@ -19,6 +20,7 @@ repository = "https://gitea.gioser.net/sergio/hammer"
hammer-core = { path = "crates/hammer-core" }
hammer-build = { path = "crates/hammer-build" }
hammer-overlay = { path = "crates/hammer-overlay" }
hammer-journal = { path = "crates/hammer-journal" }
# shared third-party deps, pinned at the workspace level
anyhow = "1"
@@ -30,6 +32,7 @@ toml = "0.8"
blake3 = "1"
sha2 = "0.10"
hex = "0.4"
nix = { version = "0.30", default-features = false, features = ["fanotify", "fs", "user"] }
tempfile = "3"
clap = { version = "4", features = ["derive"] }
tracing = "0.1"