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 6 of 4712 (security review F17). A subscription kept the UserId sent by
the client, and object events (created, modified, deleted, age) were matched by
record type only, so a user could get record names of types it may not read,
delivered to any address. Now a subscription is created for the caller and an
update cannot move it to another user, unless the caller administers users; and
object events skip subscribers without read rights on the record type.
Checked: Service's subscription asked for SuperUser is saved as its own; with
"customer created" subscriptions, Inventory (no read on customers) got 0 events,
Service 1. Full suite: 109 passed, 5 skipped, the same 2 known failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>