Skip to main content
MUZE enforces data boundaries at two levels: ScopeGuard at the URL level, and explicit scope filters in each service method at the query level. This page shows both patterns.

ScopeGuard (URL level)

The ScopeGuard runs after PermissionsGuard and before the controller handler. It reads @RequireScope(...) metadata from the route.

Configuration

Scope resolution logic

Service-layer scoping (query level)

Every service method that reads data applies explicit scope filters. This is not automated; it is a convention enforced through code review.

Store-scoped queries

Client-scoped queries

Scope propagation through relations

When querying across relations, scope must be maintained. A store-scoped order query follows the chain Order → Employee → Store → clientId. The service resolves this chain so cross-client data cannot leak through joined queries.

Client narrowing

Client-scoped endpoints accept an optional clientId query parameter, resolved by resolveRequestedClientId in backend/src/auth/user-scope.ts. The parameter can only narrow a query:
  • Admin: filters to the requested client
  • HR: honoured only when inside the assigned client; otherwise ignored (role scope is authoritative)
  • Store Manager: ignored entirely; store scope is the only filter
The resolved filter is always combined with the existing scope filter, so a request parameter can never weaken role or store scope.