# 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) ```json [ {"field": "severity", "op": "eq", "value": "critical", "target_stage": "fix-critical"}, {"field": "severity", "op": "neq", "value": "critical", "target_stage": "fix-normal"} ] ``` ### API Walkthrough ```bash # 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: ```python 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: ```python 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) ```json { "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) ```json { "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: ```python 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 ```bash # 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.