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

202 lines
10 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.

# PRD — Workflow V2 Time-Based Clock Triggers
- Slug: `workflow-v2-time-based-clock-triggers`
- Date: `2026-03-07`
- Status: Draft
## Summary
Add first-class pure clock triggers to Workflow V2 for Enterprise Edition. A workflow may start from either a one-time scheduled timestamp or a recurring 5-field cron schedule with a timezone. Each clock fire starts exactly one workflow run with a fixed synthetic trigger payload. This scope does not include entity fan-out, synthetic event-catalog triggers, CE support, or an explicit manual trigger type.
## Problem
Workflow V2 is currently event-driven. The canonical trigger contract only supports event triggers, the designer only exposes event selection, and runtime fan-out starts runs only from event ingress. Users cannot build automations that run at a specific future time or on a recurring schedule without routing through unrelated systems.
This leaves a functional gap for common automation use cases such as daily summaries, end-of-day cleanup, periodic reminders, and future-dated follow-up workflows.
## Goals
- Add first-class time trigger variants to Workflow V2:
- one-time schedule
- recurring schedule
- Keep the model honest: time-triggered workflows should not be disguised as synthetic events.
- Make time-triggered workflows EE-only and back them with the existing job-runner scheduling layer.
- Ensure each clock fire starts exactly one workflow run.
- Give time-triggered workflows a stable, fixed payload contract that can be pinned in the designer.
- Register, reschedule, pause, and cancel underlying schedules as workflow definitions are published or updated.
- Reuse one shared run-launch path so event triggers and time triggers do not drift further apart.
## Non-goals
- Fan-out over domain entities such as “run once per due ticket”.
- A generic query/filter engine over records at fire time.
- CE support.
- Cron expressions with seconds or 6-field cron syntax.
- An explicit `manual` trigger type. “No trigger” remains the existing no-trigger shape.
- Replacing the existing Workflow V2 run worker or wait/retry model.
- Net-new operational dashboards, metrics pipelines, or feature-flag rollout work in this scope.
- Multiple schedules attached to a single workflow definition in this first version.
## Users and Primary Flows
1. Automation manager creates a workflow with a one-time trigger
- User opens Workflow Designer.
- User chooses `One-time schedule` as the trigger type.
- User selects a future timestamp.
- User reviews the fixed clock-trigger payload schema.
- User publishes the workflow.
- The system registers a one-time scheduled job.
- When the scheduled time arrives, the system starts exactly one workflow run.
2. Automation manager creates a recurring workflow
- User opens Workflow Designer.
- User chooses `Recurring schedule` as the trigger type.
- User enters a valid 5-field cron expression and selects a timezone.
- User reviews the fixed clock-trigger payload schema.
- User publishes the workflow.
- The system registers a recurring schedule.
- Each schedule fire starts exactly one workflow run.
3. Automation manager changes a published time-triggered workflow
- User edits the trigger configuration or publishes a newer version.
- The system atomically updates the registered schedule.
- Future fires use the latest published version and the new trigger configuration.
4. Automation manager pauses or removes a time-triggered workflow
- User pauses the workflow or deletes it.
- The system cancels or disables the registered schedule.
- No new runs are started while the workflow is paused or after it is removed.
## UX / UI Notes
- Replace the event-only trigger picker with a trigger-type selector:
- No trigger
- Event
- One-time schedule
- Recurring schedule
- Time-triggered workflows must not show event catalog or trigger-mapping controls.
- One-time schedule UX should use a future timestamp picker.
- Recurring schedule UX should use:
- a 5-field cron input
- timezone selection
- inline validation/help text clarifying that seconds are not supported
- For time triggers, the designer should show a fixed payload schema preview instead of inferred event schema behavior.
- “No trigger” remains the absence of a trigger object; there is no separate manual trigger type in this scope.
- Runs and workflow summaries should label time triggers distinctly from events.
## Requirements
### Functional Requirements
- Extend the shared Workflow V2 trigger contract to support:
- no trigger
- event trigger
- one-time schedule trigger
- recurring schedule trigger
- Time trigger variants must be persisted as first-class trigger definitions on workflow definitions and published versions.
- One-time schedule triggers must store a single future fire timestamp.
- Recurring schedule triggers must store a valid 5-field cron expression and timezone.
- Time-triggered workflows must be EE-only.
- Time-triggered workflows must use pinned payload schema mode in this scope.
- The system must register or update underlying scheduled jobs when:
- a time-triggered workflow is published
- a published time trigger changes
- a new published version supersedes an older one
- The system must cancel or disable underlying scheduled jobs when:
- a workflow is paused
- a workflow is deleted
- a trigger changes away from a time trigger
- Each schedule fire must start exactly one workflow run.
- One-time schedules must not refire after they have fired.
- Time-trigger fires must go through a shared workflow launcher service so run creation rules are centralized.
- Existing event-trigger behavior must continue to work after launcher extraction.
- Time-triggered runs must carry a fixed synthetic payload contract that includes enough clock metadata for workflow steps to reason about why and when the run started.
- Run provenance for time-triggered runs must be visible in workflow runs APIs and UI.
- Workflow list/filter logic must use real trigger type values rather than inferring schedule-like behavior from event-name strings.
### Non-functional Requirements
- Reuse the existing job-runner abstraction for scheduling rather than creating a new scheduler.
- Recurring schedules must use 5-field cron semantics only.
- Reschedule operations on published workflows must be atomic from the applications point of view: failed reschedule attempts must not silently leave definitions and registered jobs out of sync.
- Duplicate job delivery or retry must not create duplicate workflow runs for the same scheduled fire.
- Time-trigger lifecycle state must be durably persisted in the database.
## Data / API / Integrations
- Shared workflow definition schema:
- extend trigger union in `shared/workflow/runtime/types.ts`
- Workflow server actions:
- update create/update/publish validation paths in `packages/workflows/src/actions/workflow-runtime-v2-actions.ts`
- Designer:
- update `ee/server/src/components/workflow-designer/WorkflowDesigner.tsx`
- Scheduling backend:
- use `IJobRunner.scheduleJobAt()` for one-time schedules
- use `IJobRunner.scheduleRecurringJob()` for recurring schedules
- Add a workflow-specific schedule state table for EE that stores:
- schedule id
- tenant/workflow/version linkage
- trigger kind
- run-at or cron/timezone
- enabled/paused state
- job-runner ids
- last fire / next fire / last result metadata as needed
- Add a dedicated EE job handler that receives workflow schedule fire payloads and invokes the shared workflow launcher.
- Register a fixed schema ref for time-trigger payloads, for example a `trigger.clock.v1`-style contract owned by Workflow V2.
Example synthetic payload shape for time-triggered runs:
```json
{
"triggerType": "schedule",
"scheduleId": "uuid",
"scheduledFor": "2026-03-08T14:00:00.000Z",
"firedAt": "2026-03-08T14:00:01.250Z",
"timezone": "America/New_York",
"workflowId": "uuid",
"workflowVersion": 3
}
```
For recurring triggers, `triggerType` would be `recurring`, and the payload may additionally include the configured cron string.
## Security / Permissions
- Only users who can manage/publish workflows may configure time triggers.
- Time-triggered workflow publish paths must enforce EE-only availability.
- Schedule fire payloads must be synthetic workflow metadata only; they must not inject arbitrary external payloads.
- Schedule lifecycle operations must preserve tenant isolation in storage and job execution.
## Observability
- Reuse existing workflow run logs and job-runner status where possible.
- No new observability platform work is required in this scope.
- At minimum, the stored workflow schedule state must make it possible to determine whether a schedule is registered, last fired, and last failed.
## Rollout / Migration
- This is a net-new EE-only capability.
- Existing event-triggered workflows and no-trigger workflows must remain unchanged.
- Existing workflow list filtering should be migrated off heuristic trigger detection to real trigger types.
- No migration of legacy workflow registrations is required beyond schema/table additions for time-trigger support.
## Open Questions
- Should completed one-time schedules remain visible as completed registration records indefinitely, or be cleaned up after a retention period?
- Should recurring trigger UI show “next fire time” in this initial scope or defer that to a follow-up?
- Should time-trigger provenance use new dedicated run columns, or be represented through existing run provenance fields plus structured metadata?
## Acceptance Criteria (Definition of Done)
- Workflow V2 definitions can represent one-time and recurring clock triggers as first-class trigger variants.
- Workflow Designer supports configuring both time trigger types and does not show event-specific trigger UI for them.
- Time-triggered workflows can be published only in EE and only with pinned payload schema mode.
- Publishing a one-time triggered workflow registers one scheduled job.
- Publishing a recurring triggered workflow registers one recurring schedule.
- Editing a published time trigger reschedules it without leaving stale registrations behind.
- Pausing or deleting a time-triggered workflow stops future scheduled fires.
- Each schedule fire starts exactly one workflow run.
- One-time schedules do not refire after the scheduled execution has occurred.
- Duplicate delivery or retry of the same schedule fire does not create duplicate runs.
- Event-triggered workflows continue to publish and run correctly after launcher refactoring.