~ober/jerboa-edge
Imported from ~/mine/jerboa-edge
about
# jerboa-edge `jerboa-edge` is a Jerboa webhook processing daemon. It binds to loopback by default, accepts plain HTTP from a trusted ingress, verifies versioned webhook envelopes with freshness and replay protection, runs event filters and hot handlers in Jerboa restricted execution, persists bounded state and replay claims through jsqlite, and exposes health, metrics, event query, dead-letter, and dashboard endpoints. This daemon is not its own internet TLS endpoint. Production deployments must put it behind an external mTLS terminator or service mesh and expose the daemon only on a private listener. External ingress is defense in depth: every route except `/health` also has an application authentication boundary. ## Build ```sh JERBUILD=/path/to/jerbuild make build ``` The static binary is written to `./jerboa-edge`. The build uses Jerboa native features `crypto,wasm,http`; the `http` feature contains only the bounded HTTP parser/writev shim, while TLS native code is intentionally not linked. Production runtime target is Linux. The static fiber HTTP server uses Jerboa's Linux epoll-native backend; macOS can build the binary but does not provide the runtime epoll symbols needed to execute it. ## Run ```sh EDGE_SECRET='replace-with-webhook-secret' \ EDGE_READ_TOKEN='independent-read-capability' \ EDGE_OPERATOR_TOKEN='independent-operator-capability' \ EDGE_CODE_TOKEN='independent-code-capability' \ EDGE_PORT=8080 \ EDGE_DB_PATH=/var/lib/jerboa-edge/events.db \ ./jerboa-edge ``` All four secrets must contain at least 32 UTF-8 bytes and be distinct. `EDGE_DB_PATH` is mandatory because the bounded replay window must survive a daemon restart. There is no unsigned mode. A non-loopback `EDGE_BIND` also requires `EDGE_ALLOW_NON_LOOPBACK_BIND=1` so exposure is never accidental. Webhook clients sign this canonical UTF-8 envelope with HMAC-SHA256 and send the lowercase hex MAC in `x-edge-signature`: ```text jerboa-edge-v1\n POST\n /hooks/<type>\n <unix timestamp>\n <source id>\n <event id>\n <nonce>\n <lowercase SHA-256 of exact body bytes> ``` The timestamp, source, event ID, and nonce are supplied in `x-edge-timestamp`, `x-edge-source`, `x-edge-event-id`, and `x-edge-nonce`. The JSON body's string `id` must equal the signed ID. API callers use `Authorization: Bearer <role token>`; read, operator, and code-management tokens are intentionally not interchangeable. Useful endpoints: - `POST /hooks/:type` - `GET /health` - `GET /metrics` - `GET /api/stats` - `GET /api/events/:id` - `GET /api/dead-letter` - `POST /api/dead-letter/:id/replay` - `GET /dashboard` The daemon enforces body, connection, request-rate, queue, retry, watcher, filter, handler, replay, event, dead-letter, count, and TTL bounds internally. Ingress limits remain an additional outer layer. ## Security Release gates: ```sh JERBUILD=/path/to/jerbuild make verify JERBUILD=/path/to/jerbuild make release-evidence ``` Release evidence includes Linux runtime/load status under `dist/release-evidence/soak/`. On non-Linux hosts this records the runtime and load gates as blocked; production release requires Linux release-host smoke and sustained load evidence. A Linux release host can record sustained load with `JEDGE_RUN_RELEASE_SOAK=1 JEDGE_RUN_PRODUCTION_LOAD=1`; externally captured runtime/load proof can be attached with `JEDGE_TARGET_RUNTIME_PROOF_FILE` and `JEDGE_TARGET_LOAD_PROOF_FILE`. CI executable bootstrap now fails closed unless a signed Jerboa manifest, pinned digest, and pinned release identity are all present. The checked lock is currently `blocked-awaiting-authenticated-upstream-release`; publishing and pinning that upstream artifact is a release blocker, not a reason to restore the former unverified download. The security posture is documented in: - `SECURITY.md` - `docs/threat-model.md` - `docs/deployment-security.md` - `docs/ffi-boundary.md` - `docs/release-evidence.md` ## License Apache-2.0, matching the Jerboa and Chez Scheme license posture. See `LICENSE`.
recent commits
- Document local mine repository authority ef3317b Jaime Fournier
- Use FreeBSD Forgejo CI runner db15c9c user
- Set up Forgejo CI/CD policy a1f3aff Jaime Fournier
- Add jpkg packaging exclusions c4c1875 Jaime Fournier
- Update jpkg metadata for Forgejo 87887ec Jaime Fournier
- docs: remove jerboa-emacs restriction a8f346e Jaime Fournier
- Remove GitHub workflow metadata e5c53be Jaime Fournier
- jpkg: complete binary package setup f522f9d Jaime Fournier
- new AGENTS.md 8643d04 Jaime Fournier
- security: fix P2.2 fail-open signature validation f20f81e Jaime Fournier