shell-hooks/README.md
33 lines · 1545 bytes
1# shell-hooks
2
3Shell side of the terminal collector (spec §1.4). **Live as of v0.2.** These
4snippets belong in the dotfiles repo and are sourced by the user's `.zshrc`;
5they are kept here so the privacy contract lives next to the code it constrains
6(and so the differential secret-typing test can drive the real file).
7
8## The one rule
9
10**Aggregate-only.** The hooks emit counts, durations, and exit codes. They
11never read, store, or transmit the content of a command or a keystroke.
12
13- No input tap, no `CGEventTap`, no PTY sniffing.
14- Never reference the `zle` line buffer or capture argv.
15- What leaves the shell is a number, flushed on `precmd`.
16
17v0.2 ships the `zle` keypress counter: a widget wraps `self-insert`, does
18`(( _SIGNALD_KEYS++ ))`, then calls the built-in insert. It receives the key in
19the editor and discards it — the character is never assigned to a variable that
20outlives the widget and never leaves the shell. On each `precmd` the hook
21appends one count record — `<epoch_ms> <keys> <session_seconds>`, numbers only
22— to `$SIGNALD_SPOOL`, which `signald` reads.
23
24This contract is enforced by the forbidden-symbol scan **and** the differential
25secret-typing test in `crates/signal-schema/tests/privacy_invariant.rs` (plus
26the full-pipeline gate in `crates/signald/tests/`), which drive *this file* with
27a planted secret and fail the build if it — in any encoding — reaches the spool,
28the wire, or SQLite.
29
30## Files
31
32- `signald-hooks.zsh` — the `zle` keystroke counter + `precmd` count flush
33 (aggregate-only).