Users who may edit contacts but not users (Service, Sales, Accounting) could
give a contact login any role, BizAdmin and OpsAdmin included, and roles are
what every check uses (security review F28). Now:
- saving a Customer or HeadOffice user with any role other than Customer or
CustomerRestricted is refused (error on Roles);
- UserBiz.EffectiveRoles masks a contact's roles to the customer roles wherever
they are applied: the token middleware, download-key routes, and the
notification subscriber check, so contacts that already have staff roles
stored act without them.
Checked: Service creating a contact with BizAdmin refused, with Customer works;
a contact with OpsAdmin stored in the database gets 403 downloading a log file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Step 2 of 4712 (security review F13). The customer work-order rights checked
only tag-based feature switches, never which customer a work order belongs to.
New UserBiz.CustomerContactOwnsCustomerAsync (own customer, or for a head
office contact a customer of its head office), used by:
- workorder/customer/{id}: another customer's work order is not found (404);
- customer work order report (-100): exactly one work order, which must be the
contact's (the renderer used every id it was given);
- work order attachment list and download for contacts; other attachment types
are refused to contacts (the customer screens show them only on work orders).
Checked: other customer's work order 404 (was 200); report on another's or on
two work orders not found; own customer report still accepted (202).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>