team-region-country-filtersrun.md02_define/output/spec.mdOnce a leader can see their whole team's work, the next question is immediately "just EMEA" or "just my direct line". Without a consistent way to narrow, every surface grows its own ad-hoc controls and two views of the same population disagree (FR-9, BR-19). This advances Q2-2026 Objective 1: consistent regional and team roll-ups are what the vendor-partner conversations read.
Three filters — My Team, Region and Country — as one shared component (ScopeBar, per the
design notes: one component, not three variations), mounted identically on the surfaces in scope.
team, region, country, per the list-surface
convention) and are remembered per person between visits: the choice is stored on the
user's record and applied as the default when the URL carries no filter./users and /admin/users). The CSM/SDM dashboards'
existing mine/tenant toggles converge on the same component as those surfaces adopt the
hierarchy (D-7) — deliberately not rebuilt in this run.apps/demo code.regions-and-countries.inherited-visibility.03_build/output/notes.mdapps/web/components/scope-bar/scope-bar.tsx (new): the one shared control
— My Team (the viewer's line, or one direct report's line with its
headcount), Region, and Country (options narrowed by the chosen region;
changing region clears a country it doesn't hold). Selections ride the URL
(team/region/country, camelCase per the list convention, page reset)
and are persisted per person.apps/web/lib/scope-filter-data.ts (new): one server-side resolution for
every mounting surface — URL wins, the person's remembered choices apply
when the URL carries none; the team selection resolves through
hierarchyService.resolveTeamSelection, which only accepts the viewer's
own line (admins may pick any line) and degrades stale choices to
"everyone".apps/web/lib/actions/scope-filters.ts (new): rememberScopeFilters —
authn-only, self-scoped write of user.scopeFilters (new optional field on
the user model; no migration needed — no index, no backfill).packages/services — filters narrow, never widen (BR-19):leads/lead-scope.ts: LeadScopeFilters + applyLeadScopeFilters —
region/country equality plus a team clause ANDed onto whatever
visibility filter is in place (ids cast explicitly so aggregation
$match filters correctly).leadService.findByStatuses and getLeadValueSummary accept filters,
so the board's columns and its value tiles compute from the same
filtered set and never disagree.userService.findAllGroupedByPerson accepts region/country/teamIds.hierarchyService.getTeamFilterOptions (the design's "Priya Nair's line
— 4 people") and resolveTeamSelection./users and
/admin/users — identically, from the same component and the same
resolution.[viewerId].apps/demo change.mine|tenant toggles are unchanged this run — the
convergence path is stated in the spec's out-of-scope.service-lead-ownership-and-handoff.