Four x_fc_* fields on res.config.settings backed by ir.config_parameter:
retention_days (default 365, 0 = forever), alert_threshold (5),
alert_window_min (15), alert_enabled (True). New "Login Audit" block
on the General Settings page (gated by base.group_system on the block,
NOT on the inherited view record per CLAUDE.md rule #11).
CLAUDE.md gotchas added during this task:
#5 Boolean config_parameter fields don't round-trip "False" as a
string — IrConfigParameter.set_param deletes the row on falsy.
Test with assertFalse, never assertEqual(..., "False").
#6 ir.ui.view uses group_ids (Odoo 19 rename mirrored from res.users).
Setting groups_id on an ir.ui.view record raises ValueError at
install. (The XML attribute groups="..." on inner nodes is
unrelated and still works.)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
List, form, and search views for fusion.login.audit, plus a "Login
Events" full-history action and a "Failed Logins (24h)" pre-filtered
action. Both surface under Settings -> Technical -> Login Audit
(menu items gated by base.group_system). Views are no-create / no-edit
/ no-delete to enforce append-only at the UI layer too.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds four x_fc_* fields on res.users: login_audit_ids (One2many),
login_audit_count (compute), last_successful_login (compute, stored),
last_login_ip (compute, stored). action_fc_view_login_audit returns
a window action scoped to the current user. View inheritance adds a
smart button to the button box and a "Login Activity" page to the
notebook, both gated by base.group_system on the inner XML nodes
(NOT on the view record — Odoo 19 forbids that; see CLAUDE.md rule #11).
Tests (2 new, 18 total green):
test_computed_last_successful_login — uses registry cursor to commit
the audit row so the stored compute picks it up across the
TransactionCase boundary.
test_action_view_login_audit_returns_window_action — smart-button
action shape + domain scoping.
CLAUDE.md rule #11 added: inherited ir.ui.view records cannot have
groups/group_ids on the record; the gate must be on the inner XML nodes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>