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/docs/DEMO-WORKFLOWS.md
Jeffrey Smith f0dd43144e rebrand: Switchboard Core → Armature
- Rename Go module switchboard-core → armature (155+ files)
- Rename Docker image → gobha/armature
- Rename K8s resources, secrets, deployments
- Rename Prometheus metrics switchboard_* → armature_*
- Rename env vars SWITCHBOARD_ADMIN_* → ARMATURE_ADMIN_*
- Rename DB names switchboard_core* → armature*
- Update all frontend branding, notification templates, docs
- Update CI scripts, e2e tests, Keycloak realm, nginx conf
- Rename scripts/switchboard-ca.sh → scripts/armature-ca.sh
- Rename k8s/switchboard.yaml → k8s/armature.yaml
- Rename chart alerting/dashboard files
- Fix: DockerHub push uses env: binding for secret injection
- Helm chart updated (name, labels, template functions, dashboard, alerting)
- Replace favicon/icon assets with Armature brand

No functional changes. Pure mechanical rename + CI fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 21:39:58 +00:00

9.6 KiB

Demo Workflows — v0.3.6

Four example workflow packages that prove the engine works end-to-end. Each is a self-contained .pkg archive installable via Admin > Packages.

Feature Capability Matrix

Feature Bug Report Onboarding Content Approval Webhook
Public entry (anonymous)
Progressive fieldsets
Branch rules (conditional routing)
Team assignment + claim
SLA timer
Starlark automated stage
db.insert (ext_data tables)
notifications.send
http.post (outbound webhook)
connections.get (credentials)
Signoff gate (required_role)
Multi-party signoff (quorum)
Rejection reroute
Review cycle (loop)

Package 1: Bug Report Triage

Slug: bug-report-triage Entry mode: public_link — anyone with the link can submit Tier: browser (no Starlark needed)

Stage Flow

[submit]  →  [classify]  →  [fix-critical]  →  [verify]
  public       team        ↘ [fix-normal]  ↗     team
                              team

Stages

# Name Mode Audience Key Feature
0 submit form public 2 fieldsets: "Report Details" (email, summary, component, severity) + "Reproduction" (steps, expected, actual)
1 classify form team Team reviews. Branch rules: severity=critical → fix-critical, else → fix-normal
2 fix-critical form team Senior team queue. SLA: 3600s
3 fix-normal form team Standard fix queue
4 verify review team Verify fix, close out

Branch Rules (stage 1)

[
  {"field": "severity", "op": "eq", "value": "critical", "target_stage": "fix-critical"},
  {"field": "severity", "op": "neq", "value": "critical", "target_stage": "fix-normal"}
]

API Walkthrough

# 1. Start public instance (no auth required)
curl -X POST $BASE/api/v1/public/workflows/$WF_ID/start \
  -H 'Content-Type: application/json' \
  -d '{"data": {"reporter_email": "user@example.com", "summary": "Login broken", "component": "ui", "severity": "critical", "steps": "1. Click login", "expected": "Login page", "actual": "500 error"}}'

# Response includes entry_token for anonymous continuation
# {"id": "inst-xxx", "entry_token": "tok-yyy", ...}

# 2. Resume (check status)
curl $BASE/api/v1/public/workflows/resume/tok-yyy

# 3. Team member claims the classify assignment
curl -X POST $BASE/api/v1/teams/$TEAM/assignments/$ASSIGN_ID/claim \
  -H "Authorization: Bearer $TOKEN"

# 4. Advance classify stage (triggers branch rule)
curl -X POST $BASE/api/v1/teams/$TEAM/instances/$INST/advance \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"data": {"severity": "critical", "notes": "Confirmed production issue"}}'
# → Routes to fix-critical (not fix-normal)

Package 2: Employee Onboarding

Slug: employee-onboarding Entry mode: team_only Tier: starlark Permissions: db.write, notifications.send

Stage Flow

[new-hire-info]  →  [provision-accounts]  →  [manager-signoff]  →  [it-setup]  →  [welcome]
    team              automated (Starlark)      review + signoff       team         automated
                      auto-advances             reject → stage 0                   auto-advances

Stages

# Name Mode Audience Key Feature
0 new-hire-info form team 2 fieldsets: "Personal Info" + "Access Requirements"
1 provision-accounts automated system Starlark: db.insert provisioning records, notify HR
2 manager-signoff review team 1 approval required, required_role: "manager", reject → new-hire-info
3 it-setup form team IT confirms hardware + access
4 welcome automated system Starlark: log completion, send welcome notification

Starlark Hooks

on_provision(ctx) — Automated provisioning:

