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

15 KiB

NX Monorepo Modularization - Scratchpad


⚠️ CRITICAL INSTRUCTION FOR CLAUDE ⚠️

DO NOT CHEAT. When implementing features:

  1. Work in large chunks before lint/build. Prefer moving a whole coherent slice (e.g. an entire folder or feature) and fixing imports broadly. Only run lint/tests/build at the end of a large unit of work (or when truly blocked). Constant lint/build cycles are too expensive and slow the migration dramatically.
  2. Actually move/copy the files - don't just create re-exports from the old location
  3. Update imports in the moved files - fix relative imports to work in new location
  4. Update consumers - change imports in files that use the moved code
  5. If you defer work, add a NEW feature entry to features.json for that deferred work
  6. Only mark "implemented": true when the actual migration is complete, not just scaffolding

If you have the choice between an easy path (re-exports) and the right path (actual migration), ALWAYS choose the right path. If you need to defer harder work to later iterations, add explicit new features to track that work - don't just drop it or pretend it's done.

Temporary Shim Exception (Migration Only)

If a “shim” is required to keep work moving (e.g. to avoid editing dozens of call sites immediately), it must be:

  • treated as temporary and minimal (no long-lived architecture)
  • tracked explicitly in features.json (with a removal task)
  • removed once the owning package/horizontal slice has the real implementation

Analysis Summary (2026-01-15)

Current Codebase Metrics

  • Total TypeScript/TSX files: ~2,300+
  • Components: 777 files across 42 domain directories
  • Lib (actions, models, services, utils): 685 files
  • API Routes: 510 files
  • Interfaces: 52 files

Existing Modular Patterns

The codebase already uses npm workspaces with this structure:

"workspaces": [
  "server",
  "ee/server",
  "services/workflow-worker",
  "services/email-service",
  "shared",
  "packages/*",
  "sdk/*"
]

Existing Packages (15 total)

Located in /packages/:

  1. product-auth-ee - Enterprise auth
  2. product-billing - Billing features
  3. product-chat - Chat functionality
  4. product-client-portal-domain - Client portal domain logic
  5. product-email-domains - Email domain management (consolidated into @alga-psa/integrations/email)
  6. product-email-providers - Email provider integrations (consolidated into @alga-psa/integrations/email)
  7. product-email-settings - Email configuration (consolidated into @alga-psa/integrations/email)
  8. product-ext-proxy - Extension proxy
  9. product-extension-actions - Extension server actions
  10. product-extension-initialization - Extension init
  11. product-extensions-pages - Extension pages
  12. product-extensions - Core extensions
  13. product-settings-extensions - Settings extensions
  14. product-workflows - Workflow engine
  15. ui-kit - UI component library

Shared Library Structure

@alga-psa/shared exports:

  • ./types - Type definitions
  • ./core - Logger, secret provider
  • ./db - Database utilities, admin, connection
  • ./events/publisher.js - Event publishing
  • ./utils/encryption.js - Encryption utilities
  • ./workflow - Workflow core, persistence, streams
  • ./models/* - Shared models (client, contact, tag, ticket, user)
  • ./extensions/* - Extension domain, installs, types

Identified Feature Domains

Large Domains (>30 component files)

Domain Files Notes
billing-dashboard 120 Invoices, contracts, payments, credits
settings 86 System configuration
ui 81 Shared UI components
projects 50 Project management, kanban, tasks
client-portal 42 Client-facing portal
assets 37 Asset management
time-management 32 Time tracking, timesheets
clients 32 Client profiles

Medium Domains (10-30 files)

  • surveys (25), workflows (24), user-activities (21)
  • tickets (19), documents (18), contacts (12)
  • technician-dispatch (13), auth (12), layout (11)
  • integrations (11)

Proposed Module Architecture

Horizontal Slices (Shared Infrastructure)

  1. @alga-psa/core - Existing shared package, enhance with:

    • Logger, config, secrets
    • Event publisher
    • Encryption utilities
  2. @alga-psa/db - Database layer

    • Knex configuration
    • Tenant context management
    • Connection pooling
    • Base model patterns
  3. @alga-psa/types - Type definitions

    • All interface files
    • Shared types across features
  4. @alga-psa/validation - Validation logic

    • Zod schemas
    • Form validation utilities
    • Business rule validators
  5. @alga-psa/ui - UI component library

    • Enhance existing ui-kit
    • All shared UI components
  6. @alga-psa/auth - Authentication

    • Auth strategies
    • Session management
    • Permission utilities

Vertical Slices (Feature Modules)

  1. @alga-psa/billing - Billing & Contracts

    • Invoicing
    • Contracts/contract lines
    • Payments
    • Credits
    • Tax management
  2. @alga-psa/clients - Client Management

    • Client profiles
    • Contacts
    • Companies
    • Client relationships
  3. @alga-psa/projects - Project Management

    • Projects
    • Tasks/phases
    • Kanban boards
    • Dependencies
    • Resource allocation
  4. @alga-psa/tickets - Ticket/Issue Tracking

    • Support tickets
    • Categories
    • SLA management
  5. @alga-psa/scheduling - Scheduling & Time

    • Time tracking
    • Timesheets
    • Calendar
    • Technician dispatch
    • Schedule entries
  6. @alga-psa/workflows - Workflow Automation

    • Workflow engine
    • Triggers
    • Actions
    • Automation rules
  7. @alga-psa/documents - Document Management

    • Document storage
    • Templates
    • Sharing
  8. @alga-psa/assets - Asset Management

    • Asset tracking
    • Categorization
    • Service history
  9. @alga-psa/surveys - Surveys

    • Survey creation
    • Responses
    • Analytics
  10. @alga-psa/integrations - Third-party Integrations

    • QuickBooks
    • Email providers
    • Calendar providers
    • Webhooks
  11. @alga-psa/client-portal - Client Portal

    • Portal UI
    • Portal-specific features
    • External access

Key Decisions

Decision 1: NX vs Enhanced npm Workspaces

Decision: Use NX Rationale:

  • Existing npm workspaces show modular thinking is established

Note: Vitest + Workspace Resolution (2026-01-15)

Some dev/test setups may not have newly-added @alga-psa/* workspace packages linked into node_modules. For Vitest runs from the repo root, add explicit Vite/Vitest aliases (in server/vitest.config.ts) pointing @alga-psa/* imports to packages/*/src to keep unit tests runnable without reinstalling dependencies.

