Skip to content

feat: webhook reliability and idempotency guarantees - #50

Merged
MaryammAli merged 2 commits into
Proof-Stell:mainfrom
Xhristin3:feat/webhook-reliability-idempotency
Jul 23, 2026
Merged

feat: webhook reliability and idempotency guarantees#50
MaryammAli merged 2 commits into
Proof-Stell:mainfrom
Xhristin3:feat/webhook-reliability-idempotency

Conversation

@Xhristin3

@Xhristin3 Xhristin3 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Description

Resolves #47
Closes #47

Adds webhook reliability improvements and idempotency guarantees to the ProofStell service.

Changes

HMAC-SHA256 Request Signing

  • Every webhook delivery includes a X-Signature-256 header when WEBHOOK_SECRET is configured
  • Signature is computed over the JSON body using the shared secret
  • Receivers should verify signatures before processing payloads

Redis-backed DLQ Persistence

  • Dead-letter entries are persisted to the cache backend with a 7-day TTL
  • Survives process restarts for manual replay
  • Falls back to in-memory VecDeque when no cache is available

Webhook Health Endpoint

  • GET /webhooks/health returns healthy, degraded, or disabled status
  • Based on DLQ depth and number of configured URLs

Enhanced Deduplication

  • Redis-backed idempotency keys for cross-restart deduplication
  • Configurable deduplication TTL

Documentation

  • Full idempotency protocol docs covering all headers and recommended receiver implementation

Testing

  • 7 new tests for signature generation, dedup, DLQ persistence, and drain
  • All 202 tests pass

Implements the full scope of issue Proof-Stell#48:

Strongly-typed configuration wrappers:
- Add ValidatedUrl, ValidatedRedisUrl, ValidatedPort wrapper types
- Each validates format at construction time with clear error messages

Rate-limit invariant enforcement:
- Add burst >= per_second validation for both global and per-issuer tiers
- Prevents misconfiguration where burst is less than the refill rate

Bounds checking:
- Add MAX_TIMEOUT_MS (300s) upper bound for all delay/timeout values
- Add log level validation (trace/debug/info/warn/error only)
- Port validation with explicit min/max constants

Config versioning:
- Add CONFIG_VERSION constant and ConfigVersion type
- Rollback detection via validate_compatible()
- Version exposed via config status endpoint

Hot-reload mechanism:
- ConfigWatcher using tokio::sync::watch channel
- POST /config/reload endpoint to trigger reload from env
- GET /config/status endpoint exposing current version
- Background task applies updates to dependent services

Documentation:
- All 30+ environment variables documented with purpose, defaults, and validation rules
- Config versioning policy documented

Tests:
- 14 new tests covering all validation rules, wrapper types, versioning, and hot-reload
- HMAC-SHA256 request signing: X-Signature-256 header on every delivery
  when WEBHOOK_SECRET is configured
- Redis-backed DLQ persistence: dead-letter entries survive process
  restarts via the cache backend with 7-day TTL
- Webhook health endpoint: GET /webhooks/health returns healthy,
  degraded, or disabled status based on DLQ depth and URL count
- Enhanced deduplication: Redis-backed idempotency keys with configurable
  TTL for cross-restart deduplication
- Idempotency protocol documentation covering all headers and
  recommended receiver implementation
- New public API: url_count() on WebhookDispatcher
- 7 new tests for signature, dedup, DLQ persistence, and drain

@MaryammAli MaryammAli left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
well done dev

@MaryammAli
MaryammAli merged commit 8b26c1b into Proof-Stell:main Jul 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Webhook Reliability and Idempotency Guarantees

2 participants