Webhooks Implementation Summary

Overview

This document summarizes the implementation of webhook functionality for the Agent Passport Registry system, providing real-time notifications for status changes with retry logic and dead-letter handling.

Features Implemented

F1. Status Change Webhook āœ… FULLY IMPLEMENTED

Functionality: Real-time webhook notifications for agent status changes with robust retry logic.

Implementation:

  • functions/utils/webhook.ts - Core webhook utilities
  • functions/api/admin/status.ts - Enhanced status endpoint with webhook integration
  • functions/api/admin/webhook-test.ts - Webhook testing endpoint

Key Features:

  • Real-time Notifications: POST webhook on every status change
  • Retry Logic: Exponential backoff with configurable attempts
  • Dead Letter Handling: Failed webhooks are logged for manual processing
  • Signature Verification: HMAC-SHA256 signatures for webhook security
  • Timeout Protection: Configurable timeouts to prevent hanging requests
  • Testing Endpoint: Dedicated endpoint for webhook validation

Architecture

How Webhooks Work with Cloudflare Pages + Next.js

The webhook system is designed to work within Cloudflare's constraints:

  1. Edge Execution: Webhooks are sent from Cloudflare Pages Functions (edge runtime)
  2. Synchronous Processing: Webhooks are sent immediately after status updates
  3. Retry Logic: Built-in exponential backoff for failed deliveries
  4. Dead Letter Logging: Failed webhooks are logged to console (extensible to external services)

Limitations and Considerations

Current Limitations:

  • No Persistent Queues: Retries happen synchronously within the request
  • Limited Execution Time: Cloudflare Functions have execution time limits
  • No Background Workers: No persistent background processing for retries

Production Recommendations:

  • For high-volume systems, consider using Cloudflare Queues or Durable Objects
  • Implement external dead letter queue (e.g., database, external logging service)
  • Consider using Cloudflare Workers for more advanced webhook processing

API Endpoints

POST /api/admin/status (Enhanced)

Purpose: Update agent status with webhook notifications

Webhook Integration: Automatically sends webhook if WEBHOOK_URL is configured

Response Enhancement:

{
  "ok": true,
  "agent_id": "string",
  "status": "string",
  "previous_status": "string",
  "updated_at": "2024-01-15T10:30:00Z",
  "message": "Agent status updated from 'active' to 'suspended'",
  "webhook": {
    "sent": true,
    "attempts": 1,
    "error": null
  }
}

POST /api/admin/webhook-test

Purpose: Test webhook configuration and delivery

Request Body:

{
  "webhook_url": "https://your-webhook-endpoint.com/webhook",
  "webhook_secret": "optional-secret-key",
  "test_agent_id": "optional-test-agent-id"
}

Response:

{
  "ok": true,
  "test_url": "https://your-webhook-endpoint.com/webhook",
  "test_payload": {
    "agent_id": "test-agent",
    "status": "suspended",
    "previous_status": "active",
    "updated_at": "2024-01-15T10:30:00Z",
    "event_type": "status_change",
    "timestamp": "2024-01-15T10:30:00Z"
  },
  "result": {
    "success": true,
    "attempt": 1,
    "error": null,
    "response_status": 200,
    "response_time_ms": 150,
    "total_time_ms": 200
  },
  "message": "Webhook test successful"
}

Webhook Payload

Status Change Event

{
  "agent_id": "agent_123",
  "status": "suspended",
  "previous_status": "active",
  "updated_at": "2024-01-15T10:30:00Z",
  "event_type": "status_change",
  "timestamp": "2024-01-15T10:30:00Z"
}

Headers

Content-Type: application/json
User-Agent: Agent-Passport-Webhook/1.0
X-Webhook-Event: status_change
X-Webhook-Attempt: 1
X-Webhook-Signature: sha256=abc123... (if secret configured)

Configuration

Environment Variables

Add to wrangler.toml:

