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"` }