Skip to content

Document receiving webhooks in Zero endpoints - #55

Open
batuhan wants to merge 4 commits into
mainfrom
zero-webhook-endpoints
Open

batuhan wants to merge 4 commits into
mainfrom
zero-webhook-endpoints

Conversation

@batuhan

@batuhan batuhan commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Adds a "Receiving a webhook" section to the Zero runtime page. Someone building a Square payment flow couldn't tell from the docs whether Zero can take a provider callback.

The section covers:

  • Opening only the webhook path. Spaces are private by default, so a provider's cookie-less POST gets a 403 until a public Grant covers the path. It shows access.public in sf.jsonc and the matching sf share grant --to public --path command.
  • Reading the raw body with req.text() / req.bytes() before parsing, because signatures cover the exact bytes sent.
  • Signing key as a write-only variable read from ctx.env.
  • Writing the HMAC yourself. The runner has no crypto, crypto.subtle or TextEncoder, and server/ can only import the SDK, preact and relative files. atob/btoa are available.
  • The same-origin write check only applies to requests that carry a visitor session, so server-to-server calls reach the handler.

It also removes fetch from the "Rejected in server/" row. The compiler doesn't reject it; it just isn't defined at runtime, which the existing warning already says. The warning now lists the extra globals and points to Functions for outbound calls and to the new section for callbacks.

Verified against the released CLI (0.4.1) and the deployed runner:

  • 0.4.1 compiles every handler with fetch: false, so the "no outbound fetch" warning is still correct. Main turns fetch on, and it ships with 0.5.0 (unreleased). This page will need an update at that release, along with readOnly replacing mode and action().
  • I probed runner globals with a throwaway stattic-zero-runner test. atob/btoa are defined. crypto and TextEncoder are undefined with or without the fetch capability. The compiled runtime host adds Headers, Response, URL and URLSearchParams and nothing crypto-related.
  • Anonymous admission only checks for a public Grant with page.view on the path. It doesn't restrict by method, so POSTs to a public write endpoint are admitted.

Checks run locally: check, validate, build, verify:routes, audit, verify:public-safety, and verify:prose with Vale 3.17.1. All clean.

View in Indent View in Slack
Tag @indent to continue the conversation here.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Cover the public-path Grant a provider callback needs on a private Space,
reading the raw body for signature checks, write-only signing keys, and
the runner's missing crypto/TextEncoder with no npm imports on the server.
Drop fetch from the compile-time rejection list; it is absent at runtime,
which the warning already says.
@indent

indent Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor
PR Summary

Adds a "Receiving a webhook" section to the Zero runtime page so readers can tell that Zero endpoints can accept provider callbacks, and fixes related runtime notes.

  • New subsection with an sf.jsonc access.public snippet and a write POST endpoint. The endpoint refuses the request when the signing key is unset, verifies an HMAC signature, and inserts a row.
  • Guidance: open only the webhook path with a public Grant (or sf share grant --to public --path), verify the raw body from req.text()/req.bytes(), keep the signing key write-only in ctx.env and fail closed without it, write your own HMAC because the runner has no crypto/TextEncoder, and note that the same-origin write check only applies to requests that carry a visitor session.
  • Notes that the response helpers' { status, headers } options come last (empty({ status })).
  • Removes the garbled fetch entry from the "Rejected in server/" row. The fetch warning now applies only to sf publish builds, lists atob/btoa and the missing crypto/TextEncoder, and documents the hosted MCP server exception: its handlers get fetch, with open egress on claimed Spaces and an allowlist on unclaimed ones.

Issues

All clear! No issues remaining. 🎉

3 issues already resolved
  • The webhook example calls verifySignature(ctx.env.WEBHOOK_SIGNING_KEY ?? "", ...), so when the variable is missing (for example after sf env set but before the next finalize), anyone can sign a request with the empty key and it passes. The example should reject the request when the key is missing, before it verifies the signature. (fixed by commit afaca03)
  • The page says "Each helper takes an optional { status, headers } second argument", but empty(options?) takes them as its only argument, and ImageResponse options also accept width/height. Change the wording so a reader doesn't write empty(undefined, { status }). (fixed by commit 0176452)
  • The expanded warning says Zero handlers have no fetch. That holds for sf publish with CLI 0.4.1, but the hosted MCP publish tool compiles capsules on the server with the current compiler, which turns fetch on for every handler. Consider limiting the warning to CLI publishes, or noting the difference, so agents that publish through the hosted MCP server don't get contradictory guidance. (fixed by commit 2d366db)

CI Checks

All required CI checks passed on 2d366db.

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 33829041-8872-443d-9dfd-636fd2102af8


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread content/(dynamic)/zero-runtime.mdx Outdated
Comment thread content/(dynamic)/zero-runtime.mdx Outdated
Comment thread content/(dynamic)/zero-runtime.mdx Outdated
Verifying against an empty HMAC key accepts forged events.
The hosted MCP publish tool compiles on the platform, where handlers
already get fetch bounded by the Space's egress scope.

This branch was successfully deployed

1 active deployment
preview/zero-webhook-endpoints — 2d366dba Deployed Sep 26, 2026 by spacefast[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant