feat: add async /jobs surface, state webhooks, and artifact handling

Add the async job submission API, webhook state notifications, and
artifact serving endpoints on top of the Phase 3 queue infrastructure.

Key changes:
- POST /jobs: async job submission with 202 + job_id ULID; optional
  state_webhook_url for push notifications on state transitions
- GET /jobs/{id}: job status polling with result, error, and artifact
  metadata; artifacts <= 256KB inlined, larger ones by URL reference
- GET /jobs/{id}/artifacts/{name}: raw artifact data serving
- Webhook dispatcher: at-least-once delivery with exponential backoff
  (5 retries); optional HMAC-SHA256 signing (X-Foreman-Signature)
- ADR-0014: state_webhook_url only honored on POST /jobs, not sync
  /api/chat (caller already blocks for result)
- Comprehensive tests for /jobs lifecycle, webhook delivery, HMAC
  verification, artifact inline/URL threshold, and TTL pruning

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-23 18:30:18 -04:00
parent 6fd050855a
commit daf07fd759
7 changed files with 1129 additions and 0 deletions
+2
View File
@@ -25,6 +25,8 @@ worker, one queue. No distributed dispatch, no leases, no fair queueing.
| 0010 | Authentication and security boundary | Accepted |
| 0011 | Go client library and go-llm integration | Accepted |
| 0012 | Streaming support | Accepted |
| 0013 | Two-slot residency and embedding bypass | Accepted |
| 0014 | No webhooks on synchronous /api/chat | Accepted |
ADR-0003 was resolved in favor of **native Ollama** as the v1 surface: foreman is,
on the wire, a private authenticated Ollama deployment, so `go-llm` integrates via