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

200 lines
22 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 — Workflow Time Actions
- Plan slug: `2026-04-27-workflow-time-actions`
- Created: `2026-04-27`
## What This Is
Rolling notes for adding workflow-safe time-entry, time-sheet, and billing-readiness actions to the workflow action registry.
## Decisions
- (2026-04-27) Scope option selected: core time entry actions, core time sheet actions, and readiness helpers. Timers and broad picker expansion can be deferred unless required by core flows.
- (2026-04-27) Implementation approach selected: create workflow-safe helpers/services that preserve canonical time module behavior, then build workflow actions on top of those helpers. Do not continue direct DB writes that bypass time-entry business logic.
- (2026-04-27) Existing `time.create_entry` should be treated as incomplete/prototype behavior and brought onto the canonical helper path rather than expanded as-is.
- (2026-04-27) Picker scope decision (`F028`): keep phase-1 fixed picker expansion minimal to currently supported infrastructure (user/ticket + textarea metadata). Service/contract/time-entry/time-sheet/time-period dedicated fixed pickers are explicitly deferred; schema descriptions and dynamic-reference support remain the fallback for those IDs.
## Discoveries / Constraints
- (2026-04-27) Current workflow action file: `shared/workflow/runtime/actions/businessOperations/time.ts`.
- (2026-04-27) Existing `time.create_entry` directly inserts into `time_entries`, uses `billing_plan_id`, computes `work_date` from UTC, and does not attach to a time sheet or resolve `service_id`/`contract_line_id` behavior.
- (2026-04-27) Canonical scheduling behavior lives primarily in `packages/scheduling/src/actions/timeEntryCrudActions.ts`, `timeSheetOperations.ts`, and `timeSheetActions.ts`.
- (2026-04-27) Important canonical side effects include `service_id` validation, user timezone work-date computation, time-sheet period validation, default contract line resolution, bucket usage updates, project-task actual-hours updates, ticket/task resource updates, invoiced-entry guards, and change-request handling.
- (2026-04-27) API time-entry service exists at `server/src/lib/api/services/TimeEntryService.ts`, but it has its own behavior and should not be blindly treated as the canonical source without reconciliation.
- (2026-04-27) Workflow fixed pickers currently support board, client, contact, user, user-or-team, ticket, ticket-status, ticket-priority, ticket-category, ticket-subcategory, and client-location. They do not currently support service catalog, contract line, time entry, time sheet, time period, project task, interaction, or non-billable category resources.
- (2026-04-27) Event schemas for `TIME_ENTRY_SUBMITTED` and `TIME_ENTRY_APPROVED` exist in `shared/workflow/runtime/schemas/timeEventSchemas.ts`, but current workflow-trigger publication appears limited; ticket time entry added publication is handled by `server/src/lib/api/services/timeEntryWorkflowEvents.ts`.
- (2026-04-27) `packages/scheduling/src/services/bucketUsageService.ts` requires tenant inference via `createTenantKnex()` when transaction config does not carry tenant metadata; workflow runtime already has explicit tenant context, so directly calling that service from workflow helper would be fragile in shared Vitest DB tests.
## Commands / Runbooks
- (2026-04-27) Initial investigation used `rg` across `server`, `shared`, `packages`, and `ee` for `time_entries`, `time_sheets`, `time.create_entry`, and workflow picker support.
- (2026-04-27) Validate plan JSON after edits: `python scripts/validate_plan.py ee/docs/plans/2026-04-27-workflow-time-actions` if the validator supports folder input; otherwise run project JSON validation or `python -m json.tool` on each JSON file.
## Links / References
- `shared/workflow/runtime/actions/businessOperations/time.ts`
- `shared/workflow/runtime/actions/registerBusinessOperationsActions.ts`
- `shared/workflow/runtime/designer/actionCatalog.ts`
- `shared/workflow/runtime/jsonSchemaMetadata.ts`
- `packages/scheduling/src/actions/timeEntryCrudActions.ts`
- `packages/scheduling/src/actions/timeSheetOperations.ts`
- `packages/scheduling/src/actions/timeSheetActions.ts`
- `packages/scheduling/src/actions/timeEntryServices.ts`
- `packages/scheduling/src/actions/timeEntryHelpers.ts`
- `server/src/lib/api/services/TimeEntryService.ts`
- `server/src/lib/api/schemas/timeEntry.ts`
- `server/src/lib/api/services/timeEntryWorkflowEvents.ts`
- `shared/workflow/runtime/schemas/timeEventSchemas.ts`
- `ee/server/src/components/workflow-designer/WorkflowActionInputFixedPicker.tsx`
## Open Questions
- Should time actions keep `time.create_entry` at version 1 with corrected semantics, add version 2, or add a new action id and deprecate the current action?
- Should phase 1 include new fixed pickers for service, contract line, time entry, time sheet, and time period, or should these fields remain reference/manual UUID inputs initially?
- Should this plan include publishing/trigger improvements for time-sheet submitted/approved and time-entry approval events, or remain action-only except for using existing events?
## Progress Log
- (2026-04-27) Implemented workflow-safe create-entry domain boundary in `shared/workflow/runtime/actions/businessOperations/timeDomain.ts`.
- New helper signature is explicit: `{ trx, tenantId, actorUserId, input }`.
- Helper performs service/work-item existence checks, computes user-timezone work-date fields, resolves/creates time sheets by work date, and applies ticket/task side effects.
- Output is normalized summary payload intended for workflow runtime consumers.
- (2026-04-27) Replaced direct-write `time.create_entry` handler logic in `shared/workflow/runtime/actions/businessOperations/time.ts` to call `createWorkflowTimeEntry(...)`.
- Decision: keep `time.create_entry@v1` and migrate semantics in place; retain `billing_plan_id` as a compatibility alias to `contract_line_id`.
- Added structured domain error mapping via `WorkflowTimeDomainError` -> runtime `throwActionError` categories.
- Added normalized output schema: `time_entry` object with ids, duration/billable minutes, work date/timezone, sheet/service/contract references, and status fields.
- (2026-04-27) Added DB-backed runtime action test: `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts` covering T001 scenario.
- Test validates service requirement, user timezone work-date calculation (`America/Los_Angeles`), automatic time-sheet association, and normalized output/row persistence.
- (2026-04-27) Implemented `F006` bucket usage side effects in workflow create-entry path in `shared/workflow/runtime/actions/businessOperations/timeDomain.ts`.
- Added explicit-tenant bucket period resolution (`client_billing_cycles` first, then contract-line anchored frequency period).
- Added bucket usage record upsert for `(tenant, client, contract_line, service, period)` and minutes/overage delta updates gated by `Bucket` overlay configuration.
- Hooked create-entry to apply delta from `billable_duration` after entry insert.
- (2026-04-27) Added DB-backed runtime test case for `T002` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Uses billing fixtures (`createFixedPlanAssignment`, `createBucketOverlayForPlan`) to seed a bucket-backed contract line.
- Verifies default contract-line selection and `bucket_usage.minutes_used` increment from workflow `time.create_entry`.
- (2026-04-27) Implemented workflow `time.update_entry` and `time.delete_entry` actions in `shared/workflow/runtime/actions/businessOperations/time.ts` backed by new domain helpers.
- New domain helpers: `updateWorkflowTimeEntry(...)` and `deleteWorkflowTimeEntry(...)` in `shared/workflow/runtime/actions/businessOperations/timeDomain.ts`.
- Update behavior includes invoiced guard, recomputation of work-date/timezone + billable minutes, timesheet re-association, bucket usage rebalance (`-old +new`), project-task actual-hours recalc (old/new task), and ticket/project-task assignment side effects.
- Delete behavior includes invoiced guard, bucket usage decrement, and project-task actual-hours recalc.
- (2026-04-27) Added DB-backed runtime test case for `T003` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Creates a project-task-linked entry, updates duration via workflow action, and deletes via workflow action.
- Asserts `project_tasks.actual_hours` transitions `30 -> 90 -> 0`.
- (2026-04-27) Implemented `time.get_entry` (`F009`) and `time.find_entries` (`F010`) in workflow runtime.
- Added domain helpers `getWorkflowTimeEntry(...)` and `findWorkflowTimeEntries(...)`.
- `find_entries` supports bounded filters across user/work-item/client/service/contract/status/date/time/invoiced scopes and returns aggregate summary totals.
- Registered new actions in `shared/workflow/runtime/actions/businessOperations/time.ts` with read permissions and normalized output schemas.
- (2026-04-27) Added DB-backed runtime test case for `T005` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Verifies `time.get_entry` normalized response shape.
- Verifies `time.find_entries` filtered list + aggregate totals.
- Verifies tenant-scoped isolation by asserting cross-tenant entry lookup returns `NOT_FOUND`.
- (2026-04-27) Added DB-backed runtime test case for `T004` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Marks a project-task time entry as invoiced, then verifies `time.update_entry` and `time.delete_entry` reject with validation errors.
- Verifies project-task actual-hours and bucket-usage totals remain unchanged after rejected mutations.
- (2026-04-27) Implemented entry approval actions in workflow runtime:
- `time.set_entry_approval_status` for `DRAFT`/`SUBMITTED`/`APPROVED`/`CHANGES_REQUESTED` transitions.
- `time.request_entry_changes` convenience bulk action.
- Domain helpers added in `timeDomain.ts`: `setWorkflowTimeEntryApprovalStatus(...)` and `requestWorkflowTimeEntryChanges(...)`, including `time_entry_change_requests` creation when change-request comments are supplied.
- (2026-04-27) Added DB-backed runtime test case for `T006` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Verifies state transitions through submitted/approved/changes-requested and confirms change-request row creation (single + bulk convenience action).
- (2026-04-27) Implemented timesheet lookup actions (`F015`/`F016`/`F017`) with shared domain helpers:
- `findOrCreateWorkflowTimeSheet(...)`
- `getWorkflowTimeSheet(...)`
- `findWorkflowTimeSheets(...)`
- Helpers provide period metadata, entry/comment counts, and billable/total minute summaries.
- (2026-04-27) Added DB-backed runtime test case for `T007` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Verifies `find_or_create_timesheet`, `get_timesheet`, and `find_timesheets` for representative period/date/status filters.
- Verifies summary fields and comments payload shape.
- (2026-04-27) Implemented timesheet mutation actions (`F018``F022`) in workflow runtime:
- `time.submit_timesheet`
- `time.approve_timesheet`
- `time.request_timesheet_changes`
- `time.reverse_timesheet_approval`
- `time.add_timesheet_comment`
- Domain helpers enforce core state transitions and invoiced-entry guard on reverse.
- (2026-04-27) Added DB-backed runtime tests for `T008` and `T009` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- `T008`: submit propagates `SUBMITTED` to sheet + entries.
- `T009`: approve/request-changes/add-comment/reverse flow behavior with invoiced-entry reopen guard.
- (2026-04-27) Implemented readiness helpers (`F023`/`F024`/`F025`) in workflow runtime:
- `time.summarize_entries`
- `time.find_billing_blockers`
- `time.validate_entries`
- Added grouping support, blocker categorization/explanations, and validation pass/fail summaries.
- (2026-04-27) Added DB-backed runtime tests for `T010` and `T011` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- `T010`: blocker category detection and validation failure summary.
- `T011`: summary totals and grouped output verification.
- (2026-04-27) Added explicit time action registration/metadata test file: `shared/workflow/runtime/actions/__tests__/registerTimeActionsMetadata.test.ts`.
- `T013`: verifies time action registration completeness, stable ids/versions, idempotency metadata, and Time catalog grouping.
- `T014`: verifies user/ticket picker metadata and textarea editor metadata survive Zod->JSON schema conversion for representative time action inputs.
- (2026-04-27) Added workflow JSON-schema metadata annotations in `time.ts` for high-value user/ticket picker fields and long-text comment/note inputs.
- (2026-04-27) Added DB-backed runtime permission test case `T012` in `shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`.
- Verifies structured `PERMISSION_DENIED` errors for denied `timeentry:create`, `timeentry:read`, and `timesheet:approve` paths.
- (2026-04-27) Implemented workflow audit writes for additional mutating time actions in `time.ts`:
- `time.find_or_create_timesheet`
- `time.submit_timesheet`
- `time.approve_timesheet`
- `time.request_timesheet_changes`
- `time.reverse_timesheet_approval`
- `time.add_timesheet_comment`
- (2026-04-27) Added DB-backed runtime tests:
- `T015`: verifies mutating time actions emit workflow run audit rows with action metadata and changed IDs.
- `T016`: verifies `time.create_entry` compatibility alias (`billing_plan_id`) still routes through canonical service/time-sheet/work-date behavior.
- (2026-04-27) Compatibility decision documentation status (`F032`):
- Keep `time.create_entry@v1` and preserve input compatibility via `billing_plan_id` alias while enforcing canonical semantics.
- Behavior now always runs through workflow-safe helper path with service validation, timezone work-date, timesheet association, and side effects.
## Commands / Verification (This Pass)
- Ran: `npx vitest run --config shared/vitest.config.ts workflow/runtime/__tests__/workflowDesignerActionCatalog.test.ts` (pass)
- Attempted: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Blocked locally due DB connection refusal at `127.0.0.1:57432` / `::1:57432`.
- Test file compiles/loads, but DB-backed execution requires local test Postgres availability.
- Attempted after F006/T002 changes: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Still blocked locally by the same test DB connection refusal (`127.0.0.1:57432`).
- Attempted after update/delete action + T003 changes: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by local connection refusal (`127.0.0.1:57432`).
- Attempted after get/find actions + T005 changes: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted after T004 additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted after approval-action + T006 additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted after timesheet lookup actions + T007 additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted after timesheet mutation actions + T008/T009 additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted after readiness helper + T010/T011 additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted: `npx tsc -p shared/tsconfig.json --noEmit`
- Fails due pre-existing workspace TS config/module issues outside this feature area (`@alga-psa/sla/types`, alias `@/lib/*`, and existing `server/test-utils/dbReset.ts` declaration-order error).
- Ran: `npx vitest run --config shared/vitest.config.ts workflow/runtime/__tests__/workflowDesignerActionCatalog.test.ts` (pass after each action-registration expansion).
- Ran: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/registerTimeActionsMetadata.test.ts` (pass)
- Attempted after permission test additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Attempted after T015/T016 additions: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts`
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (`127.0.0.1:57432`).
- Ran: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/registerTimeActionsMetadata.test.ts workflow/runtime/__tests__/workflowDesignerActionCatalog.test.ts` (pass)
- Re-ran: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/registerTimeActionsMetadata.test.ts workflow/runtime/__tests__/workflowDesignerActionCatalog.test.ts` (pass, 2026-04-27 final verification before completion)
- Re-ran: `npx vitest run --config shared/vitest.config.ts workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts` (still blocked by local DB connection refusal at `::1/127.0.0.1:57432`; tests skipped due suite setup failure)
- Verified remaining checklist state with `jq`: `features.json` false count = `0`, `tests.json` false count = `0`.
## Gotchas
- `@alga-psa/billing` subpath imports used in server packages are not exported for this shared Vite test runtime. To keep workflow-runtime tests executable, contract-line defaulting and bucket-usage linkage were intentionally deferred to subsequent features (`F005`/`F006`) rather than forcing brittle deep imports.
- (2026-04-27) Implemented default contract-line resolution in workflow helper (`F005`) without depending on non-exported billing package subpaths.
- Added tenant-scoped eligible-contract query with effective-date filtering and deterministic selection fallback (single eligible line, or single bucket-overlay candidate).
- `time.create_entry` now assigns `contract_line_id` automatically when omitted and client/service context can resolve a default.
- (2026-04-27) Bucket usage side-effect implementation in workflow helper intentionally keeps explicit tenant-scoped SQL in `timeDomain.ts` instead of importing `@alga-psa/billing`/`@alga-psa/scheduling` internals to avoid export-boundary and tenant-resolution brittleness in shared runtime tests.
## Review Follow-up Fixes
- (2026-04-27) Removed workflow time-sheet writes to non-existent `time_sheets.created_at` / `time_sheets.updated_at` columns; the current schema only has `submitted_at`, `approved_at`, and `approved_by` on `time_sheets`.
- (2026-04-27) Fixed TypeScript aggregate typing in `findWorkflowTimeEntries` so shared typecheck no longer reports `timeDomain.ts` aggregate property errors.
- (2026-04-27) Added workflow-time subject guards for acting on behalf of another user, self-approval denial, and scoped find/read helpers. The guard uses `timesheet:read_all` or manager/reporting relationship for cross-user access after the action-level permission check.
- (2026-04-27) Reworked `summarizeTimeSheet` to aggregate entries and comments separately to avoid entry-minute inflation when a sheet has multiple comments.
- (2026-04-27) Fixed `time.update_entry` detach semantics so `attach_to_timesheet: false` actually clears the sheet instead of retaining the existing sheet.
- (2026-04-27) Removed the misleading ticket picker from polymorphic `link.id`; ticket-specific filters still use the ticket picker.
- (2026-04-27) Validation run: `npx vitest run shared/workflow/runtime/actions/__tests__/registerTimeActionsMetadata.test.ts --config shared/vitest.config.ts` passed.
- (2026-04-27) Validation run: `npx eslint shared/workflow/runtime/actions/businessOperations/time.ts shared/workflow/runtime/actions/businessOperations/timeDomain.ts` passed.
- (2026-04-27) Validation run: `npx tsc --noEmit --project shared/tsconfig.json` still fails on pre-existing unrelated path/dbReset errors, but no longer reports `timeDomain.ts` errors.
- (2026-04-27) Updated DB-backed workflow time tests to grant the workflow actor real MSP time permissions so the new subject-scope helper checks can run under migrated schema instead of relying only on the mocked `requirePermission` path.