Files
git.stella-ops.org/src/JobEngine/StellaOps.Scheduler.WebService/docs/SCHED-WEB-16-104-WEBHOOKS.md
master 70cbfcee72 feat(scheduler): postgres + redis webhook rate limiter runtime
Sprint SPRINT_20260417_019_JobEngine_truthful_webhook_rate_limiter_runtime.

NoOpWebhookRateLimiter + RedisWebhookRateLimiter, service-collection
wiring, WebhookRateLimiterRuntimeTests, SCHED-WEB-16-104-WEBHOOKS doc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:41:42 +03:00

2.4 KiB

SCHED-WEB-16-104 · Conselier/Excitor Webhook Endpoints

Overview

Scheduler.WebService exposes inbound webhooks that allow Conselier and Excitor to notify the planner when new exports are available. Each webhook validates the payload, enforces signature requirements, and applies a per-endpoint rate limit before queuing downstream processing.

Endpoint Description AuthZ
POST /events/conselier-export Ingest Conselier export metadata (exportId, changedProductKeys, optional KEV & window). HMAC X-Scheduler-Signature and/or mTLS client certificate
POST /events/excitor-export Ingest Excitor export delta summary (changedClaims). HMAC X-Scheduler-Signature and/or mTLS client certificate

Security

  • Webhooks require either:
    • mTLS with trusted client certificates; or
    • an HMAC-SHA256 signature in the X-Scheduler-Signature header. The signature must be computed as sha256=<hex> over the raw request body.
  • Requests without the required signature/certificate return 401.
  • Secrets are configured under Scheduler:Events:Webhooks:{Conselier|Excitor}:HmacSecret.

Rate limiting

  • Each webhook enforces a sliding-window limit (RateLimitRequests over RateLimitWindowSeconds).
  • Requests over the limit return 429 and include a Retry-After header.
  • Defaults: 120 requests / 60 seconds. Adjust via configuration.
  • Outside the Testing environment, the limiter is distributed and backed by the existing scheduler:queue Redis transport contract. InMemoryWebhookRateLimiter remains test-only.
  • If either inbound webhook remains enabled outside Testing without scheduler:queue.kind=Redis and a Redis connection string, Scheduler startup fails fast instead of falling back to process-local rate limiting.

Configuration

Scheduler:
  Events:
    Webhooks:
      Conselier:
        Enabled: true
        HmacSecret: conselier-secret
        RequireClientCertificate: false
        RateLimitRequests: 120
        RateLimitWindowSeconds: 60
      Excitor:
        Enabled: true
        HmacSecret: excitor-secret
        RequireClientCertificate: false
  queue:
    kind: Redis
    redis:
      connectionString: localhost:6379
      database: 0

Response envelope

On success the webhook returns 202 Accepted and a JSON body:

{ "status": "accepted" }

Failures return problem JSON with error describing the violation.