Status & Release
Smoke tests, release gates, and operational limits
Pre-production validation strategy and release criteria for safe deployment confidence.
Smoke Test Strategy
Before promoting code to production, run a deterministic smoke test suite that validates:
- • Task creation with idempotency key reuse
- • Status polling until terminal state
- • Evidence retrieval and structure validation
- • Error handling for 4xx/5xx responses
- • Rate limit compliance and backoff behavior
Test Environment
Use sandbox credentials and a dedicated test tenant to isolate smoke test activity from production data.
Webhook Simulation
Test webhook handling before release by simulating lifecycle events locally:
Mock Event Payload
{
"event": "task.completed",
"taskId": "task_test_123",
"status": "completed",
"timestamp": "2026-02-14T22:00:00Z",
"evidence": {
"type": "photo",
"url": "https://...",
"metadata": {}
}
}Signature Verification Test
import crypto from "node:crypto";
function verifyWebhook(body: string, signature: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Test with known payload and secret
const testPayload = JSON.stringify({ event: "task.completed" });
const testSecret = "test_webhook_secret";
const validSig = crypto.createHmac("sha256", testSecret)
.update(testPayload)
.digest("hex");
console.assert(verifyWebhook(testPayload, validSig, testSecret));Signature Validation
Always verify webhook signatures before processing events to prevent spoofed notifications.
Release Gate Criteria
A deployment passes release gates when:
- 1. All smoke tests pass in staging environment
- 2. Webhook signature verification succeeds
- 3. Idempotency key collision handling is validated
- 4. Rate limit backoff logic is confirmed
- 5. Error response parsing covers all documented codes
Production Readiness
Do not bypass release gates. Failed validation indicates integration risk that must be resolved before production promotion.
Endpoint Surface
| Endpoint | Purpose |
|---|---|
| POST /v1/tasks | Create task |
| GET /v1/tasks | List tasks |
| GET /v1/tasks/:id | Read task status and evidence |
| GET /health | Service health check |
| GET /ready | Dependency readiness |
Rate Limits
Limits vary by plan and endpoint class. Handle 429 responses with retry backoff and preserve idempotency keys on retry.
x-ratelimit-limit: 120
x-ratelimit-remaining: 0
x-ratelimit-reset: 1710000000// Safe retry pattern
if (status === 429) {
const retryAfter = Number(response.headers.get("retry-after") ?? 1);
await sleep(retryAfter * 1000 + jitter());
// Retry with same idempotency key
}Error Model
| Code | Meaning | Action |
|---|---|---|
| 400 | Invalid request payload | Fix schema fields |
| 401 | Authentication failure | Rotate/verify API key |
| 409 | Idempotency conflict | Reuse original request shape |
| 429 | Rate limit exceeded | Backoff and retry |
| 5xx | Transient service issue | Retry with circuit breaker |