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

22 KiB
Raw Blame History

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.
  • 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 (F018F022) 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.