9.8 KiB
Requirements Document
Introduction
Add per-user Business Unit (BU) team assignment so that multiple users with different BU responsibilities can share the same dashboard instance. The Reporting page (Ivanti findings) and Compliance page will display only data relevant to the logged-in user's assigned BU teams, while the CVE home page remains a shared global view. This follows "Option B" — a single Ivanti API key with a broadened sync filter, storing all BU findings in the local cache and filtering at query time based on the user's team assignments.
Glossary
- BU: Business Unit — an organizational group within the Ivanti platform (e.g. NTS-AEO-STEAM, NTS-AEO-ACCESS-ENG, NTS-AEO-INTELDEV)
- bu_teams: A per-user field storing the comma-separated list of BU team identifiers the user is authorized to view
- FINDINGS_FILTERS: The hardcoded Ivanti API filter array that currently scopes synced findings to specific BU values
- Compliance Team: One of the allowed team identifiers used in the compliance data model (STEAM, ACCESS-ENG, ACCESS-OPS, INTELDEV)
- Reporting Page: The Ivanti host findings triage page that displays findings from the local cache
- Compliance Page: The AEO compliance posture page that displays non-compliant devices by team
- CVE Home Page: The shared CVE tracking page — remains unscoped and visible to all users
- Admin: A user in the Admin user_group who can manage users and assign BU teams
- Team Selector: The UI dropdown on the Compliance page that lets users switch between their assigned teams
Requirements
Requirement 1: Per-User BU Team Assignment
User Story: As an admin, I want to assign one or more BU teams to each user, so that their dashboard experience is scoped to the data relevant to their responsibilities.
Acceptance Criteria
- THE users table SHALL include a
bu_teamscolumn storing a comma-separated list of team identifiers - WHEN a new user is created without explicit bu_teams, THE Dashboard SHALL default bu_teams to an empty string (no teams assigned)
- THE Dashboard SHALL accept any combination of known team identifiers: STEAM, ACCESS-ENG, ACCESS-OPS, INTELDEV
- THE Dashboard SHALL allow Admin users to assign or update bu_teams for any user via the user management interface
- THE Dashboard SHALL validate that bu_teams contains only recognized team identifiers before persisting
Requirement 2: Expose User Teams in Session
User Story: As a logged-in user, I want my assigned BU teams to be available in my session context, so that the frontend can scope data requests appropriately.
Acceptance Criteria
- WHEN a user authenticates, THE auth middleware SHALL attach the user's parsed bu_teams array to
req.user.teams - THE
GET /api/auth/meendpoint SHALL return the user's teams array in the response - THE login response SHALL include the user's teams array
- IF a user has no bu_teams assigned (empty string), THEN the teams array SHALL be empty
[]
Requirement 3: Broaden Ivanti Sync Filter
User Story: As a system operator, I want the Ivanti sync to pull findings for all configured BU values, so that users from any BU can see their relevant findings without needing separate API keys.
Acceptance Criteria
- THE FINDINGS_FILTERS BU value SHALL be configurable via an environment variable
IVANTI_BU_FILTERrather than hardcoded - IF
IVANTI_BU_FILTERis not set, THE Dashboard SHALL default to the current value'NTS-AEO-ACCESS-ENG,NTS-AEO-STEAM'for backward compatibility - THE CLOSED_COUNT_FILTERS SHALL use the same configurable BU filter value
- THE Dashboard SHALL document the
IVANTI_BU_FILTERvariable in.env.examplewith usage instructions
Requirement 4: Filter Reporting Page by User's Teams
User Story: As a user assigned to specific BU teams, I want the Reporting page to show only findings belonging to my BUs, so that I see relevant data without noise from other teams.
Acceptance Criteria
- THE
GET /api/ivanti/findingsendpoint SHALL accept an optionalteamsquery parameter - WHEN
teamsis provided, THE endpoint SHALL filter the cached findings to only those whosebuOwnershipmatches one of the specified team values - WHEN
teamsis not provided, THE endpoint SHALL return all cached findings (backward-compatible for Admin or unscoped views) - THE frontend Reporting page SHALL pass the logged-in user's teams when fetching findings
- IF a user has no teams assigned (empty array) and the user is not Admin, THE Reporting page SHALL display a message indicating no BU teams are configured and direct them to contact an admin
- Admin users SHALL have a scope toggle with three modes: "My Teams" (filters to admin's own bu_teams), "All BUs" (shows everything unfiltered)
- THE Admin scope toggle SHALL default to "My Teams" so the admin's daily workflow view is scoped to their assigned BUs
- WHEN an Admin switches to "All BUs" mode, THE Dashboard SHALL fetch findings without a teams filter
- THE scope toggle selection SHALL persist across page navigations within the same session (stored in component state or localStorage)
Requirement 5: Filter Compliance Page by User's Teams
User Story: As a user assigned to specific BU teams, I want the Compliance page team selector to show only my assigned teams, so that I cannot accidentally view or interact with another team's compliance data.
Acceptance Criteria
- THE frontend Compliance page team selector SHALL display only the teams present in the user's teams array
- IF a user has only one team assigned, THE team selector SHALL default to that team and may be hidden or disabled
- IF a user has no teams assigned and the user is not Admin, THE Compliance page SHALL display a message indicating no teams are configured
- Admin users SHALL see all available teams in the selector regardless of their personal bu_teams assignment
- Admin users SHALL have the same scope toggle as the Reporting page: "My Teams" shows only their assigned teams in the selector, "All BUs" shows all available teams
- THE Admin scope toggle state SHALL be shared across Reporting and Compliance pages (single toggle, consistent behavior)
- THE backend compliance endpoints SHALL continue to accept any valid team parameter (authorization is frontend-scoped, not backend-enforced, to keep the API flexible for Admin use)
Requirement 6: Admin User Management for BU Teams
User Story: As an admin, I want a UI to assign and modify BU teams for users, so that I can onboard new team members and adjust assignments as responsibilities change.
Acceptance Criteria
- THE user management create form SHALL include a multi-select or checkbox group for BU team assignment
- THE user management edit form SHALL include a multi-select or checkbox group for BU team assignment
- WHEN an admin updates a user's bu_teams, THE Dashboard SHALL log the change in the audit trail with previous and new values
- THE user list table SHALL display each user's assigned BU teams
- THE Dashboard SHALL provide a visual indicator when a user has no teams assigned (warning state)
Requirement 7: CVE Home Page Remains Shared
User Story: As any user, I want the CVE tracking page to remain a shared global view, so that all teams can collaborate on vulnerability tracking regardless of BU assignment.
Acceptance Criteria
- THE CVE home page SHALL NOT filter data based on the user's bu_teams
- ALL authenticated users SHALL see the same CVE data regardless of team assignment
- THE CVE creation, editing, and status workflows SHALL remain unaffected by bu_teams
Requirement 8: Ivanti Findings Count Scoping
User Story: As a user, I want the findings count badges and status cards on the Reporting page to reflect only my BU's findings, so that metrics are meaningful to my scope.
Acceptance Criteria
- THE
GET /api/ivanti/findings/countsendpoint SHALL accept an optionalteamsparameter and return counts filtered to those BUs - THE open/closed count cards on the Reporting page SHALL reflect the user's scoped findings
- WHEN viewing all BUs (Admin toggle), THE counts SHALL reflect the full unfiltered totals
Requirement 9: Export Scoping
User Story: As a user exporting findings data, I want exports to respect my BU scope, so that I don't inadvertently share another team's data.
Acceptance Criteria
- THE Exports page Ivanti findings exports SHALL filter by the user's teams by default
- Admin users in "My Teams" mode SHALL export only their assigned BUs; in "All BUs" mode SHALL export everything
- THE exported filename or metadata SHALL indicate which BU scope was applied
Requirement 10: Admin Scope Toggle
User Story: As an admin with assigned BU teams, I want a global scope toggle that lets me switch between "My Teams" (my daily workflow) and "All BUs" (full visibility), so that I can work efficiently in my own BU context while retaining the ability to see the full picture when needed.
Acceptance Criteria
- THE Dashboard SHALL display a scope toggle control visible only to Admin users
- THE scope toggle SHALL offer two modes: "My Teams" and "All BUs"
- WHEN "My Teams" is active, THE Dashboard SHALL filter Reporting, Compliance, and Exports to the admin's own bu_teams assignment (identical behavior to a non-admin user)
- WHEN "All BUs" is active, THE Dashboard SHALL show all data across all BUs without filtering
- THE scope toggle SHALL default to "My Teams" on login so the admin's daily workflow is immediately relevant
- THE scope toggle state SHALL persist in localStorage so it survives page refreshes within the same browser
- THE scope toggle SHALL be displayed in a consistent location (e.g. top nav bar or header area) accessible from any page
- WHEN the admin's bu_teams is empty, "My Teams" mode SHALL behave the same as "All BUs" (no filtering applied)