Cross–tenant authorization hardening on team–scoped services
A defense–in–depth audit of the team–scoped service layer identified several endpoints that accepted the caller's session but did not validate the caller's membership of, or admin role on, the requested team. The hardened endpoints are: the team–devices roster read, broadcast message send, direct message send, the team update endpoint, and bulk and single position pushes. A new repository–level membership check helper joins the membership, team, and device tables and is invoked before any side effect on every team–scoped service entry point. Rejections are logged with a dedicated audit tag for grep–based review. Six new integration tests and two new repository tests cover the formerly unguarded paths and pin the contract.
Cross–tenant authorization hardening on point–of–interest services
Every write and delete operation on points of interest and POI groups previously accepted the caller's user identifier without using it for authorization. Any authenticated user could read, modify or delete another user's POI data given a security identifier, and the create paths additionally allowed identifier collision to silently rewrite foreign records via upsert. The service layer now loads the resource and its containing group, compares group ownership to the session user, and returns a not–found response on mismatch — failing obscurely without leaking existence. The bulk root update path keeps caller–owned groups going through normally and silently skips foreign entries. Eight new integration tests exercise each blocked attack pattern from a victim and attacker pair.
Dedicated endpoint for relocating points of interest between folders
The generic POI update endpoint cannot move a POI between groups because the payload intentionally carries no group field. A new dedicated move endpoint accepts a POI identifier and a target group identifier, validates both, and atomically updates the parent group reference and modification timestamp at the repository level. The endpoint is exercised by an integration test that creates a source and target group, performs the move, and asserts the resulting tree shape.
Account blacklisting and account–creation rate limit
Authentication requests originating from a blacklisted user now return a structured error response instead of a permissive acknowledgement. In addition, the account creation endpoint is now rate–limited per source to mitigate registration–abuse patterns observed in operational logs.
New PENDING initial state for support tickets
The support ticket lifecycle gains a new initial state, PENDING, which sits before triage and is automatically assigned at ticket creation. This separates the «newly submitted, not yet read» phase from the «under investigation» phase that previously conflated both, improving dashboard ordering and operator workflow without changing existing transitions.