[vars]
# Webhook configuration (optional)
WEBHOOK_URL = "https://your-webhook-endpoint.com/webhook"
WEBHOOK_SECRET = "your-webhook-secret-key"

Webhook Configuration Options

interface WebhookConfig {
  url: string;                    // Webhook endpoint URL
  secret?: string;               // Optional HMAC secret for signature verification
  retry_attempts?: number;       // Number of retry attempts (default: 3)
  retry_delay_ms?: number;       // Base delay between retries (default: 1000ms)
  timeout_ms?: number;          // Request timeout (default: 5000ms)
}

Security

Signature Verification

Webhooks include HMAC-SHA256 signatures when a secret is configured:

// Verify webhook signature
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature.replace('sha256=', '')),
    Buffer.from(expectedSignature)
  );
}

Best Practices

  1. Always verify signatures when secret is provided
  2. Use HTTPS for webhook endpoints
  3. Implement idempotency to handle duplicate webhooks
  4. Log webhook deliveries for debugging and monitoring
  5. Set appropriate timeouts to prevent hanging requests

Testing

Test Coverage

  • F1.1: Webhook test endpoint returns 200 with test result
  • F1.2: Webhook test unauthorized access returns 401
  • F1.3: Webhook test missing URL returns 400
  • F1.4: Webhook test invalid URL returns 400
  • F1.5: Status change includes webhook information in response
  • F1.6: Webhook payload has correct structure
  • F1.7: Webhook retry logic handles failed requests
  • F1.8: Webhook test with signature works

Running Tests

# Run webhook tests
pnpm run test:webhooks

# Run all tests including webhooks
pnpm run test:all

Usage Examples

Configure Webhook

# Set environment variables
export WEBHOOK_URL="https://your-app.com/webhook"
export WEBHOOK_SECRET="your-secret-key"

# Deploy with webhook configuration
wrangler pages deploy

Test Webhook Configuration

curl -X POST "https://your-domain.com/api/admin/webhook-test" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_url": "https://your-webhook-endpoint.com/webhook",
    "webhook_secret": "your-secret-key"
  }'

Receive Webhook

// Express.js webhook handler example
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const payload = req.body.toString();
  
  // Verify signature
  if (signature && !verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const data = JSON.parse(payload);
  
  // Handle status change
  if (data.event_type === 'status_change') {
    console.log(`Agent ${data.agent_id} status changed from ${data.previous_status} to ${data.status}`);
    // Update your system accordingly
  }
  
  res.status(200).send('OK');
});

Monitoring and Debugging

Webhook Response Information

The status update endpoint returns webhook delivery information:

{
  "webhook": {
    "sent": true,           // Whether webhook was sent
    "attempts": 1,          // Number of attempts made
    "error": null           // Error message if failed
  }
}

Dead Letter Logging

Failed webhooks are logged with detailed information:

{
  "timestamp": "2024-01-15T10:30:00Z",
  "webhook_url": "https://your-webhook-endpoint.com/webhook",
  "payload": { /* webhook payload */ },
  "failure_reason": "Connection timeout",
  "attempts": 3,
  "response_status": null
}

Future Enhancements

  1. Cloudflare Queues Integration: Use Cloudflare Queues for reliable webhook delivery
  2. Durable Objects: Implement persistent retry logic with Durable Objects
  3. Webhook History: Store webhook delivery history in KV
  4. Multiple Webhooks: Support multiple webhook endpoints per event
  5. Event Filtering: Filter webhooks based on event types or conditions
  6. Webhook Dashboard: Admin interface for webhook management and monitoring

Implementation Status

āœ… F1. Status change webhook: Fully implemented with retry logic, dead-letter handling, and comprehensive testing

The webhook implementation provides a robust foundation for real-time notifications while working within Cloudflare's architectural constraints. The system is production-ready for moderate webhook volumes and can be extended for higher-scale requirements.