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

14 KiB
Raw Permalink Blame History

Scratchpad — Premium ABAC Follow-up Remediation

  • Plan slug: premium-abac-remediation
  • Created: 2026-04-22

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-22) This is a follow-up remediation plan for ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/, not a replacement for it.
  • (2026-04-22) Scope is limited to defects identified during review of the first implementation session.
  • (2026-04-22) Remediation should be surgical where possible and should preserve the architecture and product decisions from the original plan.
  • (2026-04-22) The most urgent fixes are draft/publish integrity, selected-rule fidelity, starter-bundle publish behavior, time resource-key alignment, simulator fidelity, and API pagination semantics.
  • (2026-04-22) F001 implemented by adding explicit remediation-to-original feature/test mapping to this plan PRD; this follow-up now has auditable traceability to original plan IDs.

Discoveries / Constraints

  • (2026-04-22) getAuthorizationBundleDraftEditorAction currently requires only read permission but calls ensureDraftBundleRevision(...), which creates draft state as a side effect.
  • (2026-04-22) upsertBundleRule(...) and deleteBundleRule(...) are currently not scoped tightly enough to the active draft revision, which weakens draft/publish isolation.
  • (2026-04-22) Runtime relationship evaluation for selected_clients and selected_boards depends on evaluation input fields, but the stored rule config is not fully propagated into bundle-rule evaluation objects.
  • (2026-04-22) Starter bundle seeding currently creates bundle rules without publishing the initial revision, leaving seeded bundles inert.
  • (2026-04-22) Migrated Time UI/catalog uses time_entry while selected time/delegation kernel calls currently use timesheet.
  • (2026-04-22) API list controllers for tickets, projects, and quotes paginate in the service layer first, then narrow in memory, then report filtered-page counts as totals.
  • (2026-04-22) Simulator fidelity is weakened by billing-record mismatch and by simulator kernel construction that does not mirror all builtin resource-specific invariants used in real runtime paths.
  • (2026-04-22) server package tests run directly via cd server && npx vitest run ...; root npm run test:local -- ... currently fails because its dotenv invocation expects a different CLI syntax.
  • (2026-04-22) Control-plane schema allows authorization_bundle_rules.bundle_id to drift from the referenced revisions bundle_id because rule rows currently only foreign-key revision by (tenant, revision_id).
  • (2026-04-22) Runtime rule mapping loaded constraints/redactedFields from rule config but did not load selectedClientIds or selectedBoardIds, so selected template rules could evaluate against missing IDs.
  • (2026-04-22) seedStarterAuthorizationBundlesAction created starter bundle draft revisions/rules but never published them, so seeded bundles were assignable yet inert.
  • (2026-04-22) Time delegation/approval kernelization used resource type timesheet for bundle evaluation while the bundle editor/catalog and starter rules target time_entry.
  • (2026-04-22) Simulator billing record lookup/listing used invoices, but migrated billing API authorization evaluates billing over quote records (quotes).
  • (2026-04-22) Simulator previously evaluated all actions via authorizeResource, so approve-path mutation guards (for billing/time self-approval) were not represented.
  • (2026-04-22) Simulator previously allowed non-read action modes (create/update/delete) without mutation context, which could imply unsupported fidelity.
  • (2026-04-22) API authorization subject shaping only mapped client_id and ignored camelCase client ID payloads and portfolio client ID arrays.
  • (2026-04-22) Ticket/project/quote API list controllers paginated service results before authorization narrowing, which stranded authorized records and reported filtered-page counts as totals.

