# SSN guard

Stops an AI agent working in this folder from writing a full Social Security
number into a file or a command.

## What it blocks

A full number: three digits, two digits, then four digits, with a dash, a
space, or nothing between the groups (for example the forms `NNN-NN-NNNN`,
`NNN NN NNNN`, and `NNNNNNNNN`). Mixed separators such as `NNN-NN NNNN` are
also blocked.

Message on a block:

    Blocked: a full Social Security number. Use only the last four digits.

## What it allows

- The last four digits on their own.
- Phone numbers such as 555-0142.
- Digit runs longer than nine digits, and nine digits that touch other digits,
  because the pattern requires a non-digit (or the start or end of the text)
  on both sides.
- Groups joined by other separators, such as dots or slashes.

Pattern used in both places:

    (^|[^0-9])[0-9]{3}[- ]?[0-9]{2}[- ]?[0-9]{4}([^0-9]|$)

## Which file each tool reads

| Tool        | File it reads                  | What happens                                                                                     |
|-------------|--------------------------------|--------------------------------------------------------------------------------------------------|
| Claude Code | `.claude/settings.json`        | PreToolUse hook, matcher `Write\|Edit\|MultiEdit\|Bash`, runs `bash "$CLAUDE_PROJECT_DIR/guard/ssn-check.sh"`. |
| Claude Code | `guard/ssn-check.sh`           | Gets the tool call as JSON on standard input. Exit 2 blocks the call and shows the message.       |
| OMP         | `.omp/hooks/pre/ssn-guard.ts`  | `pi.on("tool_call", ...)` returns `{ block: true, reason }` when `JSON.stringify(event.input)` matches. |

Before matching, `ssn-check.sh` uses `sed` to empty the values of
`session_id`, `transcript_path`, `cwd`, and `tool_use_id`, since ids and paths
can hold long digit runs by chance. Everything else, including the tool input,
is checked. `jq` is not needed.

Known limit: the `sed` step empties any key with one of those four names,
wherever it appears in the JSON, so a value stored under a key named `cwd`
inside the tool input is not checked.

## Tests

Each line was piped into `bash guard/ssn-check.sh` one at a time. The test
numbers use only area 987, group 65, and serials 4320 through 4329, a reserved
range that is never issued. The commands hold the three groups in separate
shell variables and join them with `printf`, so this README and the commands
themselves never hold a full number. Writing the groups as plain arguments
(three groups separated by spaces) would itself be a full number in the spaced
form and would be blocked.

| # | Input                    | Command                                                                       | Exit status | Result  |
|---|--------------------------|-------------------------------------------------------------------------------|-------------|---------|
| 1 | Number with dashes       | `a=987 b=65 c=4321; printf '%s-%s-%s\n' "$a" "$b" "$c" \| bash guard/ssn-check.sh` | 2 | Blocked |
| 2 | Number with spaces       | `a=987 b=65 c=4322; printf '%s %s %s\n' "$a" "$b" "$c" \| bash guard/ssn-check.sh` | 2 | Blocked |
| 3 | Nine digits run together | `a=987 b=65 c=4323; printf '%s%s%s\n' "$a" "$b" "$c" \| bash guard/ssn-check.sh`   | 2 | Blocked |
| 4 | Last four digits only    | `printf '%s\n' 4324 \| bash guard/ssn-check.sh`                                   | 0 | Allowed |
| 5 | Phone number 555-0142    | `printf '%s\n' 555-0142 \| bash guard/ssn-check.sh`                               | 0 | Allowed |

Tests 1 to 3 printed the block message on standard error. Tests 4 and 5
printed nothing.