def on_provision(ctx):
    data = ctx["stage_data"]
    name = data.get("full_name", "unknown")
    dept = data.get("department", "general")

    # Record provision in ext_data table
    db.insert("provisions", {
        "employee_name": name,
        "department": dept,
        "needs_vpn": str(data.get("needs_vpn", False)),
        "needs_admin": str(data.get("needs_admin", False)),
        "equipment": data.get("equipment", "standard laptop"),
        "status": "provisioned"
    })

    # Notify the HR user who started this workflow
    notifications.send(
        ctx["started_by"],
        "Accounts provisioned for " + name,
        "Department: " + dept + ". Ready for manager review."
    )

    return {"advance": True, "data": {
        "provision_status": "complete",
        "accounts": ["email", "vpn" if data.get("needs_vpn") else None, "admin" if data.get("needs_admin") else None]
    }}

on_welcome(ctx) — Completion logging:

def on_welcome(ctx):
    data = ctx["stage_data"]

    db.insert("onboarding_log", {
        "employee_name": data.get("full_name", ""),
        "department": data.get("department", ""),
        "completed_by": ctx["started_by"],
        "status": "complete"
    })

    notifications.send(
        ctx["started_by"],
        "Onboarding complete: " + data.get("full_name", ""),
        "All stages finished. Welcome aboard!"
    )

    return {"advance": True, "data": {"onboarding_complete": True}}

Signoff Gate (stage 2)

{
  "validation": {
    "required_approvals": 1,
    "required_role": "manager",
    "reject_action": "new-hire-info"
  }
}

Prerequisites

  • Team must have a custom "manager" role (via Team Admin > Members > Team Roles)
  • At least one team member with the "manager" role assigned

Package 3: Content Approval

Slug: content-approval Entry mode: team_only Tier: browser

Stage Flow

[draft]  →  [review]  →  [publish]
   team       team  ↕      team
             [revision]
              team

Stages

# Name Mode Audience Key Feature
0 draft form team Author submits title, body, category
1 review review team 2 approvals required. Reject → revision
2 revision form team Author revises. Branch rule always routes back to review
3 publish form team Final confirmation

Review Cycle

The rejection reroute creates a loop:

  1. Author submits draft → enters review
  2. Reviewer A approves, Reviewer B rejects → reject_action: "revision" routes to stage 2
  3. Author revises → branch rule routes back to review (stage 1)
  4. Both reviewers approve → advances to publish (stage 3)

Signoff Gate (stage 1)

{
  "validation": {
    "required_approvals": 2,
    "reject_action": "revision"
  }
}

Package 4: Webhook Notifier

Slug: webhook-notifier Entry mode: team_only Tier: starlark Permissions: api.http, connections.read, db.write

Stage Flow

[configure]  →  [fire-webhook]  →  [result]
    team          automated          review
                  (http.post)

Stages

# Name Mode Audience Key Feature
0 configure form team URL + event name + payload
1 fire-webhook automated system Starlark: http.post to webhook URL
2 result review team Shows delivery status

Starlark Hook

on_fire(ctx) — Outbound HTTP:

def on_fire(ctx):
    data = ctx["stage_data"]
    url = data.get("webhook_url", "")

    # Fallback to configured connection
    if not url:
        conn = connections.get("webhook")
        if conn:
            url = conn.get("url", "")

    if not url:
        return {"error": "No webhook URL configured"}

    payload = json.encode({
        "event": data.get("event_name", "workflow.notify"),
        "instance_id": ctx["instance_id"],
        "workflow_id": ctx["workflow_id"],
        "data": data
    })

    resp = http.post(url, body=payload, headers={
        "Content-Type": "application/json",
        "X-Armature-Event": data.get("event_name", "workflow.notify")
    })

    # Log the delivery
    db.insert("webhook_log", {
        "url": url,
        "status_code": str(resp["status"]),
        "event": data.get("event_name", ""),
        "instance_id": ctx["instance_id"]
    })

    return {"advance": True, "data": {
        "delivery_status": "delivered" if int(resp["status"]) < 400 else "failed",
        "status_code": resp["status"],
        "response_body": resp["body"][:500]
    }}

Demo Surface

A browser-tier surface (workflow-demo) auto-installed on first run. Provides:

  • Workflow cards with feature badges and stage flow diagrams
  • "Try It" buttons for interactive exploration
  • Starlark code viewer showing hook source
  • API curl examples for each operation

Can be uninstalled by admin like any other package.


Quick Start

# Build all example packages
cd packages && ./build.sh bug-report-triage employee-onboarding content-approval webhook-notifier workflow-demo

# Install via admin API
for pkg in dist/bug-report-triage.pkg dist/employee-onboarding.pkg dist/content-approval.pkg dist/webhook-notifier.pkg dist/workflow-demo.pkg; do
  curl -X POST $BASE/api/v1/admin/packages/install \
    -H "Authorization: Bearer $TOKEN" \
    -F "file=@$pkg"
done

Or with bundled packages (v0.3.8+): just docker compose up — all examples are auto-installed.