~ober/jerboa-edge

Imported from ~/mine/jerboa-edge

download snapshot

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