docs: comprehensive README rewrite with complete service specification #13
64
README.md
64
README.md
@@ -150,8 +150,10 @@ It uses:
|
||||
lifecycle management
|
||||
- **[go-chi](https://github.com/go-chi/chi)** for HTTP routing
|
||||
- **[GORM](https://gorm.io)** for database access with
|
||||
**[modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite)** (pure
|
||||
Go, no CGO) as the storage backend
|
||||
**[modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite)** as
|
||||
the runtime SQLite driver. Note: `gorm.io/driver/sqlite` transitively
|
||||
depends on `mattn/go-sqlite3`, which requires CGO at build time (see
|
||||
[Docker](#docker) section)
|
||||
- **[slog](https://pkg.go.dev/log/slog)** (stdlib) for structured
|
||||
logging with TTY detection (text for dev, JSON for prod)
|
||||
- **[gorilla/sessions](https://github.com/gorilla/sessions)** for
|
||||
@@ -198,7 +200,7 @@ tier** (event ingestion, delivery, and logging).
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ EVENT TIER │
|
||||
│ (per-webhook dedicated database) │
|
||||
│ (planned: per-webhook dedicated database) │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ Event │──1:N──│ Delivery │──1:N──│ DeliveryResult │ │
|
||||
@@ -254,7 +256,7 @@ the full request and creates an Event.
|
||||
| -------------- | ------- | ----------- |
|
||||
| `id` | UUID | Primary key |
|
||||
| `processor_id` | UUID | Foreign key → Webhook |
|
||||
| `path` | string | Unique URL path (UUID-based, e.g. `/hooks/<uuid>`) |
|
||||
| `path` | string | Unique URL path (UUID-based, e.g. `/webhook/{uuid}`) |
|
||||
| `description` | string | Optional description |
|
||||
| `active` | boolean | Whether this entrypoint accepts events (default: true) |
|
||||
|
||||
@@ -387,12 +389,21 @@ All entities include these fields from `BaseModel`:
|
||||
|
||||
### Database Architecture
|
||||
|
||||
webhooker uses **separate SQLite database files** rather than a single
|
||||
monolithic database. This is a deliberate architectural choice.
|
||||
#### Current Implementation
|
||||
|
||||
#### Main Application Database
|
||||
webhooker currently uses a **single SQLite database** for all data —
|
||||
application configuration, user accounts, and (once implemented) event
|
||||
storage. The database connection is managed by GORM with a single
|
||||
connection string configured via `DBURL`. On first startup the database
|
||||
is auto-migrated and an `admin` user is created.
|
||||
|
||||
A single SQLite file stores all application-level data:
|
||||
#### Planned: Per-Webhook Event Databases (Phase 2)
|
||||
|
||||
In a future phase (see TODO Phase 2 below), webhooker will split into
|
||||
**separate SQLite database files**: a main application database for
|
||||
configuration data and per-webhook databases for event storage.
|
||||
|
||||
**Main Application Database** — will store:
|
||||
|
||||
- **Users** — accounts and Argon2id password hashes
|
||||
- **Webhooks** (Processors) — webhook configurations
|
||||
@@ -400,18 +411,14 @@ A single SQLite file stores all application-level data:
|
||||
- **Targets** — delivery destination configurations
|
||||
- **APIKeys** — programmatic access credentials
|
||||
|
||||
This database is small, low-write, and contains the configuration that
|
||||
defines how the application behaves. It is backed up as a single file.
|
||||
|
||||
#### Per-Webhook Event Databases
|
||||
|
||||
Each webhook gets its own dedicated SQLite database file containing:
|
||||
**Per-Webhook Event Databases** — each webhook will get its own
|
||||
dedicated SQLite file containing:
|
||||
|
||||
- **Events** — captured incoming webhook payloads
|
||||
- **Deliveries** — event-to-target pairings and their status
|
||||
- **DeliveryResults** — individual delivery attempt logs
|
||||
|
||||
This separation provides:
|
||||
This planned separation will provide:
|
||||
|
||||
- **Isolation** — a high-volume webhook won't cause lock contention or
|
||||
WAL bloat affecting the main application or other webhooks.
|
||||
@@ -421,22 +428,23 @@ This separation provides:
|
||||
- **Clean deletion** — removing a webhook and all its history is as
|
||||
simple as deleting one file.
|
||||
- **Per-webhook retention** — the `retention_days` field on each webhook
|
||||
controls automatic cleanup of old events in that webhook's database
|
||||
only.
|
||||
- **Performance** — each webhook's database has its own WAL, its own
|
||||
page cache, and its own lock, so concurrent event ingestion across
|
||||
webhooks never contends.
|
||||
will control automatic cleanup of old events in that webhook's
|
||||
database only.
|
||||
- **Performance** — each webhook's database will have its own WAL, its
|
||||
own page cache, and its own lock, so concurrent event ingestion across
|
||||
webhooks won't contend.
|
||||
|
||||
All databases use the pure-Go SQLite driver
|
||||
([modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite)) — no CGO
|
||||
required.
|
||||
The database uses the
|
||||
[modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite) driver at
|
||||
runtime, though CGO is required at build time due to the transitive
|
||||
`mattn/go-sqlite3` dependency from `gorm.io/driver/sqlite`.
|
||||
|
||||
### Request Flow
|
||||
|
||||
```
|
||||
External Service
|
||||
│
|
||||
│ POST /hooks/<uuid>
|
||||
│ POST /webhook/{uuid}
|
||||
▼
|
||||
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ chi Router │────►│ Middleware │────►│ Webhook │
|
||||
@@ -484,7 +492,7 @@ against a misbehaving sender).
|
||||
| `GET` | `/` | Web UI index page (server-rendered) |
|
||||
| `GET` | `/.well-known/healthcheck` | Health check (JSON: status, uptime, version) |
|
||||
| `GET` | `/s/*` | Static file serving (embedded CSS, JS) |
|
||||
| `ANY` | `/hooks/<uuid>` | Webhook receiver endpoint (POST only; others return 405) |
|
||||
| `ANY` | `/webhook/{uuid}` | Webhook receiver endpoint (accepts all methods) |
|
||||
|
||||
#### Authentication Endpoints
|
||||
|
||||
@@ -579,8 +587,8 @@ webhooker/
|
||||
├── pkg/config/ # Reusable multi-environment config library
|
||||
├── static/
|
||||
│ ├── static.go # //go:embed directive
|
||||
│ ├── css/ # Bootstrap CSS
|
||||
│ └── js/ # Bootstrap + jQuery JS
|
||||
│ ├── css/style.css # Custom stylesheet (system font stack, card effects, layout)
|
||||
│ └── js/app.js # Client-side JavaScript (minimal bootstrap)
|
||||
├── templates/ # Go HTML templates (base, index, login, etc.)
|
||||
├── configs/
|
||||
│ └── config.yaml.example # Example configuration file
|
||||
@@ -662,7 +670,7 @@ linted, tested, and compiled.
|
||||
## TODO
|
||||
|
||||
### Phase 1: Core Webhook Engine
|
||||
- [ ] Implement webhook reception and event storage at `/hooks/<uuid>`
|
||||
- [ ] Implement webhook reception and event storage at `/webhook/{uuid}`
|
||||
- [ ] Build event processing and target delivery engine
|
||||
- [ ] Implement HTTP target type (fire-and-forget POST)
|
||||
- [ ] Implement retry target type (exponential backoff)
|
||||
|
||||
Reference in New Issue
Block a user