Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

339 lines
40 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Scratchpad — Advanced Authorization Kernel and Premium ABAC Bundles
- Plan slug: `premium-abac-authorization-kernel`
- Created: `2026-04-21`
## What This Is
Keep a lightweight, continuously-updated log of discoveries and decisions made while implementing this plan.
Prefer short bullets. Append new entries as you learn things, and also *update earlier notes* when a decision changes or an open question is resolved.
## Decisions
- (2026-04-21) The product direction is a **comprehensive authorization-kernel overhaul** rather than a small ABAC bolt-on.
- (2026-04-21) The design should follow the **ALGA plan** approach with `PRD.md`, `features.json`, `tests.json`, and `SCRATCHPAD.md` under `ee/docs/plans/`.
- (2026-04-21) The old policy DSL should be treated as abandoned scaffolding and **not** evolved into the main runtime direction.
- (2026-04-21) Configurable ABAC should use **admin-configurable templates**, not arbitrary expressions.
- (2026-04-21) The most important first-class relationship concepts are **owns / manages / assigned / same client / client portfolio / selected boards**.
- (2026-04-21) Configured premium ABAC is **narrowing-only**; it must never widen access beyond RBAC + built-in kernel behavior.
- (2026-04-21) The shared authorization runtime should exist in **CE and EE** so existing ABAC-like product rules can be normalized without forking security behavior by edition.
- (2026-04-21) The **EE-only seam** is the configurable control plane: bundle CRUD, assignments, publishing, simulation, and governance UX.
- (2026-04-21) Configurable premium ABAC management is officially gated at the existing **Premium** tenant tier by default.
- (2026-04-21) The packaging model should mirror existing EE plugin/provider seams: one stable interface, CE builtin implementation, EE configurable implementation.
- (2026-04-21) Bundle assignments should support **roles, teams, users, and API keys**.
- (2026-04-21) Bundle assignments should use **one generic assignment table** keyed by `target_type + target_id`.
- (2026-04-21) Bundle changes should use a **draft → publish** model rather than editing active policy in place.
- (2026-04-21) The primary admin artifact should be a **bundle**, not a raw policy row.
- (2026-04-21) The first configurable resource families are **tickets, documents, time, billing, projects, and assets**, with API-key scoping treated as cross-cutting.
- (2026-04-21) The EE simulator should support both **real principals/records** and **synthetic scenarios**.
- (2026-04-21) The migration must explicitly document and validate **current behavior parity** before and after cutover.
## Discoveries / Constraints
- (2026-04-21) Core RBAC is currently centered in `server/src/lib/auth/rbac.ts` and `packages/db/src/models/user.ts` via role/permission lookup plus MSP/client portal gating.
- (2026-04-21) There are multiple copies of RBAC and policy-engine code (`server`, `packages/auth`, `packages/tags`, `ee/server`), which reinforces the need for a single shared runtime contract.
- (2026-04-21) The codebase already contains important production ABAC-like behavior that should become built-in kernel rules rather than optional premium overlays.
- (2026-04-21) `packages/tickets/src/lib/clientPortalVisibility.ts` is the clearest existing shared scope-filter example and is a strong model for list/query narrowing.
- (2026-04-21) `packages/scheduling/src/actions/timeEntryDelegationAuth.ts` already expresses a high-value managed-hierarchy relationship model (`self`, `manager`, `tenant-wide`).
- (2026-04-21) `server/src/app/api/documents/view/[fileId]/route.ts` contains a large amount of inline relationship/visibility logic that should be kernelized carefully and fail-closed.
- (2026-04-21) `packages/client-portal/src/actions/client-portal-actions/visibilityGroupActions.ts` demonstrates same-client and client-admin relationship guards that belong in the shared kernel, not only in premium configuration.
- (2026-04-21) API-key-backed controllers such as `server/src/lib/api/controllers/ApiBaseController.ts` and `ApiTicketController.ts` are mostly RBAC-only today and are a likely parity gap compared with UI/server-action flows.
- (2026-04-21) There is a legacy `policies` table and policy UI scaffolding, but runtime evaluation does not appear to rely on it as the authoritative production path.
- (2026-04-21) The dev seed `server/seeds/dev/49_policies.cjs` references stale concepts like `department`, confirming drift in the old DSL path.
- (2026-04-21) Existing EE gating patterns already exist in the repo:
- edition detection via `server/src/lib/features.ts`
- tier gating via `server/src/lib/tier-gating/assertTierAccess.ts` and `ServerTierGate.tsx`
- feature-tier mapping in `packages/types/src/constants/tierFeatures.ts`
- Teams-style availability logic in `packages/integrations/src/lib/teamsAvailability.ts`
- (2026-04-21) The product already uses stable CE/EE entrypoint aliasing (for example `packages/product-auth-ee/{oss,ee}/entry*`), which is the preferred packaging pattern for the configurable authorization seam.
## Commands / Runbooks
- (2026-04-21) Search for RBAC/ABAC-related code and existing inline rules:
`rg -n --hidden --glob '!node_modules' --glob '!dist' "\bABAC\b|attribute[- ]based|access policy|policy engine|scope filter|row[- ]level|hasPermission\(|role_permissions|permissions|is_client_admin|portal_visibility_group_id|isInReportsToChain|approval_status|is_client_visible" packages server ee`
- (2026-04-21) Find policy-engine and legacy DSL scaffolding:
`rg -n --hidden --glob '!node_modules' --glob '!dist' "class PolicyEngine|evaluateAccess\(|parsePolicy|policyActions|policies\b" packages server ee`
- (2026-04-21) Inspect current Teams-style edition/tier gating references:
`rg -n --hidden --glob '!node_modules' --glob '!dist' "tier-gating|TIER_FEATURES|Teams integration|teamsAvailability|isEnterprise" packages server ee`
- (2026-04-21) Scaffold an ALGA plan folder:
`python3 /Users/roberisaacs/.agents/skills/alga-plan/scripts/scaffold_plan.py "Advanced Authorization Kernel and Premium ABAC Bundles" --slug premium-abac-authorization-kernel`
## Links / References
- `packages/auth/src/lib/getSession.ts`
- `packages/auth/src/lib/getCurrentUser.ts`
- `packages/auth/src/lib/withAuth.ts`
- `server/src/lib/auth/rbac.ts`
- `packages/db/src/models/user.ts`
- `packages/tickets/src/lib/clientPortalVisibility.ts`
- `packages/scheduling/src/actions/timeEntryDelegationAuth.ts`
- `server/src/app/api/documents/view/[fileId]/route.ts`
- `packages/client-portal/src/actions/client-portal-actions/visibilityGroupActions.ts`
- `server/src/lib/api/controllers/ApiBaseController.ts`
- `server/src/lib/api/controllers/ApiTicketController.ts`
- `packages/auth/src/actions/policyActions.ts`
- `packages/product-auth-ee/oss/entry.tsx`
- `packages/product-auth-ee/ee/entry.ts`
- `server/src/lib/features.ts`
- `server/src/lib/tier-gating/assertTierAccess.ts`
- `server/src/lib/tier-gating/ServerTierGate.tsx`
- `packages/types/src/constants/tierFeatures.ts`
- `packages/integrations/src/lib/teamsAvailability.ts`
- `ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/CURRENT_AUTHORIZATION_BASELINE.md`
- `context.md`
- `research.md`
## Open Questions
- Which exact project and asset surfaces are in the first migration wave under the shared kernel versus the second wave?
- Which billing fields participate in v1 redaction, and which wait for a later phase?
- Which API surfaces are in the first parity wave once the shared kernel exists?
## Progress Log
- (2026-04-21) Completed `F001`: validated and retained `CURRENT_AUTHORIZATION_BASELINE.md` as the parity contract for tickets/documents/time/projects/assets/billing/client-portal/API-key behaviors.
- (2026-04-21) Completed `F002` by introducing a shared kernel contract at `server/src/lib/authorization/kernel/contracts.ts` with common entry points for single-resource authorization, scope resolution, mutation authorization, field redactions, and explainability.
- (2026-04-21) Completed `F003` with CE builtin provider `BuiltinAuthorizationKernelProvider` (`server/src/lib/authorization/kernel/providers/builtinProvider.ts`) that evaluates only builtin product rules.
- (2026-04-21) Completed `F004` by introducing bundle overlay provider plumbing (`BundleAuthorizationKernelProvider`) plus EE kernel factory (`ee/server/src/lib/authorization/kernel.ts`) and CE stub seam (`packages/ee/src/lib/authorization/kernel.ts`).
- (2026-04-21) Completed `F005` with edition-aware runtime loading (`server/src/lib/authorization/kernel/enterpriseEntry.ts` + `index.ts`) so callers use one kernel interface without `isEnterprise()` branching.
- (2026-04-21) Completed `F006`: kernel engine now hard-gates on RBAC first (`server/src/lib/authorization/kernel/engine.ts`) before builtin/bundle narrowing logic.
- (2026-04-21) Completed `F007` via shared relationship template evaluators in `server/src/lib/authorization/kernel/relationships.ts` for `own`, `assigned`, `managed`, `same_client`, `client_portfolio`, `same_team`, and `selected_boards`.
- (2026-04-21) Completed `F008` with explicit intersection composition in `server/src/lib/authorization/kernel/scope.ts` (`intersectAuthorizationScopes`).
- (2026-04-21) Completed `F009` by adding shared mutation-guard evaluation through builtin provider hooks and `authorizeMutation` in the kernel engine.
- (2026-04-21) Completed `F010` by adding shared redaction hook support through `resolveFieldRedactions` and provider-level field redaction resolvers.
- (2026-04-21) Completed `F011` by emitting structured stage-aware reasons (`rbac`, `builtin`, `bundle`, `mutation`, `redaction`) in every decision path.
- (2026-04-21) Completed `F012` with request-local memoization support (`RequestLocalAuthorizationCache`) and RBAC memoization in the kernel engine.
- (2026-04-21) Validation runbook for this checkpoint:
- `cd server && npx vitest run src/test/unit/authorization/kernel.engine.test.ts src/test/unit/authorization/kernel.relationships.test.ts`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `F013`: added regression boundary test `server/src/test/unit/authorization/kernel.legacyDirection.test.ts` to enforce that the new kernel path does not import legacy policy DSL runtime modules; this codifies the cutover direction before resource-family migrations.
- (2026-04-21) Completed `F014`-`F017` with migration `server/migrations/20260421190000_create_authorization_bundle_control_plane.cjs` introducing `authorization_bundles`, `authorization_bundle_revisions`, `authorization_bundle_rules`, and generic `authorization_bundle_assignments`.
- (2026-04-21) Completed `F018` with tenant-scoped assignment target validation in `createBundleAssignment(...)` (`server/src/lib/authorization/bundles/service.ts`) for role/team/user/api_key targets.
- (2026-04-21) Completed `F019`-`F021` by modeling lifecycle states (`active/archived`, `draft/published/archived`, `active/disabled`) plus transactional publish, bundle archive, and assignment enable/disable service operations.
- (2026-04-21) Completed `F022` and `F023` with bundle-resolution logic that aggregates active role/team/user/api_key assignments, resolves published revision rules, and applies them through kernel intersection semantics.
- (2026-04-21) Completed `F024` and `F025` via typed catalog enforcement in `server/src/lib/authorization/bundles/catalog.ts` and expanded relationship template support (`own_or_assigned`, `own_or_managed`, `selected_clients`).
- (2026-04-21) Completed `F026` by adding support hooks for `not_self_approver`, `client_visible_only`, and `hide_sensitive_fields` constraint behavior in bundle evaluation.
- (2026-04-21) Completed `F027` by shipping starter bundle definitions in `server/src/lib/authorization/bundles/starterBundles.ts` for assigned-client technician, project delivery team, time manager, restricted asset operator, and finance reviewer scenarios.
- (2026-04-21) Completed `T001` and `T002`:
- `T001`: baseline artifact validated and maintained.
- `T002`: migration contract test added at `server/src/test/unit/migrations/authorizationBundleControlPlaneMigration.test.ts` to assert control-plane schema shape and narrowing-only constraints.
- (2026-04-21) Additional validation runbook for this checkpoint:
- `cd server && npx vitest run src/test/unit/authorization/kernel.engine.test.ts src/test/unit/authorization/kernel.relationships.test.ts src/test/unit/authorization/kernel.legacyDirection.test.ts src/test/unit/authorization/bundle.catalog.test.ts src/test/unit/authorization/bundle.provider.test.ts src/test/unit/authorization/starterBundles.test.ts src/test/unit/migrations/authorizationBundleControlPlaneMigration.test.ts`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `F028` by replacing EE `PolicyManagement` with a tier-gated Authorization Bundle Library surface:
- UI: `ee/server/src/components/settings/policy/PolicyManagement.tsx`
- Actions: `ee/server/src/lib/actions/auth/authorizationBundleActions.ts`
- Service additions for list/create/clone: `server/src/lib/authorization/bundles/service.ts`
- Tier feature gate: `TIER_FEATURES.ADVANCED_AUTHORIZATION_BUNDLES` in `packages/types/src/constants/tierFeatures.ts`
- (2026-04-21) `F028` implementation details:
- Browse/search active+archived bundles from `authorization_bundles`.
- Clone bundle into new draft-backed custom bundle while copying source revision rules.
- Archive active bundles.
- Seed starter bundles into tenant scope via one action.
- Tier enforcement is server-side (`assertTierAccess`) and client-side (`useTierFeature`) with Premium minimum tier.
- (2026-04-21) Completed `T003` with DB-backed integration coverage in `server/src/test/integration/authorization/bundleRevisionPublishing.integration.test.ts` validating:
- publish moves previous published revision to archived
- target draft revision becomes published
- stable bundle identity and assignment rows are preserved
- (2026-04-21) Validation runbook for `F028` + `T003` checkpoint:
- `cd packages/types && npx vitest run src/constants/tierFeatures.test.ts --coverage.enabled=false`
- `mkdir -p server/coverage/.tmp && cd server && npx vitest run --coverage.enabled=false src/test/integration/authorization/bundleRevisionPublishing.integration.test.ts`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `F029` by extending EE policy settings to include a draft-oriented Bundle Editor in resource sections (Tickets, Documents, Time, Projects, Assets, Billing), replacing raw policy text editing:
- UI editor surface: `ee/server/src/components/settings/policy/PolicyManagement.tsx`
- Draft editor actions: `getAuthorizationBundleDraftEditorAction`, `upsertAuthorizationBundleDraftRuleAction`, `deleteAuthorizationBundleDraftRuleAction` in `ee/server/src/lib/actions/auth/authorizationBundleActions.ts`
- Draft helpers in service layer: `ensureDraftBundleRevision`, `listBundleRulesForRevision`, `deleteBundleRule` in `server/src/lib/authorization/bundles/service.ts`
- (2026-04-21) `F029` rationale: enforce draft-first authoring semantics by materializing/rehydrating a draft revision from the currently published revision when no draft exists, then editing only draft rules grouped by resource family.
- (2026-04-21) Completed `F030` by adding human-readable summaries for both bundle-level and rule-level understanding:
- Rule summaries in editor rows (`Narrow <resource> <action> to ...`) generated in `ee/server/src/components/settings/policy/PolicyManagement.tsx`.
- Effective bundle summaries in library rows (status + assignment impact text).
- Draft-vs-published revision summary generated server-side in `getAuthorizationBundleDraftEditorAction` (`ee/server/src/lib/actions/auth/authorizationBundleActions.ts`) and rendered in the editor header.
- (2026-04-21) Completed `F031` by adding an Assignment Manager panel to the EE bundle surface:
- New action `listAuthorizationBundleAssignmentsAction` resolves assignment targets across role/team/user/api_key with friendly labels.
- UI now has per-bundle `Assignments` toggle showing grouped assignment cards and status.
- Files: `ee/server/src/lib/actions/auth/authorizationBundleActions.ts`, `ee/server/src/components/settings/policy/PolicyManagement.tsx`.
- (2026-04-21) Completed `F032` by adding an EE Access Simulator for real principals + existing records:
- Principal lookup action: `listAuthorizationSimulationPrincipalsAction`.
- Record lookup action by resource family: `listAuthorizationSimulationRecordsAction`.
- Simulation execution: `runAuthorizationBundleSimulationAction` compares draft vs published revision decisions with explainability codes.
- UI: simulator panel in `ee/server/src/components/settings/policy/PolicyManagement.tsx`.
- (2026-04-21) Completed `F033` by extending the simulator with synthetic scenarios:
- Added synthetic record input (`ownerUserId`, `clientId`, `boardId`, `isClientVisible`) when no real record is suitable.
- Simulation action now supports `syntheticRecord` payloads and runs the same draft-vs-published decision flow.
- (2026-04-21) Completed `F034` by tightening unavailable/upgrade states for non-entitled contexts:
- EE tier-gate surface already blocks with `useTierFeature(TIER_FEATURES.ADVANCED_AUTHORIZATION_BUNDLES)`.
- CE placeholder copy updated (`packages/ee/src/components/settings/policy/PolicyManagement.tsx`) to show Premium upgrade path while clarifying builtin authorization remains active.
- (2026-04-21) Completed `F035` by adding explicit server-side permission/tier gates to bundle management actions:
- CRUD + editor + simulator + assignment + publish actions all enforce `assertTierAccess(TIER_FEATURES.ADVANCED_AUTHORIZATION_BUNDLES)` plus RBAC permission checks (`system_settings:read|write`).
- Added write-gated actions for publish and assignment status changes in `ee/server/src/lib/actions/auth/authorizationBundleActions.ts`.
- (2026-04-21) Completed `F036` by exposing an audit-trail read model from persisted bundle metadata:
- Added `getAuthorizationBundleAuditTrailAction` returning chronological lifecycle events for bundle creation/archive, draft creation, publish events, and assignment changes.
- Uses existing metadata columns (`created_by`, `updated_by`, `published_by`, timestamps, assignment status) as authoritative audit source.
- (2026-04-21) Completed `F037` for selected server-action paths by moving ticket list/detail authorization to shared kernel checks after RBAC:
- `packages/tickets/src/actions/ticketActions.ts` now resolves authorization subject context and calls kernel `authorizeResource` for `getTicketsForList` and `getTicketById`.
- List path applies kernel decision filtering to ticket rows; single-ticket path denies when kernel disallows.
- Current cut keeps builtin-kernel path for these endpoints; premium ticket bundle overlays are tracked separately in `F039`.
- (2026-04-21) Validation for `F037` path-level cutover:
- `cd packages/tickets && npx vitest run src/actions/ticketActions.ticketOrigin.test.ts src/actions/ticketActions.moveToBoard.test.ts --coverage.enabled=false`
- (2026-04-21) Completed `F038` by kernelizing selected-board narrowing for client-portal style ticket access in selected ticket action paths:
- Added client visibility-group board resolution via `getClientContactVisibilityContext(...)`.
- For client principals, ticket list/detail now pass `selectedBoardIds` into kernel evaluation with `selected_boards` relationship template and fail-closed behavior when visibility context is missing/invalid.
- Added client-scope guard (`clientId`) alongside board narrowing for list/detail parity.
- (2026-04-21) Completed `F039` by enabling premium bundle overlays on selected ticket list/detail paths:
- Ticket actions now instantiate kernel with a bundle provider that resolves active published bundle rules for the current principal (`resolveBundleNarrowingRulesForEvaluation`).
- Bundle template semantics are now enforced in bundle provider (`bundle_template_denied`) by evaluating each matching rules relationship template against record context.
- This enables ticket narrowing from bundle templates like assignment/client/team/selected-board in the migrated ticket paths.
- (2026-04-21) Completed `F040` by migrating selected document server-action list/detail/download paths to the shared kernel:
- Added shared document auth helpers in `packages/documents/src/actions/documentActions.ts` for principal resolution, relationship-context normalization from `document_associations`, and per-record kernel evaluation.
- Migrated `getDocument`, `getAllDocuments`, `getDocumentsByEntity`, `getDocumentsByFolder`, and `downloadDocument` to run `authorizeResource` through the kernel after RBAC.
- Preserved client-user semantics by enforcing `own OR same_client` relationship checks plus fail-closed `is_client_visible` guard on non-owned records.
- (2026-04-21) Completed `F041` by enabling premium document bundle overlays on migrated document paths:
- Document actions now instantiate a bundle provider backed by `resolveBundleNarrowingRulesForEvaluation(...)`.
- Document record context passed to kernel now includes `clientId`, `teamIds`, and `is_client_visible`, enabling client/portfolio-style narrowing and `client_visible_only` enforcement where configured.
- (2026-04-21) Completed `F042` by wiring document field-redaction hooks into migrated document surfaces:
- Migrated list/detail document actions now apply kernel-provided `redactedFields` to returned document payloads without mutating allow/deny behavior.
- Redaction plumbing is centralized via `authorizeAndRedactDocuments(...)`.
- (2026-04-21) Validation runbook for `F040`-`F042` checkpoint:
- `cd packages/documents && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- `cd server && npx vitest run src/test/unit/authorization/kernel.engine.test.ts src/test/unit/authorization/bundle.provider.test.ts --coverage.enabled=false`
- (2026-04-21) Completed `F043` by kernelizing selected time/timesheet delegation checks through shared relationship semantics:
- `packages/scheduling/src/actions/timeEntryDelegationAuth.ts` now resolves managed scope (`teams` manager + optional reports-to chain) and evaluates non-self delegation with kernel `managed` relationship templates via `authorizeResource`.
- Preserved delegation hierarchy: `self` short-circuit, `timesheet:approve` prerequisite, `timesheet:read_all` tenant-wide override, then manager/reports-to managed scope.
- `fetchTimeSheetsForApproval` now uses the same managed-subject resolver to scope approval list visibility consistently with delegation rules.
- (2026-04-21) Validation runbook for `F043` checkpoint:
- `cd packages/scheduling && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- `cd packages/scheduling && npx vitest run tests/timeEntryCrud.changeRequests.test.ts tests/timeSheetClient.reopen.test.tsx --coverage.enabled=false` (known pre-existing failure in `T012` mock chain: `db(...).leftJoin is not a function`)
- (2026-04-21) Completed `F044` by enabling premium time narrowing overlays in delegation evaluation:
- `assertCanActOnBehalf` now composes built-in delegation and premium bundle narrowing by adding `BundleAuthorizationKernelProvider` with `resolveBundleNarrowingRulesForEvaluation(...)`.
- For `timesheet:read_all` principals, builtin delegation now allows broad scope, while bundle templates can narrow that scope (for example to managed-only/self-only behavior) without widening baseline RBAC/delegation.
- Result scope classification remains explicit (`manager` when subject is in managed set, otherwise `tenant-wide` only when read-all plus kernel allow).
- (2026-04-21) Validation runbook for `F044` checkpoint:
- `cd packages/scheduling && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `F045` by kernelizing not-self-approver checks in selected time approval flows:
- Added `assertCanApproveSubject(...)` in `packages/scheduling/src/actions/timeEntryDelegationAuth.ts`, which composes delegation checks with kernel `authorizeMutation` for `approve` mutations.
- Added a built-in mutation guard (`timesheet_not_self_approver_denied`) and bundle-aware mutation overlay evaluation (`not_self_approver` constraint) so approval gating is centralized in kernel semantics.
- Wired approval paths to the new guard:
- `packages/scheduling/src/actions/timeSheetActions.ts` (`approveTimeSheet`, `bulkApproveTimeSheets`)
- `packages/scheduling/src/actions/timeEntryCrudActions.ts` (`updateTimeEntryApprovalStatus` when transitioning to `APPROVED`)
- (2026-04-21) Validation runbook for `F045` checkpoint:
- `cd packages/scheduling && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `F046` by migrating selected project comment authorization semantics to kernel evaluation:
- `packages/projects/src/actions/projectTaskCommentActions.ts` now enforces non-internal comment edit/delete access via kernel `own` relationship evaluation on the comment owner record.
- Preserved prior behavior exactly for internal users (retain full edit/delete capability), while non-internal users must satisfy `own` semantics through the shared kernel path.
- This captures the targeted v1 own-comment/internal-user seam under shared authorization contracts.
- (2026-04-21) Validation runbook for `F046` checkpoint:
- `cd packages/projects && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- `cd packages/projects && npx vitest run src/actions/projectPhaseStatusActions.contract.test.ts src/actions/projectPhaseStatusCopyRemove.contract.test.ts --coverage.enabled=false` (known pre-existing contract drift in `projectTaskStatusActions.ts` expectation: missing literal `async function getScopedProjectStatusMappings(`)
- (2026-04-21) Completed `F047` by enabling premium bundle narrowing on selected project list/detail surfaces:
- `packages/projects/src/actions/projectActions.ts` now evaluates `getProjects` and `getProject` through kernel `authorizeResource` with `BundleAuthorizationKernelProvider`.
- Added project record normalization for bundle template matching (`assigned_to`, `client_id`, optional `assigned_team_id`) and per-request subject context resolution (roles/teams/managed users/client).
- Result: published bundle templates for assignment/client/team scope now narrow project visibility on these migrated read paths.
- (2026-04-21) Validation runbook for `F047` checkpoint:
- `cd packages/projects && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `F048` on selected asset read paths by migrating authorization to kernel evaluation:
- `packages/assets/src/actions/assetActions.ts` now evaluates asset access via kernel in `getAsset`, `getAssetDetailBundle`, and `listAssets`.
- Added shared asset authorization subject resolution and asset record normalization from `assets` + `asset_associations` (client/team/assignment hooks).
- (2026-04-21) Completed `F049` by enabling premium bundle narrowing on migrated asset paths:
- Asset kernel calls now include `BundleAuthorizationKernelProvider` with `resolveBundleNarrowingRulesForEvaluation(...)`, allowing published client/team/assignment bundle templates to narrow asset visibility on selected surfaces.
- (2026-04-21) Validation runbook for `F048`-`F049` checkpoint:
- `cd packages/assets && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- `cd packages/assets && npx vitest run tests --coverage.enabled=false` (no matching tests discovered in this package)
- (2026-04-21) Completed `F050` by migrating selected billing (quote) visibility/mutation paths onto kernel checks:
- `packages/billing/src/actions/quoteActions.ts` now authorizes `getQuote` and `listQuotes` through kernel `authorizeResource` (resource `billing:read`) after RBAC.
- `approveQuote` now uses kernel `authorizeMutation` for approval guards before state transition.
- (2026-04-21) Completed `F051` by enabling premium billing bundle narrowing on migrated quote paths:
- Billing quote read/approve kernel calls now include `BundleAuthorizationKernelProvider` with `resolveBundleNarrowingRulesForEvaluation(...)`, enabling client-portfolio style narrowing and bundle mutation constraints.
- (2026-04-21) Completed `F052` by adding billing field-redaction hook application on selected quote surfaces:
- `getQuote` and `listQuotes` now apply kernel `redactedFields` to returned quote payloads without changing base allow/deny semantics.
- (2026-04-21) Validation runbook for `F050`-`F052` checkpoint:
- `cd packages/billing && npx tsc --pretty false --noEmit -p tsconfig.json`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- `cd packages/billing && npx vitest run tests/contractReportActions.revenue.assignmentFact.test.ts tests/contractReportActions.expiration.wiring.test.ts --coverage.enabled=false`
- (2026-04-21) Completed `F053` and `F054` for selected API-key-backed v1 parity read surfaces by moving API authorization to shared kernel decisions:
- Added API helper `server/src/lib/api/controllers/authorizationKernel.ts` for subject normalization and kernel delegation.
- Added `apiKeyId` to API request context (`ApiContext`, `ApiBaseController.authenticate`) so API-key bundle assignments are intersected in authorization subject evaluation.
- Kernelized selected read paths in:
- `server/src/lib/api/controllers/ApiTicketController.ts` (`list`, `getById`)
- `server/src/lib/api/controllers/ApiProjectController.ts` (`list`, `getById`)
- `server/src/lib/api/controllers/ApiQuoteController.ts` (`list`, `getById`)
- These controllers now apply shared-kernel allow/deny checks per record, instead of RBAC-only pass-through.
- (2026-04-21) Completed `F055` by ensuring migrated API/server-action authorization uses shared kernel loading (`getAuthorizationKernel`) so CE remains on builtin-kernel runtime while EE overlays remain edition-gated.
- (2026-04-21) Completed `F056` by adding DB-backed narrowing regression coverage for assignment guards and intersection composition to catch silent broadening on migrated paths.
- (2026-04-21) Completed `T004`, `T005`, `T006`, and `T012` with DB-backed integration coverage in `server/src/test/integration/authorization/bundleAssignmentResolution.integration.test.ts`:
- assignment target validation rejects invalid role/team/user/api_key references
- role+team+user bundle attachments compose as narrowing intersections
- api-key bundle restrictions intersect with impersonated user bundles
- role assignment to published bundle immediately narrows ticket read decisions
- (2026-04-21) Completed `T008` and `T009` using existing kernel guard/intersection unit tests (`server/src/test/unit/authorization/kernel.engine.test.ts`) and reinforced by new integration assertions.
- (2026-04-21) Completed `T030` via existing legacy-direction guard (`server/src/test/unit/authorization/kernel.legacyDirection.test.ts`).
- (2026-04-21) Added API helper unit coverage in `server/src/test/unit/api/authorizationKernel.test.ts` for subject shaping and shared-kernel delegation.
- (2026-04-21) Validation runbook for `F053`-`F056` + tests checkpoint:
- `npx tsc --pretty false --noEmit -p server/tsconfig.json`
- `cd server && npx vitest run --coverage.enabled=false src/test/unit/api/authorizationKernel.test.ts src/test/integration/authorization/bundleAssignmentResolution.integration.test.ts`
- (2026-04-21) Completed `T007` with shared-contract mode tests in `server/src/test/unit/authorization/kernel.contract.modes.test.ts`:
- validates that CE mode (builtin only) and EE-overlay mode (builtin + bundle provider) both expose and execute shared kernel entry points (`authorizeResource`, `resolveScope`, `authorizeMutation`, `explainDecision`).
- (2026-04-21) Additional validation runbook:
- `cd server && npx vitest run --coverage.enabled=false src/test/unit/authorization/kernel.contract.modes.test.ts src/test/unit/api/authorizationKernel.test.ts`
- (2026-04-21) Completed `T029` by extending `server/src/test/unit/authorization/kernel.engine.test.ts` with explicit reason-chain assertions that include RBAC gate (`rbac_allowed`), builtin relationship path (`relationship_rules_allowed`), and bundle narrowing (`bundle_narrowing_applied`).
- (2026-04-21) Note on current integration runner state: repeated full integration reruns encountered transient DB pool exhaustion (`KnexTimeoutError` during test DB recreation). Unit-level checkpoints continue to run reliably; heavy integration reruns should be resumed after DB pool reset.
- (2026-04-21) Completed `T010` with simulator action unit coverage in `server/src/test/unit/authorization/bundleSimulatorAction.test.ts`:
- validates real principal + persisted-record simulation paths (`listAuthorizationSimulationPrincipalsAction`, `listAuthorizationSimulationRecordsAction`, `runAuthorizationBundleSimulationAction`)
- validates synthetic scenario simulation path (no persisted record lookup) against the same draft-vs-published decision flow
- asserts explainability reason chains are emitted for both revisions (for example `rbac:rbac_allowed`, `bundle:bundle_narrowing_applied`, `bundle:bundle_template_denied`)
- (2026-04-21) Fixed simulator action wiring in `ee/server/src/lib/actions/auth/authorizationBundleActions.ts` by restoring in-action record resolution and removing an orphaned trailing record block that had drifted outside any action scope.
- (2026-04-21) Validation runbook for `T010` checkpoint:
- `cd server && npx vitest run --coverage.enabled=false src/test/unit/authorization/bundleSimulatorAction.test.ts`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `T011` with tier/edition guard coverage across EE actions and CE fallback surfaces:
- `server/src/test/unit/authorization/bundleSimulatorAction.test.ts` now asserts non-entitled tier gating blocks EE bundle-management actions before service calls.
- `server/src/test/unit/authorization/kernel.ceFallback.test.ts` verifies CE fallback behavior: when enterprise kernel factory is unavailable, `getAuthorizationKernel()` still runs builtin authorization decisions.
- `server/src/test/unit/authorization/cePolicyManagement.placeholder.test.ts` enforces CE placeholder UI copy includes Premium upgrade guidance while explicitly stating builtin authorization remains active.
- (2026-04-21) Validation runbook for `T011` checkpoint:
- `cd server && npx vitest run --coverage.enabled=false src/test/unit/authorization/bundleSimulatorAction.test.ts src/test/unit/authorization/kernel.ceFallback.test.ts src/test/unit/authorization/cePolicyManagement.placeholder.test.ts`
- `cd .. && npx tsc --pretty false --noEmit -p server/tsconfig.json`
- (2026-04-21) Completed `T013` with ticket authorization narrowing regression coverage in `packages/tickets/src/actions/ticketActions.authorizationNarrowing.test.ts`:
- validates migrated `getTicketsForList` + `getTicketById` preserve baseline client board-narrowing behavior via selected board visibility.
- validates selected-client + selected-board bundle restrictions are enforced on list/detail paths in the migrated ticket authorization flow.
- (2026-04-21) Validation runbook for `T013` checkpoint:
- `cd packages/tickets && npx vitest run src/actions/ticketActions.authorizationNarrowing.test.ts --coverage.enabled=false`
- (2026-04-21) Completed `T014` by extending `packages/tickets/src/actions/ticketActions.authorizationNarrowing.test.ts` with API/UI parity coverage:
- compares migrated UI list scope (`getTicketsForList`) with API helper scope (`authorizeApiResourceRead`) under the same tenant/user/bundle-rule context.
- asserts the same effective allowed ticket IDs for both paths in the selected v1 ticket parity scenario.
- (2026-04-21) Completed `T015` and `T016` with document authorization contract coverage in `packages/documents/tests/documentActions.authorization.contract.test.ts`:
- `T015`: verifies migrated document paths preserve client baseline own/same-client/client-visible semantics while including selected-client bundle narrowing hooks.
- `T016`: verifies document redaction wiring applies `redactedFields` on allowed records without changing allow/deny filtering.
- (2026-04-21) Completed `T017`, `T018`, and `T019` with runtime delegation/approval coverage in `packages/scheduling/tests/timeEntryDelegationAuth.authorization.test.ts`:
- `T017`: validates self, manager, reports-to, and tenant-wide delegation semantics remain intact.
- `T018`: validates premium bundle overlays narrow delegation (for example self-only on read-all users) and do not broaden non-managed access.
- `T019`: validates not-self-approver guard remains enforced in kernelized approval flow.
- (2026-04-21) Completed `T020` with project authorization contract coverage in `packages/projects/src/actions/projectAuthorization.contract.test.ts`:
- preserves own-comment/internal-user behavior in `projectTaskCommentActions.ts` and bundle-aware kernel narrowing on project list/detail in `projectActions.ts`.
- (2026-04-21) Completed `T021` with asset authorization contract coverage in `packages/assets/src/actions/assetAuthorization.contract.test.ts`:
- verifies selected migrated asset surfaces (`getAsset`, `getAssetDetailBundle`, `listAssets`) remain on shared kernel evaluation with bundle narrowing overlays.
- (2026-04-21) Completed `T022` and `T023` with billing quote authorization contract coverage in `packages/billing/tests/quoteAuthorization.contract.test.ts`:
- `T022`: verifies selected quote read/approve paths stay on kernel read/mutation checks with bundle narrowing and self-approver guard.
- `T023`: verifies quote field redaction wiring on allowed records for both detail and list flows.
- (2026-04-21) Completed `T024`, `T025`, and `T027` with EE bundle-management contract coverage in `server/src/test/unit/authorization/bundleManagement.contract.test.ts`:
- `T024`: verifies draft-first editor/publish/assignment flow wiring and explicit revision publishing seam.
- `T025`: verifies resource-section and human-readable summary wiring in both UI and server payloads.
- `T027`: verifies audit trail event model includes bundle/revision/assignment lifecycle metadata and chronological sorting.
- (2026-04-21) Completed `T026` with runtime action guard coverage in `server/src/test/unit/authorization/bundleManagementPermissions.test.ts`:
- verifies create/edit/publish/assignment/simulator actions fail closed when `system_settings` permission is missing and no mutating service call executes.
- (2026-04-21) Completed `T028` with CE migration contract coverage in `server/src/test/unit/authorization/kernel.ceMigratedFlows.contract.test.ts`:
- verifies selected migrated ticket/document/time/project/asset/billing paths continue to wire through shared builtin kernel entry points.
- (2026-04-21) Validation runbook for `T015`-`T028` checkpoint:
- `cd packages/documents && npx vitest run tests/documentActions.authorization.contract.test.ts --coverage.enabled=false`
- `cd packages/scheduling && npx vitest run tests/timeEntryDelegationAuth.authorization.test.ts --coverage.enabled=false`
- `cd packages/projects && npx vitest run src/actions/projectAuthorization.contract.test.ts --coverage.enabled=false`
- `cd packages/assets && npx vitest run src/actions/assetAuthorization.contract.test.ts --coverage.enabled=false`
- `cd packages/billing && npx vitest run tests/quoteAuthorization.contract.test.ts --coverage.enabled=false`
- `cd server && npx vitest run src/test/unit/authorization/bundleManagement.contract.test.ts src/test/unit/authorization/kernel.ceMigratedFlows.contract.test.ts src/test/unit/authorization/bundleManagementPermissions.test.ts --coverage.enabled=false`