>_
.issue.db
/highway-workflow-engine
Dashboard
Issues
Memory
Lessons
Audit Log
New Issue
Edit Issue #328
Update issue details
Title *
Description
## Summary External systems need to send signals/events to **waiting workflows**. This is NOT standalone app execution - apps only exist within workflow context. ## Core Concept ``` Workflow starts → App calls wait_for_event() or request_approval() → Workflow SUSPENDS ↓ External system/User → HTTP Gateway → Emits event → Workflow RESUMES ``` The HTTP Gateway is an **event injection mechanism** that wakes suspended workflows. ## Use Cases 1. **Human Approval** - User clicks approve/reject link in email 2. **Webhook Callbacks** - GitHub/Stripe/Twilio sends webhook, workflow continues 3. **External System Signals** - CI/CD completion, payment confirmation 4. **Manual Intervention** - Operator signals workflow to proceed ## API Endpoints ### 1. Approval Endpoint (Email Links) ``` GET /api/v1/approvals/{approval_id}/respond?decision=approved&token={signed_token} GET /api/v1/approvals/{approval_id}/respond?decision=rejected&token={signed_token} ``` **Flow:** 1. Workflow calls `ctx.request_approval("payment_approval", ...)` 2. System creates approval record, sends email with links 3. User clicks link → GET request to approval endpoint 4. Endpoint validates token, emits `approval_{key}` event 5. Workflow wakes up, receives `{status: "approved", approved_by: ...}` **Response:** - HTML confirmation page (for browsers) - Or redirect to configured URL ### 2. Event Injection Endpoint ``` POST /api/v1/events/{tenant_id} Authorization: Bearer <token> Content-Type: application/json { "event_name": "payment.confirmed", "correlation_key": "order_123", "payload": { "transaction_id": "txn_abc", "amount": 100.00 } } ``` **Flow:** 1. Workflow calls `ctx.wait_for_event("wait_payment", "payment.confirmed", correlation_key="order_123")` 2. External payment system POSTs to event endpoint 3. Event routed to waiting workflow by correlation_key 4. Workflow resumes with payload ### 3. Webhook Receiver Endpoint ``` POST /api/v1/webhooks/{webhook_id} X-Hub-Signature-256: sha256=... Content-Type: application/json { ...webhook payload from GitHub/Stripe/etc... } ``` **Flow:** 1. Workflow registers webhook expectation with `ctx.register_webhook("github_pr", ...)` 2. GitHub sends webhook to registered URL 3. Gateway validates signature, extracts event data 4. Emits event to waiting workflow ## Data Model ### Approval Records (existing) ```sql -- Already exists: highway.workflow_approvals -- Links approval_key to workflow_run_id ``` ### Event Subscriptions ```sql CREATE TABLE highway.event_subscriptions ( subscription_id UUID PRIMARY KEY, tenant_id VARCHAR(100) NOT NULL, workflow_run_id UUID NOT NULL, event_name VARCHAR(255) NOT NULL, correlation_key VARCHAR(255), created_at TIMESTAMPTZ DEFAULT NOW(), expires_at TIMESTAMPTZ, consumed_at TIMESTAMPTZ, UNIQUE (tenant_id, event_name, correlation_key) ); ``` ### Webhook Registrations ```sql CREATE TABLE highway.webhook_registrations ( webhook_id UUID PRIMARY KEY, tenant_id VARCHAR(100) NOT NULL, workflow_run_id UUID NOT NULL, webhook_path VARCHAR(255) NOT NULL, signature_header VARCHAR(100), signature_secret_id UUID, -- Reference to tenant secret created_at TIMESTAMPTZ DEFAULT NOW(), expires_at TIMESTAMPTZ, consumed_at TIMESTAMPTZ ); ``` ## Security ### Approval Tokens - Signed with HMAC (short, single-use) - Contains: approval_id, expiry, expected_decision - Validated before emitting event - Marked consumed after use ### Event Injection - Requires tenant JWT token - Events scoped to tenant - Rate limited per tenant ### Webhooks - Signature verification (HMAC-SHA256) - Secret stored in Vault, referenced by UUID - IP allowlisting (optional) ## Response Formats ### Approval (GET - browser) ```html <!DOCTYPE html> <html><body> <h1>Thank You</h1> <p>Your approval has been recorded.</p> </body></html> ``` Or redirect: ``` HTTP/1.1 302 Found Location: https://app.example.com/approved?id=123 ``` ### Event/Webhook (POST - API) ```json { "status": "accepted", "event_id": "uuid", "delivered_to": 1, // Number of workflows that received event "message": "Event delivered to waiting workflow" } ``` ### Errors ```json { "status": "error", "code": "NO_WAITING_WORKFLOW", "message": "No workflow waiting for this event" } ``` ## URL Structure | Use Case | Method | URL | |----------|--------|-----| | Email approval | GET | `/api/v1/approvals/{approval_id}/respond?decision=...&token=...` | | Event injection | POST | `/api/v1/events/{tenant_id}` | | Webhook receiver | POST | `/api/v1/webhooks/{webhook_id}` | | Check approval status | GET | `/api/v1/approvals/{approval_id}` | ## SDK Methods (App Side) ```python # Already exists ctx.request_approval(step_name, approval_key, title, ...) ctx.wait_for_event(step_name, event_name, timeout_seconds, correlation_key=None) # New ctx.register_webhook(step_name, webhook_path, signature_config) -> webhook_url ``` ## Key Principle **Apps do NOT execute via HTTP Gateway.** The gateway only: 1. Validates incoming request 2. Looks up waiting workflow 3. Emits event to wake workflow 4. Workflow resumes and app continues executing within workflow context
Priority
Low
Medium
High
Critical
Status
Open
In Progress
Closed
Won't Do
Due Date (YYYY-MM-DD)
Tags (comma separated)
Related Issues (IDs)
Enter IDs of issues related to this one. They will be linked as 'related'.
Update Issue
Cancel