This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/models/workflow.go
Jeffrey Smith 446edb8333 Feat v0.9.6 deprecate stage_type, collapse stage_mode
stage_type no longer validated — starlark_hook presence determines
automation. stage_mode collapsed from 4→3 values (form/delegated/
automated); "review" mapped to "form" on input for backward compat.
Migration 018 converts existing rows. Review surface removed (~110
lines). 4 package manifests updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 17:41:55 +00:00

220 lines
8.2 KiB
Go

package models
import (
"encoding/json"
"time"
)
// ── Workflow ────────────────────────────────
// Workflow is a team-owned or global staged process definition.
type Workflow struct {
ID string `json:"id"`
TeamID *string `json:"team_id,omitempty"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Branding json.RawMessage `json:"branding"`
EntryMode string `json:"entry_mode"` // public_link | team_only
IsActive bool `json:"is_active"`
Version int `json:"version"`
OnComplete json.RawMessage `json:"on_complete,omitempty"`
Retention json.RawMessage `json:"retention"`
WebhookURL string `json:"webhook_url,omitempty"`
WebhookSecret string `json:"webhook_secret,omitempty"`
StalenessTimeoutHours *int `json:"staleness_timeout_hours,omitempty"`
CreatedBy string `json:"created_by"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Joined data (not stored directly)
Stages []WorkflowStage `json:"stages,omitempty"`
}
// WorkflowPatch contains optional fields for updating a workflow.
type WorkflowPatch struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
TeamID *string `json:"team_id,omitempty"`
Branding *json.RawMessage `json:"branding,omitempty"`
EntryMode *string `json:"entry_mode,omitempty"`
IsActive *bool `json:"is_active,omitempty"`
OnComplete *json.RawMessage `json:"on_complete,omitempty"`
Retention *json.RawMessage `json:"retention,omitempty"`
WebhookURL *string `json:"webhook_url,omitempty"`
WebhookSecret *string `json:"webhook_secret,omitempty"`
StalenessTimeoutHours *int `json:"staleness_timeout_hours,omitempty"`
}
// ── Workflow Stage ──────────────────────────
// WorkflowStage is an ordered step within a workflow definition.
type WorkflowStage struct {
ID string `json:"id"`
WorkflowID string `json:"workflow_id"`
Ordinal int `json:"ordinal"`
Name string `json:"name"`
AssignmentTeamID *string `json:"assignment_team_id,omitempty"`
FormTemplate json.RawMessage `json:"form_template"`
StageMode string `json:"stage_mode"` // form | delegated | automated
Audience string `json:"audience"` // team | public | system
StageType string `json:"stage_type"` // deprecated — retained for backward compatibility
AutoTransition bool `json:"auto_transition"`
StageConfig json.RawMessage `json:"stage_config"`
BranchRules json.RawMessage `json:"branch_rules"`
StarlarkHook *string `json:"starlark_hook,omitempty"`
SurfacePkgID *string `json:"surface_pkg_id,omitempty"`
SLASeconds *int `json:"sla_seconds,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// ── Stage Mode Constants ────────────────────
const (
StageModeForm = "form"
StageModeDelegated = "delegated"
StageModeAutomated = "automated"
)
// ValidStageModes is the set of valid stage_mode values.
var ValidStageModes = map[string]bool{
StageModeForm: true,
StageModeDelegated: true,
StageModeAutomated: true,
}
// NormalizeStageModeInput maps deprecated stage_mode values to their
// replacements. "review" → "form"; all others pass through unchanged.
func NormalizeStageModeInput(mode string) string {
if mode == "review" {
return StageModeForm
}
return mode
}
// ── Stage Type Constants (deprecated) ───────
// stage_type is redundant with starlark_hook presence and is no longer
// validated. Constants are retained for backward-compatible references.
const (
StageTypeSimple = "simple"
StageTypeDynamic = "dynamic"
StageTypeAutomated = "automated"
)
// ── Audience Constants ──────────────────────
const (
AudienceTeam = "team"
AudiencePublic = "public"
AudienceSystem = "system"
)
// ValidAudiences is the set of valid audience values.
var ValidAudiences = map[string]bool{
AudienceTeam: true,
AudiencePublic: true,
AudienceSystem: true,
}
// ── Instance Status Constants ───────────────
const (
InstanceStatusActive = "active"
InstanceStatusCompleted = "completed"
InstanceStatusCancelled = "cancelled"
InstanceStatusStale = "stale"
InstanceStatusError = "error"
)
// ValidInstanceStatuses is the set of valid workflow instance status values.
var ValidInstanceStatuses = map[string]bool{
InstanceStatusActive: true,
InstanceStatusCompleted: true,
InstanceStatusCancelled: true,
InstanceStatusStale: true,
InstanceStatusError: true,
}
// ── Assignment Status Constants ─────────────
const (
AssignmentStatusUnassigned = "unassigned"
AssignmentStatusClaimed = "claimed"
AssignmentStatusCompleted = "completed"
AssignmentStatusCancelled = "cancelled"
)
// ValidAssignmentStatuses is the set of valid workflow assignment status values.
var ValidAssignmentStatuses = map[string]bool{
AssignmentStatusUnassigned: true,
AssignmentStatusClaimed: true,
AssignmentStatusCompleted: true,
AssignmentStatusCancelled: true,
}
// ── Workflow Instance ───────────────────────
// WorkflowInstance tracks a single execution of a workflow definition.
type WorkflowInstance struct {
ID string `json:"id"`
WorkflowID string `json:"workflow_id"`
WorkflowVersion int `json:"workflow_version"`
CurrentStage string `json:"current_stage"`
StageData json.RawMessage `json:"stage_data"`
Status string `json:"status"`
StartedBy string `json:"started_by"`
EntryToken *string `json:"entry_token,omitempty"`
Metadata json.RawMessage `json:"metadata"`
StageEnteredAt time.Time `json:"stage_entered_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// ── Workflow Assignment ─────────────────────
// WorkflowAssignment tracks per-stage work items in the team queue.
type WorkflowAssignment struct {
ID string `json:"id"`
InstanceID string `json:"instance_id"`
Stage string `json:"stage"`
TeamID string `json:"team_id"`
AssignedTo *string `json:"assigned_to,omitempty"`
Status string `json:"status"`
ReviewData json.RawMessage `json:"review_data"`
ClaimedAt *time.Time `json:"claimed_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// ── Workflow Signoff ───────────────
// WorkflowSignoff records a user's approval or rejection at a stage boundary.
type WorkflowSignoff struct {
ID string `json:"id"`
InstanceID string `json:"instance_id"`
Stage string `json:"stage"`
UserID string `json:"user_id"`
Decision string `json:"decision"` // approve | reject
Comment string `json:"comment"`
CreatedAt time.Time `json:"created_at"`
}
// Signoff decision constants.
const (
SignoffApprove = "approve"
SignoffReject = "reject"
)
// ── Workflow Version (immutable snapshot) ───
// WorkflowVersion is an immutable snapshot of a workflow definition
// at a point in time. Active workflow instances run against a pinned version.
type WorkflowVersion struct {
ID string `json:"id"`
WorkflowID string `json:"workflow_id"`
VersionNumber int `json:"version_number"`
Snapshot json.RawMessage `json:"snapshot"`
CreatedAt time.Time `json:"created_at"`
}