fp.tablet.pin.reset stores hashed 4-digit codes emailed for self-
service PIN create/reset. Per CLAUDE.md Rule 24 + Rule 13l it follows
the defensive patterns established elsewhere in the shopfloor module:
- PBKDF2-SHA256 hashing (200k iterations, matches ResUsers PIN)
- 72h TTL per D4
- 5 wrong-attempt cap per D5 (invalidates code, used_at set)
- 3 requests/60min rate limit per D6 (raises UserError)
- SQL EXCLUDE constraint enforces one-active-row-per-user per D7
- HMAC-SHA256 reset_token (300s TTL, single-use) for step 3 of
the flow (set_pin via reset_token alternative to old_pin)
Audit event_type extended with 3 new values (pin_reset_requested,
pin_reset_code_verified, pin_set_after_reset). Manager-only ACL on
the new model; sudo when endpoints need access.
10 model-level tests cover generate / replace-active / rate-limit /
verify-correct / verify-wrong / 5-attempt-cap / expired / token sign
roundtrip / tampered-sig / purpose-mismatch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>