Commands / Runbooks

  • (2026-04-22) Inspect original plan scratchpad and feature/test references: read ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/SCRATCHPAD.md
  • (2026-04-22) Review committed implementation history on this branch: git log --oneline --decorate --reverse --ancestry-path $(git merge-base HEAD origin/main)..HEAD
  • (2026-04-22) Review changed files in the premium-ABAC rollout: git diff --stat $(git merge-base HEAD origin/main)..HEAD
  • (2026-04-22) Spot-check known hot files:
    • server/src/lib/authorization/bundles/service.ts
    • ee/server/src/lib/actions/auth/authorizationBundleActions.ts
    • server/src/lib/authorization/kernel/providers/bundleProvider.ts
    • packages/scheduling/src/actions/timeEntryDelegationAuth.ts
    • server/src/lib/api/controllers/Api{Ticket,Project,Quote}Controller.ts
  • Original plan:
    • ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/PRD.md
    • ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/features.json
    • ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/tests.json
    • ee/docs/plans/2026-04-21-premium-abac-authorization-kernel/SCRATCHPAD.md
  • Key implementation files:
    • server/src/lib/authorization/bundles/service.ts
    • server/src/lib/authorization/kernel/providers/bundleProvider.ts
    • server/src/lib/authorization/kernel/relationships.ts
    • ee/server/src/lib/actions/auth/authorizationBundleActions.ts
    • packages/scheduling/src/actions/timeEntryDelegationAuth.ts
    • server/src/lib/api/controllers/authorizationKernel.ts
    • server/src/lib/api/controllers/ApiTicketController.ts
    • server/src/lib/api/controllers/ApiProjectController.ts
    • server/src/lib/api/controllers/ApiQuoteController.ts
    • server/migrations/20260421190000_create_authorization_bundle_control_plane.cjs

Open Questions

  • Should this follow-up fully solve post-authorization pagination totals, or only make pagination semantics honest and fail-safe for now?
  • Should simulator fidelity in this follow-up be broadened by modeling builtin resource rules per resource family, or narrowed by explicitly refusing unsupported scenario types?

