Skip to content

Boat.Webhook reference

Source: packages/boat/src/SandboxEvents.ts

Receive Boat sandbox lifecycle events (sandbox.ready, sandbox.hydrated, sandbox.error, sandbox.archived, sandbox.degraded, sandbox.recovered) in a Cloudflare Worker or any other webhook host.

At deploy, a Webhook is created pointing at the host, and its signing secret is given to the host as a secret (a Cloudflare secret on a Worker). While the host runs, each delivery’s X-Ascii-Signature (HMAC-SHA256 over the delivery id, timestamp and raw body) is checked before the handler runs; an unsigned, wrongly signed, altered or stale (over five minutes old) request is refused with 401, and bodies over 1 MB are refused unread. Boat retries a failed delivery, so handlers should be idempotent on event.id.

Boat sends a webhook the events of every sandbox in the account, and an account has at most 10 webhooks. With the default scope: "stack", the host looks each sandbox up with a key of its own, created at deploy and deleted with the host, that can only read sandboxes (sandbox.read), and drops events for sandboxes other stacks or stages own, and for sandboxes already deleted. The scope is a filter, not an access boundary: anyone in the account who can create sandboxes can label one with the stack’s labels.

Record when a sandbox stops

export default class Api extends Cloudflare.Worker<Api>()(
"Api",
{ main: import.meta.url },
Effect.gen(function* () {
yield* Boat.consumeSandboxEvents({ events: ["sandbox.archived"] }, (event) =>
Effect.log(`sandbox ${event.data.sandbox.id} stopped`),
);
return { fetch: Effect.succeed(HttpServerResponse.text("ok")) };
}).pipe(Effect.provide(Boat.SandboxEventsLive)),
) {}

Every sandbox in the account

yield* Boat.consumeSandboxEvents({ scope: "account", events: ["sandbox.error"] }, (event) =>
Effect.logError(`sandbox ${event.data.sandbox.id} failed`),
);

Source: packages/boat/src/SandboxEventsLive.ts Kind: Layer · Provides: Boat.SandboxEvents

SandboxEvents on any WebhookHost: every Cloudflare Worker is one.

Source: packages/boat/src/Webhook.ts

A Boat webhook: Boat POSTs sandbox lifecycle events (sandbox.ready, sandbox.error, sandbox.archived, sandbox.hydrated, sandbox.degraded, sandbox.recovered) to your endpoint, signed with secret.

const receiver = yield* Receiver;
const hook = yield* Boat.Webhook("Events", {
url: Output.interpolate`${receiver.url}/boat`,
events: ["sandbox.ready", "sandbox.archived"],
});