- Shipped
- August 21, 2026 at 1:04 AM UTC
- Author
- Kamo
- Commit
- 05b90c8
A support agent needs to look inside the customer's tenant to answer the ticket they are holding. Until now the only way in was the blanket SYSTEM_USER platform right, which is all-organizations and permanent — far more than the job needs. Adds a second, much narrower grant and puts both behind one resolver: - SupportSystemAccessResolver answers "may this member enter that organization as the System User", by the blanket right OR by an open ticket assigned to them and raised from that organization. MediaService runs it to decide whether to draw a button; SecurityService runs it again from scratch before minting a session, so the button and the action cannot disagree about who may press it. Preconditions hold on both paths: an active TEAM member of the top-level org, never the System User itself, never the top-level org as a target, never your own org. - The ticket grant is DERIVED, never stored, so it ends the moment the last open assigned ticket from that organization is reassigned, resolved, closed or voided. Nothing has to remember to take it away. - A session already in a browser is not asking anybody anything, though, so SupportSystemSessionRevoker indexes the ones minted this way and destroys them when the grant lapses. Deleting the *** key is the only universal kill switch — every service reads sessions from the same Redis. Key names live in SupportSystemSessionKeys because two services write and read them, and a typo would present as an agent quietly keeping access to a customer's business. Not a @Service: it needs a RedisTemplate, and a shared stereotype requiring one takes down every service that has no Redis on its next deploy. - **************** is the one definition of "open" the grant hangs on. PRE_TICKET counts (a chat request is the same unit of work); resolved does not. Also carries requestorOrgName / requestorOrgIsPlatform on SupportTicketDTO, and status, age and requestor org on the Chats-feed support rows — a support queue that answers more than one tenant is unreadable without them.