Files
webhooker/README.md
clawbot 18cfedb81c
All checks were successful
check / check (push) Successful in 2m19s
feat: bring repo up to REPO_POLICIES standards
- Create cmd/webhooker/main.go with fx dependency injection wiring
- Add REPO_POLICIES.md, .editorconfig, .dockerignore
- Add .gitea/workflows/check.yml for CI (docker build on push)
- Rewrite Makefile with all required targets (test, lint, fmt, fmt-check,
  check, build, hooks, docker, clean, dev, run, deps)
- Rewrite Dockerfile with sha256-pinned base images, golangci-lint
  installed from verified release archive, make check as build step
- Fix README.md: add required sections (description, getting started,
  rationale, design, TODO, license, author)
- Integrate TODO.md content into README.md and remove TODO.md
- Move config.yaml to configs/config.yaml.example
- Fix .gitignore pattern for webhooker binary
- Fix static/static.go embed directive (remove empty vendor dir)
- Fix database test to use in-memory config (no filesystem dependency)

closes #1
closes #2
2026-03-01 08:20:51 -08:00

5.4 KiB

webhooker

webhooker is a Go web application by @sneak that receives, stores, and proxies webhooks to configured targets with retry support, observability, and a management web UI. License: pending.

Getting Started

# Clone the repo
git clone https://git.eeqj.de/sneak/webhooker.git
cd webhooker

# Install dependencies
make deps

# Copy example config
cp configs/config.yaml.example config.yaml

# Run in development mode
make dev

# Run all checks (format, lint, test, build)
make check

# Build Docker image
make docker

Environment Variables

  • WEBHOOKER_ENVIRONMENTdev or prod (default: dev)
  • DEBUG — Enable debug logging
  • PORT — Server port (default: 8080)
  • DBURL — Database connection string
  • SESSION_KEY — Base64-encoded 32-byte session key (required in prod)
  • METRICS_USERNAME — Username for metrics endpoint
  • METRICS_PASSWORD — Password for metrics endpoint
  • SENTRY_DSN — Sentry error reporting (optional)

Rationale

Webhook integrations between services are fragile: the receiving service must be up when the webhook fires, there is no built-in retry for most webhook senders, and there is no visibility into what was sent or when. webhooker solves this by acting as a reliable intermediary that receives webhooks, stores them, and delivers them to configured targets — with optional retries, logging, and Prometheus metrics for observability.

Use cases include:

  • Store-and-forward with unlimited retries for unreliable receivers
  • Prometheus/Grafana metric analysis of webhook frequency, size, and handler performance
  • Introspection and debugging of webhook payloads
  • Redelivery of webhook events for application testing
  • Fan-out delivery of webhooks to multiple targets
  • HA ingestion endpoint for delivery to less reliable systems

Design

Architecture

webhooker uses Uber's fx dependency injection library for managing application lifecycle. It uses log/slog for structured logging, GORM for database access, and SQLite (via modernc.org/sqlite, pure Go, no CGO) for storage. HTTP routing uses chi.

Package Layout

All application code lives under internal/ to prevent external imports. The main entry point is cmd/webhooker/main.go.

  • internal/config — Configuration management via pkg/config (Viper-based)
  • internal/database — GORM database connection, migrations, and models
  • internal/globals — Global application metadata (version, build info)
  • internal/handlers — HTTP handlers using the closure pattern
  • internal/healthcheck — Health check endpoint logic
  • internal/logger — Structured logging setup (log/slog)
  • internal/middleware — HTTP middleware (auth, CORS, logging, metrics)
  • internal/server — HTTP server setup and routing
  • internal/session — Session management (gorilla/sessions)
  • pkg/config — Reusable multi-environment configuration library
  • static/ — Embedded static assets (CSS, JS)
  • templates/ — Go HTML templates

Data Model

  • Users — Service users with username/password (Argon2id hashing)
  • Processors — Webhook processing units, many-to-one with users
  • Webhooks — Inbound URL endpoints feeding into processors
  • Targets — Delivery destinations per processor (HTTP, retry, database, log)
  • Events — Captured webhook payloads
  • Deliveries — Pairing of events with targets
  • Delivery Results — Outcome of each delivery attempt
  • API Keys — Programmatic access credentials per user

API Endpoints

  • GET / — Web UI index page
  • GET /.well-known/healthcheck.json — Health check with uptime, version
  • GET /s/* — Static file serving (CSS, JS)
  • GET /metrics — Prometheus metrics (requires basic auth)
  • POST /webhook/{uuid} — Webhook receiver endpoint
  • /pages/login, /pages/logout — Authentication
  • /user/{username} — User profile
  • /sources/* — Webhook source management

TODO

Phase 1: Security & Infrastructure

  • Security headers (HSTS, CSP, X-Frame-Options)
  • Rate limiting middleware
  • CSRF protection for forms
  • Request ID tracking through entire lifecycle

Phase 2: Authentication & Authorization

  • Authentication middleware for protected routes
  • Session expiration and "remember me"
  • Password reset flow
  • API key authentication for programmatic access

Phase 3: Core Webhook Features

  • Webhook reception and event storage at /webhook/{uuid}
  • Event processing and target delivery engine
  • HTTP target type (fire-and-forget POST)
  • Retry target type (exponential backoff)
  • Database target type (store only)
  • Log target type (console output)
  • Webhook signature verification (GitHub, Stripe formats)

Phase 4: Web UI

  • Webhook source management pages (list, create, edit, delete)
  • Webhook request log viewer with filtering
  • Delivery status and retry management UI
  • Manual event redelivery
  • Analytics dashboard (success rates, response times)

Phase 5: API

  • RESTful CRUD for processors, webhooks, targets
  • Event viewing and filtering endpoints
  • API documentation (OpenAPI)

Future

  • Email source and delivery target types
  • SNS, S3, Slack delivery targets
  • Data transformations (e.g. webhook-to-Slack message)
  • JSONL file delivery with periodic S3 upload

License

Pending — to be determined by the author (MIT, GPL, or WTFPL).

Author

@sneak