feat(tablet_pin_reset): new model + hash helpers + token sign (Task 1)

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>
This commit is contained in:
gsinghpal
2026-05-25 16:48:45 -04:00
parent 33fff5acba
commit 152e6d4328
6 changed files with 426 additions and 0 deletions

View File

@@ -15,3 +15,4 @@ access_fp_job_node_override_operator,fp.job.node.override.operator,fusion_platin
access_res_users_kiosk,res.users.kiosk.read,base.model_res_users,fusion_plating_shopfloor.group_fp_tablet_kiosk,1,0,0,0
access_ir_config_param_kiosk,ir.config_parameter.kiosk.read,base.model_ir_config_parameter,fusion_plating_shopfloor.group_fp_tablet_kiosk,1,0,0,0
access_fp_tablet_session_event_owner,fp.tablet.session.event.owner.read,model_fp_tablet_session_event,fusion_plating.group_fp_owner,1,0,0,0
access_fp_tablet_pin_reset_manager,fp.tablet.pin.reset.manager,model_fp_tablet_pin_reset,fusion_plating.group_fusion_plating_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
15 access_res_users_kiosk res.users.kiosk.read base.model_res_users fusion_plating_shopfloor.group_fp_tablet_kiosk 1 0 0 0
16 access_ir_config_param_kiosk ir.config_parameter.kiosk.read base.model_ir_config_parameter fusion_plating_shopfloor.group_fp_tablet_kiosk 1 0 0 0
17 access_fp_tablet_session_event_owner fp.tablet.session.event.owner.read model_fp_tablet_session_event fusion_plating.group_fp_owner 1 0 0 0
18 access_fp_tablet_pin_reset_manager fp.tablet.pin.reset.manager model_fp_tablet_pin_reset fusion_plating.group_fusion_plating_manager 1 1 1 1