# Scratchpad — Modular Dependency Slices (Billing ↔ Clients) - Plan folder: `ee/docs/plans/2026-01-20-modularity-dependency-slices/` - Date started: `2026-01-20` ## Current State (Discovery) - There is an active effort to break a circular dependency between `@alga-psa/billing` and `@alga-psa/clients`. - Temporary mitigation already introduced: dynamic import wrappers in billing: - `packages/billing/src/lib/clientsHelpers.ts` - Used by billing backend (e.g. `packages/billing/src/services/invoiceService.ts`) and billing UI (e.g. `packages/billing/src/components/billing-dashboard/BillingCycles.tsx`). - There is also a clients→billing dynamic import: - `packages/clients/src/actions/clientContractActions.ts` dynamically imports `@alga-psa/billing/models/contract` to call `checkAndReactivateExpiredContract(...)`. ## Goal Replace dynamic-import “escape hatches” with a new shared slice so dependencies flow down: - `billing` → `shared-cross-slice` - `clients` → `shared-cross-slice` - No `billing` ↔ `clients` imports. ## Candidate “Cross Slice” Responsibilities - Client contract assignment APIs (create/update/get/list) currently in clients but used by billing screens. - Client lookup APIs used by billing screens (paginated + billing-cycle-range filtered). - Default client tax region lookup currently in clients but used by billing invoice generation. - Contract reactivation logic currently in billing contract model but invoked from clients. ## Decisions (Pending) ### Confirmed - “Cross-dependencies” live in the existing lower slice `@alga-psa/shared` (not a new domain package). - Move `ClientPicker` into `@alga-psa/ui` as part of this effort. - Keep “default client tax region lookup” in `@alga-psa/shared` for now (no separate tax slice in this scope). - Move contract reactivation-on-assignment-update logic into `@alga-psa/shared` so no billing import is needed from clients/shared. - Pragmatic rule: limited *copying* of code is allowed to break dependencies without exploding package boundaries; if the same logic is copied >4 times, centralize it. ### Still open - Exact `@alga-psa/shared` export/module path for these APIs (chosen: `@alga-psa/shared/billingClients`). ## Notes / Commands - Find remaining billing imports of clients: `rg -n \"@alga-psa/clients\" packages/billing/src` - Find remaining clients imports of billing: `rg -n \"@alga-psa/billing\" packages/clients/src` - Existing plan folder format example: `ee/docs/plans/2026-01-09-billing-cycle-anchors/` - Some code duplication and intentional copying is permissible if it simplifies modularization. We should be pragmatic! ## Scope Adjustment (2026-01-20) - Validation focus: **build/typecheck checks only** to ensure deterministic builds and a clean dependency graph. Comprehensive new business-logic tests are intentionally deferred for this effort. ## Build Gotcha (2026-01-20) - `npm run build` was failing in `server/src/invoice-templates/assemblyscript` because the installed `assemblyscript@0.27.36` package was missing its `dist/` folder (so `bin/asc.js` could not import `../dist/asc.js`). - Fix: pin `assemblyscript` to the local tarball `assemblyscript-0.27.36.tgz` and run `npm install` with a repo-local cache (`--cache ../../../../.npm-cache`) to avoid global npm cache permission issues. ## Nx Cycle Follow-up (2026-01-20) - `nx run-many -t build` revealed an additional cycle: `auth -> ui -> onboarding -> licensing -> auth`. - Root cause: `@alga-psa/ui` contained onboarding-specific UI (wizard + dashboard onboarding widgets) and imported `@alga-psa/onboarding`. - Fix: move onboarding-specific UI into `@alga-psa/onboarding` and keep `@alga-psa/ui` limited to shared UI primitives (wizard chrome, shared components). - Also moved the onboarding wizard data shape (`WizardData`, etc.) down into `@alga-psa/types` to avoid `tenancy <-> onboarding` cycles. ## Nx Cycle Follow-up — UI Vertical Imports (2026-01-20) - Additional cycle observed: `... -> auth -> ui -> tenancy -> client-portal -> clients -> ui`. - Root cause: `@alga-psa/ui` contains multiple “feature” components that import vertical slice actions/components, including: - `@alga-psa/tenancy/actions` (branding + locale + tenant settings UIs) - `@alga-psa/users/actions` (user settings/profile/admin UIs; mentions search in editor; notification dropdown user lookup) - `@alga-psa/clients/actions` and `@alga-psa/clients/components` (settings and activity UIs) - `@alga-psa/client-portal/*` (domain settings entry, invitation flows) - Fix strategy: move those “feature” components out of `@alga-psa/ui` into the owning vertical slice (e.g. `users`, `tenancy`, `client-portal`) or into top-level app (`server`), leaving `@alga-psa/ui` as pure, reusable UI primitives only. ## Nx Tooling Note (2026-01-20) - On this worktree, `npx nx ...` frequently hangs while “Calculating the project graph on the Nx Daemon” under `node v25.1.0`, and `NX_DAEMON=false` can fail with `Failed to start plugin worker.`. - Mitigation: the repo now pins Node to a supported range via `.nvmrc` (`20`) and root `package.json` `engines` (`>=20 <25`). - Validation for this effort therefore relies on: - package typechecks (`tsc --noEmit`) for touched packages, and - import-greps confirming the key layering breaks (e.g. no `@alga-psa/ui` imports of `@alga-psa/tenancy|users|clients|client-portal`). ## Build Fixes (2026-01-20) - Added CE stub component for EE policy settings so `server:build` can typecheck: - `server/src/empty/components/settings/policy/PolicyManagement.tsx` - Fixed CE build typing for Temporal runner factory: - `server/src/lib/jobs/JobRunnerFactory.ts` casts the dynamically-imported `TemporalJobRunner` to `IJobRunner` (CE stubs don’t structurally match the server interface). - Made Nx build fully offline-friendly by avoiding networked installs during sample component builds: - `sdk/samples/component/secrets-demo/package.json` uses `alga build --skip-install`. - Fixed `workflow-worker:build` in CE by resolving `@ee/*` imports to the `@alga-psa/ee-stubs` sources instead of `server/src/empty`: - `services/workflow-worker/tsconfig.json` maps `@ee/*` → `packages/ee/src/*`.