Repository navigation
Architecture and Security
Home · Previous: API and Configuration · Next: Troubleshooting and Contributing
Sender → POST /in/{token} → size check + header redaction → SQLite commit → 201
Workbench → bearer-authenticated API → stored events and history
Manual replay → persist pending attempt → configured receiver → persist outcome
Events and attempts are separate records. Replaying does not replace the original event or erase earlier failures.
| Decision | Benefit | Boundary |
|---|---|---|
| SQLite with WAL | No extra database service for local use | Small synchronous operations can block the API loop; no production throughput claim |
| Commit before capture acknowledgement | An accepted event survives an app restart | Backups and infrastructure durability remain the operator's concern |
| Persist a pending attempt before sending | Record unfinished work across restart | Remote side effects can happen before a final outcome is recorded |
| One application process | Simple local lifecycle | Multiple processes can misclassify each other's pending attempts |
| Named destinations | API callers select approved server configuration | Operator-controlled DNS and URLs remain trusted inputs |
| Plain HTML/CSS/JavaScript UI | Small package focused on backend behavior | Manual refresh and loaded-page filtering |
A replay starts as pending and finishes as delivered for a destination 2xx, or failed for another status or a network error. An unfinished attempt can become interrupted after cancellation or on startup recovery. Interrupted does not mean the receiver did nothing.
The built-in demo uses in-process ASGI transport. Its latency is not a network benchmark. Replay and Idempotency shows real local HTTP delivery and why receiver deduplication matters.
Location under webhook_lab/
|
Responsibility |
|---|---|
config.py |
Environment and destination validation |
store.py |
Schema, capacity and persisted event/attempt lifecycle |
replay.py |
One bounded outgoing HTTP attempt |
app.py |
Routes, auth, limits and application lifecycle |
static/ |
Event inspector UI |
This build is a local, single-user development tool. Keep its loopback binding; it is not ready for public hosting.
- The inbox URL allows capture. The separate administrator token grants inspection and replay. Keep both private.
- A diagnostic header allowlist retains selected values; other values become
[redacted]before storage. Query strings are not stored. - Bodies are unchanged and unencrypted. Header redaction does not redact payloads. Use synthetic data for demos and screenshots.
- Replay preserves body/content type, but not captured credentials, cookies or provider signatures. Response bodies are not stored.
- Redirects and environment proxies are disabled. Private destination addresses remain allowed for local development; this is not public multi-tenant SSRF isolation.
- There is an event cap, but no attempt-count cap or automatic retention yet.
- UI previews use text nodes and raw bodies download as attachments. The optional Swagger documentation uses FastAPI's standard external assets.
The roadmap proposes migrations, PostgreSQL and durable jobs with leases before multi-process background delivery. Those features have not shipped.
See the architecture document for the detailed diagram and security policy for private vulnerability reporting guidance.