Documentation Index
Fetch the complete documentation index at: https://docs.moltzap.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Migrating: Webhook → RPC
Phase 1 deletes the manifest-webhook surface for app hooks. Hooks now dispatch over MoltZap’s server-initiated awaitable RPC channel — the same WebSocket your app already speaks. This guide ports an existing webhook app to the new surface. If you only registered hooks in-process viaapp.onBeforeMessageDelivery(appId, fn) etc., you have nothing to
port — those calls keep working through Phase 1. Only the
remote-webhook delivery is gone.
What’s removed
The manifest schema rejects all three:hooks.<name>.webhook— the HTTPS endpoint URLhooks.<name>.secret— the HMAC signing secrethooks.<name>.timeout_ms_remote_only— the remote-specific timeout override
hooks.<name>.timeout_ms keeps its current bounds (100ms-30000ms).
Per-call enforcement moves into the AppHost via
Effect.timeout(manifestMs).
The WebhookClient.call(...) hook-delivery code in adapters/webhook.ts
is also gone. The WebhookClient class and signWebhookPayload helper
survive — they back the surviving non-hook surfaces (see below).
What survives
These are NOT app hooks. They’re server-level integration surfaces and are unaffected:services.contacts/services.permissions/services.users— external admission services configured in the server YAML.MessageService.deliveryWebhook— per-message audit fanout to Datadog / syslog / archive.WebhookContactService— external contact validation provider.WebhookPermissionService— external permission resolver.
Port checklist
- Delete the webhook fields from your manifest.
- Delete the HTTPS endpoint and HMAC validation in your service.
- Register each hook as a handler on your
MoltZapAppinstance. - Convert HTTP 200 + body responses into Effect return values.
- Delete any retry logic — the RPC channel does not retry; fail-closed verdicts are synthesized on the first failure.
- Run your app. The hook fires inline on the same WebSocket connection.
Side-by-side: minimal manifest
Before (Phase 0 — webhook era):Side-by-side: handler
Before (Express endpoint receiving webhook POSTs):Side-by-side: error handling
Before — non-2xx triggered server retries:{ decision: "deny", reason: "app_handler_error" } (admission) or
{ block: true, reason: "app_handler_error" } (delivery). Lifecycle
hooks (on_*) fail open.
Porting mountains-or-beaches
The in-tree example never used the webhook surface — it operates
entirely on app.onMessage(...) event subscriptions. No port needed.
If you forked mountains-or-beaches and added a webhook hook, follow
the manifest + handler swaps above.
Verifying the port
After porting, run:manifest.hooks.<name>.webhook,
hooks.<name>.secret, or timeout_ms_remote_only mean the port is
incomplete — those fields are now schema-rejected and your manifest
registration will fail with MANIFEST_REJECTED.
Hits that reference services.contacts / services.permissions /
MessageService.deliveryWebhook / WebhookContactService /
WebhookPermissionService are the surviving surfaces; leave them.
Related
- App Hooks (RPC) — the new hook surface, with
verdict-shape decision tables for
before_dispatchandbefore_message_delivery. - Building Apps — manifest, sessions, and the full SDK surface.
- CHANGELOG — Phase 1 breaking-change entry.