#327 App HTTP Gateway - Direct API invocation of app actions

wont-do high Created 2025-12-09 12:54 · Updated 2025-12-09 13:16

Description

Edit
## Summary Add ability to invoke app actions directly via HTTP API without creating a workflow. ## HTTP Methods ### GET - For Email Approval Links & Simple Queries ``` GET /api/v1/apps/invoke/{installation_id}/{action_name}?param1=value1&param2=value2 Authorization: Bearer <token> (or via signed URL token) ``` **Use Cases:** - Email approval links: `<a href="/api/v1/apps/invoke/{id}/approve?token=xyz&decision=yes">Approve</a>` - Simple status checks - Idempotent read operations ### POST - For API Integrations & Complex Data ``` POST /api/v1/apps/invoke/{installation_id}/{action_name} Authorization: Bearer <token> Content-Type: application/json { "param1": "value1", "param2": "value2" } ``` ### Version-Specific Endpoints ``` GET /api/v1/apps/invoke/version/{version_id}/{action_name}?params... POST /api/v1/apps/invoke/version/{version_id}/{action_name} ``` **Why UUIDs, not names:** - Guaranteed uniqueness across 1000s of apps - Version-specific targeting (v1.0.0 vs v2.0.0 behavior) - No name collision between publishers - Immutable reference - URL always points to same code ## Response Formats ### Standard JSON Response ```json { "status": "success", "data": { "result": { ... }, "execution_id": "uuid", "app_id": "uuid", "version_id": "uuid", "duration_ms": 123 } } ``` ### HTML Response (for email links) When `Accept: text/html` header or `?format=html` query param: ```html <!DOCTYPE html> <html><body> <h1>Thank You</h1> <p>Your decision has been recorded.</p> </body></html> ``` ### Redirect Response When action returns `{"_redirect": "https://..."}`: ``` HTTP/1.1 302 Found Location: https://app.example.com/approval-confirmed?id=123 ``` ### Error Response ```json { "status": "error", "error": { "code": "ACTION_FAILED", "message": "Human readable error", "details": { ... } }, "execution_id": "uuid" } ``` ## Email Approval Flow 1. Workflow sends approval email with links: ``` Approve: https://highway.example.com/api/v1/apps/invoke/{id}/approve?token=abc&decision=yes&format=html Reject: https://highway.example.com/api/v1/apps/invoke/{id}/approve?token=abc&decision=no&format=html ``` 2. User clicks link → GET request 3. App validates token, processes decision 4. Returns HTML page OR redirects to confirmation page ## Security Considerations ### For GET Requests (Email Links) - Use **signed tokens** instead of JWT in URL (shorter, single-use) - Token includes: action_id, expiry, decision, HMAC signature - Tokens tracked in `highway.action_tokens` table (consumed on use) - Short expiry (24-72 hours) - No sensitive data in URL params ### Token Consumption Table ```sql CREATE TABLE highway.action_tokens ( token_id UUID PRIMARY KEY, installation_id UUID NOT NULL, action_name VARCHAR(100) NOT NULL, params_hash VARCHAR(64), expires_at TIMESTAMPTZ NOT NULL, consumed_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW() ); ``` ### For POST Requests - Standard JWT authentication - CORS policy: Same-origin by default, configurable per installation - Request body validation against action schema ## Gateway Context (vs Workflow Context) HTTP Gateway executions get a simplified context: | Feature | AppContext (Workflow) | GatewayContext (HTTP) | |---------|----------------------|----------------------| | Secrets | ✅ | ✅ | | Config | ✅ | ✅ | | HTTP requests | ✅ | ✅ | | Logging | ✅ | ✅ | | Checkpoints | ✅ | ❌ (single call) | | Events/wait | ✅ | ❌ | | Sleep | ✅ | ❌ | | State vars | ✅ | ❌ | | DB connection | ✅ | ✅ (separate tx) | ## Rate Limiting | Scope | Default Limit | Configurable | |-------|--------------|--------------| | Per tenant | 1000 req/min | Yes | | Per installation | 100 req/min | Yes | | Per action | 50 req/min | Yes | | Burst | 10 req/sec | Yes | ## Async Execution (Future) For long-running actions: ``` POST /api/v1/apps/invoke/{installation_id}/{action_name}?async=true Response: { "status": "accepted", "job_id": "uuid", "poll_url": "/api/v1/apps/jobs/{job_id}" } ``` ## Webhook Registration Apps declare webhooks in manifest: ```json { "webhooks": { "github_push": { "path": "github/push", "method": "POST", "signature_header": "X-Hub-Signature-256", "signature_algorithm": "hmac-sha256" } } } ``` Webhook URL: `POST /api/v1/webhooks/{version_id}/github/push` ## URL Structure | Use Case | Method | URL Pattern | |----------|--------|-------------| | Email approval link | GET | `/api/v1/apps/invoke/{installation_id}/{action_name}?token=...&format=html` | | API integration | POST | `/api/v1/apps/invoke/{installation_id}/{action_name}` | | Specific version (GET) | GET | `/api/v1/apps/invoke/version/{version_id}/{action_name}?params...` | | Specific version (POST) | POST | `/api/v1/apps/invoke/version/{version_id}/{action_name}` | | Webhook receiver | POST | `/api/v1/webhooks/{version_id}/{webhook_path}` | | Async job status | GET | `/api/v1/apps/jobs/{job_id}` | ## Use Cases - **Email approvals** - User clicks link in email, records decision - GitHub webhook triggers app action (version-pinned) - Slack slash commands invoke app - External API integrations - Simple automations without full workflow - CI/CD pipelines calling specific app versions

Comments

Loading comments...

Context

Loading context...

Audit History

View All
Loading audit history...