Three-scope user model: holding-wide auto-grant, multi-company, single-company. Time-restricted grants with expiry date and automated cleanup worker.
Three tiers of access — from full-holding visibility down to a single subsidiary.
Owner, CFO, group controller. Automatic access to all companies in the holding — no explicit per-company rows needed.
IsInHolding()user_company_access rows neededusers.holding_idAccountant or manager serving several subsidiaries. Explicit rows in user_company_access for selected companies only.
expires_at per rowA manager, accountant or operator within one subsidiary. Exactly one access row. Cannot see or switch to other entities in the group.
The user creation and edit forms include a unified company access matrix tab — scope selector, per-company role assignment and optional expiry date on each row.
Choose holding-wide, multi-company or single-company. Switching to single-company automatically clears all but one checkbox.
Each checked company gets a role: Admin · Accountant · Manager · Viewer. Role is stored per access row, not globally.
Leave empty for permanent access. Set a date for temporary grants — contractors, auditors, project-based access.
Set expires_at on any user-company grant. 7-day warning notifications. Automated cleanup worker revokes expired access and invalidates the in-process cache.
FindExpired()