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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
22 KiB
22 KiB
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_entryshould 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_entrydirectly inserts intotime_entries, usesbilling_plan_id, computeswork_datefrom UTC, and does not attach to a time sheet or resolveservice_id/contract_line_idbehavior. - (2026-04-27) Canonical scheduling behavior lives primarily in
packages/scheduling/src/actions/timeEntryCrudActions.ts,timeSheetOperations.ts, andtimeSheetActions.ts. - (2026-04-27) Important canonical side effects include
service_idvalidation, 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_SUBMITTEDandTIME_ENTRY_APPROVEDexist inshared/workflow/runtime/schemas/timeEventSchemas.ts, but current workflow-trigger publication appears limited; ticket time entry added publication is handled byserver/src/lib/api/services/timeEntryWorkflowEvents.ts. - (2026-04-27)
packages/scheduling/src/services/bucketUsageService.tsrequires tenant inference viacreateTenantKnex()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
rgacrossserver,shared,packages, andeefortime_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-actionsif the validator supports folder input; otherwise run project JSON validation orpython -m json.toolon each JSON file.
Links / References
shared/workflow/runtime/actions/businessOperations/time.tsshared/workflow/runtime/actions/registerBusinessOperationsActions.tsshared/workflow/runtime/designer/actionCatalog.tsshared/workflow/runtime/jsonSchemaMetadata.tspackages/scheduling/src/actions/timeEntryCrudActions.tspackages/scheduling/src/actions/timeSheetOperations.tspackages/scheduling/src/actions/timeSheetActions.tspackages/scheduling/src/actions/timeEntryServices.tspackages/scheduling/src/actions/timeEntryHelpers.tsserver/src/lib/api/services/TimeEntryService.tsserver/src/lib/api/schemas/timeEntry.tsserver/src/lib/api/services/timeEntryWorkflowEvents.tsshared/workflow/runtime/schemas/timeEventSchemas.tsee/server/src/components/workflow-designer/WorkflowActionInputFixedPicker.tsx
Open Questions
- Should time actions keep
time.create_entryat 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.
- New helper signature is explicit:
- (2026-04-27) Replaced direct-write
time.create_entryhandler logic inshared/workflow/runtime/actions/businessOperations/time.tsto callcreateWorkflowTimeEntry(...).- Decision: keep
time.create_entry@v1and migrate semantics in place; retainbilling_plan_idas a compatibility alias tocontract_line_id. - Added structured domain error mapping via
WorkflowTimeDomainError-> runtimethrowActionErrorcategories. - Added normalized output schema:
time_entryobject with ids, duration/billable minutes, work date/timezone, sheet/service/contract references, and status fields.
- Decision: keep
- (2026-04-27) Added DB-backed runtime action test:
shared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.tscovering T001 scenario.- Test validates service requirement, user timezone work-date calculation (
America/Los_Angeles), automatic time-sheet association, and normalized output/row persistence.
- Test validates service requirement, user timezone work-date calculation (
- (2026-04-27) Implemented
F006bucket usage side effects in workflow create-entry path inshared/workflow/runtime/actions/businessOperations/timeDomain.ts.- Added explicit-tenant bucket period resolution (
client_billing_cyclesfirst, then contract-line anchored frequency period). - Added bucket usage record upsert for
(tenant, client, contract_line, service, period)and minutes/overage delta updates gated byBucketoverlay configuration. - Hooked create-entry to apply delta from
billable_durationafter entry insert.
- Added explicit-tenant bucket period resolution (
- (2026-04-27) Added DB-backed runtime test case for
T002inshared/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_usedincrement from workflowtime.create_entry.
- Uses billing fixtures (
- (2026-04-27) Implemented workflow
time.update_entryandtime.delete_entryactions inshared/workflow/runtime/actions/businessOperations/time.tsbacked by new domain helpers.- New domain helpers:
updateWorkflowTimeEntry(...)anddeleteWorkflowTimeEntry(...)inshared/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.
- New domain helpers:
- (2026-04-27) Added DB-backed runtime test case for
T003inshared/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_hourstransitions30 -> 90 -> 0.
- (2026-04-27) Implemented
time.get_entry(F009) andtime.find_entries(F010) in workflow runtime.- Added domain helpers
getWorkflowTimeEntry(...)andfindWorkflowTimeEntries(...). find_entriessupports 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.tswith read permissions and normalized output schemas.
- Added domain helpers
- (2026-04-27) Added DB-backed runtime test case for
T005inshared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts.- Verifies
time.get_entrynormalized response shape. - Verifies
time.find_entriesfiltered list + aggregate totals. - Verifies tenant-scoped isolation by asserting cross-tenant entry lookup returns
NOT_FOUND.
- Verifies
- (2026-04-27) Added DB-backed runtime test case for
T004inshared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts.- Marks a project-task time entry as invoiced, then verifies
time.update_entryandtime.delete_entryreject with validation errors. - Verifies project-task actual-hours and bucket-usage totals remain unchanged after rejected mutations.
- Marks a project-task time entry as invoiced, then verifies
- (2026-04-27) Implemented entry approval actions in workflow runtime:
time.set_entry_approval_statusforDRAFT/SUBMITTED/APPROVED/CHANGES_REQUESTEDtransitions.time.request_entry_changesconvenience bulk action.- Domain helpers added in
timeDomain.ts:setWorkflowTimeEntryApprovalStatus(...)andrequestWorkflowTimeEntryChanges(...), includingtime_entry_change_requestscreation when change-request comments are supplied.
- (2026-04-27) Added DB-backed runtime test case for
T006inshared/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
T007inshared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts.- Verifies
find_or_create_timesheet,get_timesheet, andfind_timesheetsfor representative period/date/status filters. - Verifies summary fields and comments payload shape.
- Verifies
- (2026-04-27) Implemented timesheet mutation actions (
F018–F022) in workflow runtime:time.submit_timesheettime.approve_timesheettime.request_timesheet_changestime.reverse_timesheet_approvaltime.add_timesheet_comment- Domain helpers enforce core state transitions and invoiced-entry guard on reverse.
- (2026-04-27) Added DB-backed runtime tests for
T008andT009inshared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts.T008: submit propagatesSUBMITTEDto 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_entriestime.find_billing_blockerstime.validate_entries- Added grouping support, blocker categorization/explanations, and validation pass/fail summaries.
- (2026-04-27) Added DB-backed runtime tests for
T010andT011inshared/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.tsfor high-value user/ticket picker fields and long-text comment/note inputs. - (2026-04-27) Added DB-backed runtime permission test case
T012inshared/workflow/runtime/actions/__tests__/businessOperations.time.db.test.ts.- Verifies structured
PERMISSION_DENIEDerrors for deniedtimeentry:create,timeentry:read, andtimesheet:approvepaths.
- Verifies structured
- (2026-04-27) Implemented workflow audit writes for additional mutating time actions in
time.ts:time.find_or_create_timesheettime.submit_timesheettime.approve_timesheettime.request_timesheet_changestime.reverse_timesheet_approvaltime.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: verifiestime.create_entrycompatibility 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@v1and preserve input compatibility viabilling_plan_idalias while enforcing canonical semantics. - Behavior now always runs through workflow-safe helper path with service validation, timezone work-date, timesheet association, and side effects.
- Keep
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.
- Blocked locally due DB connection refusal at
- 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).
- Still blocked locally by the same test DB connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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 existingserver/test-utils/dbReset.tsdeclaration-order error).
- Fails due pre-existing workspace TS config/module issues outside this feature area (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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).
- Compile/import succeeds, but DB-backed execution remains blocked by the same local connection refusal (
- 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.jsonfalse count =0,tests.jsonfalse count =0.
Gotchas
@alga-psa/billingsubpath 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_entrynow assignscontract_line_idautomatically 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.tsinstead of importing@alga-psa/billing/@alga-psa/schedulinginternals 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_atcolumns; the current schema only hassubmitted_at,approved_at, andapproved_byontime_sheets. - (2026-04-27) Fixed TypeScript aggregate typing in
findWorkflowTimeEntriesso shared typecheck no longer reportstimeDomain.tsaggregate 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_allor manager/reporting relationship for cross-user access after the action-level permission check. - (2026-04-27) Reworked
summarizeTimeSheetto aggregate entries and comments separately to avoid entry-minute inflation when a sheet has multiple comments. - (2026-04-27) Fixed
time.update_entrydetach semantics soattach_to_timesheet: falseactually 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.tspassed. - (2026-04-27) Validation run:
npx eslint shared/workflow/runtime/actions/businessOperations/time.ts shared/workflow/runtime/actions/businessOperations/timeDomain.tspassed. - (2026-04-27) Validation run:
npx tsc --noEmit --project shared/tsconfig.jsonstill fails on pre-existing unrelated path/dbReset errors, but no longer reportstimeDomain.tserrors. - (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
requirePermissionpath.