Progress Log

  • (2026-04-22) Completed F001:
    • Added a new Traceability Mapping section in PRD.md that maps each remediation feature cluster to original-plan feature/test IDs.
    • Purpose: satisfy follow-up-plan auditability and make remediation-to-original linkage explicit in the source-of-truth artifact.
  • (2026-04-22) Completed F002:
    • Updated getAuthorizationBundleDraftEditorAction to check system_settings:write capability.
    • Write-capable users keep existing behavior (ensureDraftBundleRevision), while read-only users load an existing draft or published revision without creating draft state.
    • Added explicit summary text for read-only fallback when no active draft exists.
  • (2026-04-22) Completed F003:
    • Hardened upsertBundleRule to require a draft revision scoped by tenant + bundle + revision.
    • Rule updates now also require tenant + bundle + revision + rule match and fail closed when no matching draft rule exists.
  • (2026-04-22) Completed F004:
    • Hardened deleteBundleRule to require tenant + bundle + revision + rule match.
    • Delete now fails closed when the rule is not in the expected draft revision scope.
  • (2026-04-22) Verification for F002-F004:
    • Command: cd server && npx vitest run src/test/unit/authorization/bundleManagementPermissions.test.ts
    • Result: pass.
  • (2026-04-22) Completed F005:
    • Added migration server/migrations/20260422113000_enforce_authorization_rule_revision_bundle_integrity.cjs.
    • Enforced unique key on authorization_bundle_revisions (tenant, bundle_id, revision_id) and moved rules FK to (tenant, bundle_id, revision_id).
    • Result: a rule can no longer reference a revision from a different bundle.
  • (2026-04-22) Verification for F005:
    • Command: cd server && npx vitest run src/test/unit/migrations/authorizationBundleControlPlaneMigration.test.ts
    • Result: pass.
  • (2026-04-22) Completed F006:
    • Added selected-client ID normalization/loading from rule config in runtime rule resolution and simulator rule normalization.
    • Supports both camelCase (selectedClientIds) and snake_case (selected_client_ids) config keys.
  • (2026-04-22) Completed F007:
    • Added selected-board ID normalization/loading from rule config in runtime rule resolution and simulator rule normalization.
    • Supports both camelCase (selectedBoardIds) and snake_case (selected_board_ids) config keys.
  • (2026-04-22) Completed F008:
    • Extended bundle-provider rule type with selectedClientIds/selectedBoardIds.
    • Updated template evaluation so selected_clients and selected_boards use rule-scoped configured IDs during decisioning instead of relying on ad hoc caller input.
  • (2026-04-22) Verification for F006-F008:
    • Command: cd server && npx vitest run src/test/unit/authorization/bundle.provider.test.ts
    • Result: pass.
  • (2026-04-22) Completed F009:
    • Starter seeding now publishes each created starter bundle revision immediately after inserting starter rules.
    • Kept publish inside the existing transaction flow by widening publishBundleRevision to accept Knex | Knex.Transaction.
  • (2026-04-22) Verification for F009:
    • Command: cd server && npx vitest run src/test/unit/authorization/starterBundles.test.ts
    • Result: pass.
    • Command: cd server && npx vitest run src/test/unit/authorization/bundleManagementPermissions.test.ts
    • Result: test pass but process ended with coverage cleanup error (ENOENT .../coverage/.tmp).
  • (2026-04-22) Completed F010:
    • Updated time delegation/approval kernel evaluations in timeEntryDelegationAuth.ts to use resource type time_entry for bundle decisions.
    • Updated scheduling authorization regression test bundle-rule fixtures to match time_entry.
  • (2026-04-22) Verification for F010:
    • Command: cd server && npx vitest run ../packages/scheduling/tests/timeEntryDelegationAuth.authorization.test.ts
    • Result: pass.
  • (2026-04-22) Completed F011:
    • Updated simulator billing record reference data and persisted-record loading from invoices to quotes.
    • Updated authorization-record normalization to include quote_id.
  • (2026-04-22) Completed F012:
    • Added simulator parity for mutation-guard invariants on approve actions by using authorizeMutation with not-self-approver guards for billing and time_entry.
    • Added simulator-side document client-visibility narrowing for client principals to mirror runtime deny behavior.
    • Added managed-user lookup to simulation subject shaping for closer runtime parity.
  • (2026-04-22) Completed F013:
    • Added explicit simulator support gating: only read/approve actions are allowed in this follow-up; unsupported modes fail closed with clear errors.
    • Added explicit refusal for ticket simulation with client principals until board-visibility builtin invariants are modeled.
  • (2026-04-22) Verification for F011-F013 and F023:
    • Command: cd server && npx vitest run src/test/unit/authorization/bundleSimulatorAction.test.ts
    • Result: pass.
  • (2026-04-22) Completed T009, T010 and F023:
    • Extended bundleSimulatorAction.test.ts to verify quote-backed billing simulation records and approve self-approval guard behavior.
    • Added regression coverage for supported-mode fidelity and explicit unsupported-mode rejection semantics.
  • (2026-04-22) Completed F014:
    • Extended API authorization subject normalization to support client_id/clientId and portfolio_client_ids/portfolioClientIds.
    • Subject shaping now preserves client/portfolio scope IDs across API user payload variants.
  • (2026-04-22) Completed F015, F016, F017, F018:
    • Added authorizationAwarePagination helper that scans source pages, applies authorization first, and paginates authorized rows afterward.
    • Updated ApiTicketController, ApiProjectController, and ApiQuoteController list paths to use authorization-aware pagination totals.
    • Remediation remains fail-closed: only authorized rows contribute to response data/totals.
  • (2026-04-22) Completed T011:
    • Added API authorization subject unit coverage for snake_case and camelCase client/portfolio identifiers.
  • (2026-04-22) Completed T012, T013, T014 and F024:
    • Added authorizationAwarePagination.test.ts with ticket/project/quote scenarios proving no authorized rows are stranded behind filtered source pages.
    • Coverage asserts coherent authorized totals after narrowing.
  • (2026-04-22) Verification for F014-F018, T011-T014:
    • Command: cd server && npx vitest run src/test/unit/authorization/bundleSimulatorAction.test.ts src/test/unit/api/authorizationKernel.test.ts src/test/unit/api/authorizationAwarePagination.test.ts
    • Result: pass.
  • (2026-04-22) Completed T001, T002, T003 and F019:
    • Verified bundle-management permission and draft-revision scoping regressions remain covered in bundleManagementPermissions.test.ts.
  • (2026-04-22) Completed T004:
    • Verified migration-level revision/bundle integrity constraints in authorizationBundleControlPlaneMigration.test.ts.
  • (2026-04-22) Completed T005, T006 and F020:
    • Verified runtime selected-client and selected-board evaluation coverage in bundle.provider.test.ts.
  • (2026-04-22) Completed T007 and F021:
    • Verified starter-bundle publish-backed enforceability in starterBundles.test.ts.
  • (2026-04-22) Completed T008 and F022:
    • Verified time delegation authorization path alignment to time_entry in timeEntryDelegationAuth.authorization.test.ts.
  • (2026-04-22) Verification for T001-T008, F019-F022:
    • Command: cd server && npx vitest run src/test/unit/authorization/bundleManagementPermissions.test.ts src/test/unit/migrations/authorizationBundleControlPlaneMigration.test.ts src/test/unit/authorization/bundle.provider.test.ts src/test/unit/authorization/starterBundles.test.ts ../packages/scheduling/tests/timeEntryDelegationAuth.authorization.test.ts
    • Result: pass.