No description
  • Scheme 57.8%
  • Shell 29.1%
  • Makefile 6.3%
  • C 3.7%
  • Python 2.8%
  • Other 0.3%
Find a file
2026-07-30 15:46:38 -06:00
.builds ci: set umask 022 in package/verify tasks too (jerbuild creates group-writable cache dirs during pkg operations) 2026-07-22 13:10:56 -06:00
.jerboa Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
docs Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
scripts Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
support Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
test Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
.gitignore jpkg: complete binary package setup 2026-07-30 15:08:56 -06:00
.jerbuild Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
.jerbuild-test Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
AGENTS.md docs: remove jerboa-emacs restriction 2026-07-30 15:46:38 -06:00
bench-edge.sh Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
edge-main.ss Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
edge.ss security: fix P2.2 fail-open signature validation 2026-07-23 20:25:43 -06:00
jpkg.lock jpkg: complete binary package setup 2026-07-30 15:08:56 -06:00
jpkg.policy.sexp jpkg: complete binary package setup 2026-07-30 15:08:56 -06:00
jpkg.sexp jpkg: complete binary package setup 2026-07-30 15:08:56 -06:00
LICENSE Switch to MIT license 2026-07-21 13:41:55 -06:00
Makefile build: add lint target 2026-07-21 11:57:22 -06:00
README.md Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
SECURITY.md Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00
test-edge.sh Harden edge runtime and release verification 2026-07-11 17:22:04 -06:00

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

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

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:

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:

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.