Workflow Templates
A workflow template defines an ordered list of stages (e.g.backlog → in_progress → review → done) that crews attach to their issue trackers. The frontend renders these as column headers on board views; the issue handler enforces the stage transitions when an issue moves between columns.
Implementation: internal/api/workflow_templates_handler.go. Backed by the workflow_templates table (schema introduced in migration v19, see internal/database/migrate_consts_v16_v25.go).
All endpoints require an authenticated session and workspace context. Mutating verbs additionally require
OWNER, ADMIN, or MANAGER role (requireRole("create")).Endpoints
Template shape
Stage shape
Stages live insidetemplate_json as a JSON array. Each stage:
Validation rules enforced by
validateTemplateJSON:
- At least one stage.
- Exactly one stage with
type: open. - At least one stage with
type: completed. - All
namevalues unique; allpositionvalues unique.
400 with a single-sentence message describing the failing constraint.
Endpoint reference
CRUD over templates. Built-in rows are server-controlled and surface first on List.GET /api/v1/workflow-templates
List every template visible to the current workspace. Built-in rows surface first (is_builtin DESC), then user-created rows by created_at ASC.
Auth: authenticated session + workspace context.
Response: 200 OK — JSON array (never null).
POST /api/v1/workflow-templates
Create a new user-owned template.
Auth: authenticated session + workspace context + requireRole("create").
Request body:
Response:
201 Created with the full template object.
Broadcasts
workflow_template.created on the workspace WS channel with {"id": "<id>"}.
GET /api/v1/workflow-templates/{id}
Fetch a single template by id, scoped to the calling workspace.
Auth: authenticated session + workspace context.
Response: 200 OK with the template object.
PATCH /api/v1/workflow-templates/{id}
Partial update. Only the mutable subset (name, description, template_json, icon, color) is writable. is_builtin, created_at, and id are immutable; updated_at is set to “now” on every successful write.
Auth: authenticated session + workspace context + requireRole("create").
Request body: every field optional; only provided (non-null) keys are written.
Response:
200 OK with the freshly-updated template (so callers don’t need to re-GET).
Broadcasts
workflow_template.updated on the workspace WS channel with {"id": "<id>"}.
DELETE /api/v1/workflow-templates/{id}
Hard delete. Templates are reference data — crews that still point at the deleted template fall back to the runtime default lifecycle at next render rather than failing.
Auth: authenticated session + workspace context + requireRole("create").
Response: 204 No Content.
Broadcasts
workflow_template.deleted on the workspace WS channel with {"id": "<id>"}.
See also
crewship workflow— CLI wrapper around these endpoints.- WorkflowTemplate manifest schema — SPEC-2 YAML shape the CLI consumes; the resulting
template_jsonis the same array documented above. - Issues — the issue rows whose stage column these templates govern.