feat(platform): harden access scoping and delivery baseline
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
# Route Access Matrix
|
||||
|
||||
**Date:** 2026-03-29
|
||||
**Purpose:** Explicit interim audience model for sensitive API read routes while the broader least-privilege refactor is still in progress.
|
||||
|
||||
## Decision Rules
|
||||
|
||||
- `protectedProcedure`: only for clearly personal or low-sensitivity reads.
|
||||
- `controllerProcedure`: planning, financial, staffing, or portfolio-wide analytics that should only be visible to `CONTROLLER`, `MANAGER`, or `ADMIN`.
|
||||
- Ownership checks: self-service routes stay user-accessible, but only for the caller's own linked resource unless elevated staff access applies.
|
||||
|
||||
## Applied In This Pass
|
||||
|
||||
### Dashboard
|
||||
|
||||
All routes in [dashboard.ts](/home/hartmut/Documents/Copilot/capakraken/packages/api/src/router/dashboard.ts) are treated as portfolio analytics and now require `controllerProcedure`.
|
||||
|
||||
| Route | Classification | Reason |
|
||||
| --- | --- | --- |
|
||||
| `getOverview` | `controllerProcedure` | exposes global resource/project counts and budget context |
|
||||
| `getPeakTimes` | `controllerProcedure` | exposes portfolio-wide demand/utilization peaks |
|
||||
| `getTopValueResources` | `controllerProcedure` | exposes ranked value/cost-related resource data |
|
||||
| `getDemand` | `controllerProcedure` | exposes staffing demand by project/person/chapter |
|
||||
| `getDetail` | `controllerProcedure` | aggregates the above into assistant-facing strategic detail |
|
||||
| `getChargeabilityOverview` | `controllerProcedure` | already correctly scoped |
|
||||
| `getBudgetForecast` | `controllerProcedure` | exposes budget burn and exhaustion projections |
|
||||
| `getSkillGaps` | `controllerProcedure` | exposes org-wide capability shortfalls |
|
||||
| `getSkillGapSummary` | `controllerProcedure` | summary variant of strategic skill analytics |
|
||||
| `getProjectHealth` | `controllerProcedure` | exposes portfolio-level delivery risk indicators |
|
||||
|
||||
### Vacation
|
||||
|
||||
Routes in [vacation.ts](/home/hartmut/Documents/Copilot/capakraken/packages/api/src/router/vacation.ts) now distinguish between self-service and staff oversight.
|
||||
|
||||
| Route | Classification | Reason |
|
||||
| --- | --- | --- |
|
||||
| `previewRequest` | self-service | personal validation before request creation |
|
||||
| `create` | self-service with ownership check | users may request only for their own resource |
|
||||
| `cancel` | self-service with ownership check | users may cancel only their own requests |
|
||||
| `list` | self-service scoped to own resource, or full staff view for manager/admin | broad vacation visibility is sensitive absence data |
|
||||
| `getById` | self-service scoped to own vacation, or full staff view for manager/admin | direct object lookup should not bypass ownership |
|
||||
| `getForResource` | self-service scoped to own resource, or full staff view for manager/admin | calculator support should not expose foreign absence data |
|
||||
| `getTeamOverlap` | self-service scoped to own resource, or full staff view for manager/admin | overlap warnings are valid, but only for the caller's team context |
|
||||
| `getPendingApprovals` | manager/admin | approval queue is supervisory data |
|
||||
|
||||
### Resource
|
||||
|
||||
Routes in [resource.ts](/home/hartmut/Documents/Copilot/capakraken/packages/api/src/router/resource.ts) remain partially deferred, but the clearest sensitive reads are now explicitly scoped.
|
||||
|
||||
| Route | Classification | Reason |
|
||||
| --- | --- | --- |
|
||||
| `directory` | authenticated safe directory | dedicated low-sensitivity directory for generic pickers, filters, calendars, and lookups; returns only `id`, `eid`, `displayName`, `chapter`, and `isActive`, limits search to name/EID, and preserves anonymization behavior |
|
||||
| `getMyResource` | self-service | explicit route for the caller's linked resource |
|
||||
| `getChargeabilitySummary` | self-service scoped to own resource, or staff with `VIEW_ALL_RESOURCES` | exposes detailed capacity, holiday, assignment, and target data for an individual resource |
|
||||
| `getValueScores` | explicit permission gate `VIEW_SCORES` | ranked score output should not depend on ad hoc session-role strings |
|
||||
| `getById` | self-service scoped to own resource, or staff with `VIEW_ALL_RESOURCES` | full resource detail page includes person-level operational and cost context |
|
||||
| `getByEid` | self-service scoped to own resource, or staff with `VIEW_ALL_RESOURCES` | direct identifier lookup should not bypass ownership |
|
||||
| `getHoverCard` | self-service scoped to own resource, or staff with `VIEW_ALL_RESOURCES` | hover card exposes rates, role, skills, and staffing targets |
|
||||
| `getByIdentifier` | exact self lookup for regular users; broad lookup for staff with `VIEW_ALL_RESOURCES` | lightweight identifier read returns only identity-safe fields (`id`, `eid`, `displayName`, `chapter`, `isActive`) |
|
||||
| `getByIdentifierDetail` | exact self lookup for regular users; broad lookup for staff with `VIEW_ALL_RESOURCES` | explicit detail route for assistant and UI flows that truly need rates, targets, org placement, and skill/count context |
|
||||
| `resolveByIdentifier` | exact self lookup for regular users; broad lookup for staff with `VIEW_ALL_RESOURCES` | minimal identity resolver used by tool chains to convert free-form names/EIDs into canonical IDs without leaking cost or location detail |
|
||||
| `listSummaries` | staff with `VIEW_ALL_RESOURCES` | staff-only org search that returns non-financial summary cards for discovery and candidate selection |
|
||||
| `listSummariesDetail` | staff with `VIEW_ALL_RESOURCES` | explicit richer search variant for assistant/staff workflows that need FTE, LCR, and chargeability context |
|
||||
| `listStaff` | staff with `VIEW_ALL_RESOURCES` | explicit staff-only list for cost-aware, role-aware, and estimate/planning workflows; supports email search, rates, roles, and dynamic field filters |
|
||||
|
||||
### Resource Directory Split
|
||||
|
||||
This pass introduces an explicit audience split in [resource.ts](/home/hartmut/Documents/Copilot/capakraken/packages/api/src/router/resource.ts):
|
||||
|
||||
- `resource.directory` is the default route for generic UI selectors and org-directory style lookups.
|
||||
- `resource.listStaff` is the explicit staff-only route for estimate, staffing, and scenario-planning screens that need cost-sensitive resource data.
|
||||
|
||||
The following web consumers now use `resource.directory`:
|
||||
|
||||
- generic resource comboboxes and assignment pickers
|
||||
- vacation filters and team calendar selectors
|
||||
- timeline quick filters, toolbar lookup, and project panel add-member search
|
||||
- project responsible-person picker
|
||||
- computation graph resource selector
|
||||
- batch skill import resource matching
|
||||
|
||||
### Project
|
||||
|
||||
Routes in [project.ts](/home/hartmut/Documents/Copilot/capakraken/packages/api/src/router/project.ts) now distinguish between lightweight project discovery and planning/commercial detail.
|
||||
|
||||
| Route | Classification | Reason |
|
||||
| --- | --- | --- |
|
||||
| `resolveByIdentifier` | authenticated safe resolver | minimal project identity lookup for names/codes/IDs without commercial detail |
|
||||
| `searchSummaries` | authenticated safe summary search | lightweight project discovery returns only code, name, status, dates, and client |
|
||||
| `searchSummariesDetail` | `controllerProcedure` | exposes budget, win probability, and staffing/estimate counts |
|
||||
| `getByIdentifier` | authenticated safe identifier read | exact/fuzzy lookup returns only identity-safe project fields |
|
||||
| `getByIdentifierDetail` | `controllerProcedure` | exposes commercial and staffing detail, including budget, responsible person, category, and top allocations |
|
||||
| `list` | `controllerProcedure` | broad project listing can expose commercial/custom-field planning context |
|
||||
| `getById` | `controllerProcedure` | full project read model includes allocations, demands, and assignments |
|
||||
| `getShoringRatio` | `controllerProcedure` | derived staffing geography analytics should not be generally user-visible |
|
||||
|
||||
### Timeline
|
||||
|
||||
Routes in [timeline.ts](/home/hartmut/Documents/Copilot/capakraken/packages/api/src/router/timeline.ts) now split personal self-service reads from broad planning views.
|
||||
|
||||
| Route | Classification | Reason |
|
||||
| --- | --- | --- |
|
||||
| `getEntries` | `controllerProcedure` | returns broad staffing allocations across projects/resources for a time window |
|
||||
| `getEntriesView` | `controllerProcedure` | exposes the full timeline read model, including demands and assignments |
|
||||
| `getHolidayOverlays` | `controllerProcedure` | org-wide absence overlays reveal staffing availability context |
|
||||
| `getMyEntriesView` | self-service scoped to own linked resource | personal timeline view for `USER`/`VIEWER`; ignores foreign resource scoping and never broadens beyond the caller's linked resource |
|
||||
| `getMyHolidayOverlays` | self-service scoped to own linked resource | personal holiday overlays for the caller's own timeline window without org-wide absence visibility |
|
||||
| `getEntriesDetail` | `controllerProcedure` | assistant-facing planning detail aggregates allocations, demands, assignments, and holiday summaries |
|
||||
| `getHolidayOverlayDetail` | `controllerProcedure` | detailed overlay summaries are planning-sensitive absence context |
|
||||
| `getProjectContext` | `controllerProcedure` | project-side planning context includes all allocations and cross-resource context |
|
||||
| `getProjectContextDetail` | `controllerProcedure` | detailed project timeline context exposes conflict and overlap analysis |
|
||||
| `previewShift` | `controllerProcedure` | shift preview computes operational and budget impacts before mutation |
|
||||
| `getShiftPreviewDetail` | `controllerProcedure` | detail variant includes project metadata plus cost/conflict preview |
|
||||
| `getBudgetStatus` | `controllerProcedure` | budget burn/remaining exposure is commercial data |
|
||||
|
||||
## Review Standard
|
||||
|
||||
- Any new sensitive read route must document one of:
|
||||
- personal self-service ownership
|
||||
- explicit role gate
|
||||
- explicit permission gate
|
||||
- Any route returning portfolio-wide financial, staffing, scheduling, or HR absence data should not default to plain `protectedProcedure`.
|
||||
Reference in New Issue
Block a user