Note: Root tsconfig.json (2026-01-15)

Several packages/*/tsconfig.json files extend ../../tsconfig.json. Ensure tsconfig.json exists at the repo root and extends tsconfig.base.json so those package configs work and editors/tools pick up the shared path aliases.

Note: DB tenant context (2026-01-15)

The @alga-psa/db package now owns tenant context via AsyncLocalStorage (runWithTenant, getTenantContext) and exports createTenantKnex(). The server-side server/src/lib/db/index.tsx continues to handle request/session/header tenant resolution but delegates context storage to @alga-psa/db.

Note: Vitest coverage temp dir (2026-01-15)

Vitest v8 coverage writes a temp directory under server/coverage/.tmp. Ensure it exists during test runs (created in server/src/test/setup.ts) to avoid occasional ENOENT errors when running multiple targeted tests.

Note: Nx project.json coverage (2026-01-15)

Many packages/* were created without project.json, which prevented them from being first-class Nx projects. Added project.json files for all new @alga-psa/* packages (and packages/ui-kit) so nx graph, caching, and affected commands can reason about them.

  • NX adds: computation caching, affected commands, dependency graph visualization
  • Better for large codebase with 2300+ files
  • Enables parallel builds and test optimization

Note: UI package split (2026-01-16)

The existing packages/ui-kit is used by SDK/extension template consumers and should remain Tailwind-free to avoid breaking external usage. The app/server UI components from server/src/components/ui (Tailwind + Radix heavy) were migrated into a new internal package packages/ui (@alga-psa/ui), and server consumers were updated to import from @alga-psa/ui.

Decision 2: Module Boundaries

Decision: Feature-based vertical slices over layer-based Rationale:

  • Aligns with existing component organization
  • Enables independent deployment/testing
  • Clear ownership boundaries
  • Reduces cross-team conflicts

Decision 3: Next.js Routes Location

Decision: Keep all routes in single server/ project Rationale:

  • Next.js requirement - App Router needs single entry
  • Routes become thin shims calling into feature modules
  • API routes can delegate to feature modules

Decision 4: Migration Strategy

Decision: Incremental, bottom-up Rationale:

  • Start with horizontal slices (already partially exist in shared/)
  • Add vertical slices one feature at a time
  • Maintain backwards compatibility during migration
  • Can deploy incrementally

Technical Constraints

  1. Next.js App Router: All routes must remain in single project
  2. CitusDB: Tenant column requirements affect data layer design
  3. Enterprise Edition: CE/EE code separation must be maintained
  4. Existing Workspaces: Must migrate, not break existing package structure

Commands & References

Useful Commands

# Current workspace structure
npm ls --workspaces

# Check package dependencies
npm -w server ls

# Run tests for specific workspace
npm -w server test

Key File Paths

  • Root package.json: /package.json
  • Server package.json: /server/package.json
  • Shared exports: /shared/package.json
  • Coding standards: /docs/AI_coding_standards.md

Open Questions

  1. Billing + Contracts: Should these be one module or separate?

    • Current thinking: Combined as @alga-psa/billing (they're tightly coupled)
  2. Email modules: Consolidated into @alga-psa/integrations/email (formerly product-email-domains, product-email-providers, product-email-settings).

  3. Extension packages: 7 extension-related packages - keep as-is or consolidate?

  4. UI components: Current ui-kit is minimal - expand or keep ui in each feature?

    • Recommendation: Expand ui-kit as @alga-psa/ui for all shared components

Migration Order (Proposed)

Phase 1: Foundation

  1. Initialize NX workspace
  2. Migrate shared/ to @alga-psa/core, @alga-psa/db, @alga-psa/types
  3. Create @alga-psa/validation from existing validation utilities
  4. Expand ui-kit to @alga-psa/ui

Phase 2: Infrastructure Features

  1. Create @alga-psa/auth from auth actions/lib
  2. Create @alga-psa/integrations (consolidate email packages + integrations)

Phase 3: Core Business Features

  1. Create @alga-psa/clients (clients + contacts)
  2. Create @alga-psa/billing (invoicing + contracts)
  3. Create @alga-psa/projects
  4. Create @alga-psa/tickets

Phase 4: Supporting Features

  1. Create @alga-psa/scheduling (time + dispatch + calendar)
  2. Create @alga-psa/workflows
  3. Create @alga-psa/documents
  4. Create @alga-psa/assets
  5. Create @alga-psa/surveys
  6. Create @alga-psa/client-portal

Phase 5: Optimization

  1. Configure NX caching
  2. Set up affected commands for CI
  3. Optimize build pipeline

Implementation Notes (2026-01-16)

  • @alga-psa/types interface migration: synced server/src/interfaces into packages/types/src/interfaces, removed duplicate/stub interface files that caused resolution ambiguity, fixed self-imports inside the types package, and added tests to validate the barrel exports. Inbound email types are exported under Inbound* aliases to avoid name collisions with outbound email types.
  • NX graph/tests: NX_DAEMON=false avoids the earlier nx command hangs; added an integration test at tools/nx-tests/nxWorkspace.test.ts to validate nx show projects, nx graph --file, and generator dry-run.
  • Module boundaries: added ESLint rule custom-rules/no-feature-to-feature-imports to prevent packages/<feature> vertical packages from importing other vertical packages via @alga-psa/* (validated in tools/nx-tests/moduleBoundaries.test.ts). nx lint is currently too memory-hungry (heap OOM) to use as an enforcement test in this environment.
  • npm workspace protocol: removed workspace:* dependency specifiers from packages/*/package.json (replaced with *) because npm cannot install/update dependencies when workspace: protocol is used.
  • NX caching + affected: added npm run test:nx (vitest config for tools/nx-tests) including a cache verification test (nxCache.test.ts) and an affected-project selection test (nxAffected.test.ts); added npm run affected:test and npm run affected:build scripts; updated .github/workflows/typecheck.yml to run nx affected -t build/test.
  • @alga-psa/clients vertical slice: migrated client/contacts actions + components into packages/clients and updated the /msp/clients + /msp/contacts routes to import from @alga-psa/clients (and actions from @alga-psa/clients/actions); server npm run build passes after import rewiring.
  • Tax + client type alignment: resolved an ITaxRate export collision by selectively exporting tax interfaces from @alga-psa/types (including ITaxRateDetails alias). Also aligned client/contacts typing by using @alga-psa/types in key action/components and allowing client.properties to be nullable where DB can return null.

Implementation Notes (2026-01-18)

server/src import cleanup (packages)

  • Verified no remaining from 'server/src' or import('server/src/...') usages under packages/**.

Documents storage self-containment

  • Added missing documents storage primitives under packages/documents/src/:
    • config/storage.ts (env/secret-driven storage config + validation)
    • types/storage.ts (provider + file store types)
    • models/storage.ts (FileStoreModel without BaseModel; tenant resolved via requireTenantId)
  • Rewired documents storage imports to stay within packages/documents/src/** (avoids importing files outside the package src/ root).
  • Removed @alga-psa/users/actions dependency from documents storage to avoid pulling incomplete user avatar utilities into core storage logic.

Business-logic tests added

  • Scheduling: packages/scheduling/tests/timePeriodSuggester.test.ts (run npm -w packages/scheduling test)
  • Documents: packages/documents/tests/storageConfig.test.ts (run npm -w packages/documents test)
  • Auth: adjusted packages/auth/src/lib/exports.test.ts to validate RBAC behavior via the subpath export @alga-psa/auth/rbac (keeps the test focused and avoids pulling Next.js UI modules).

Known tooling limitation (out of scope here)

  • tsc --noEmit in many packages currently fails with rootDir/project-reference issues when TypeScript path aliases pull in other package sources (example: importing @alga-psa/tenancy/actions from another package). Unit tests via Vitest are still runnable and used for verification.