Skip to content

feat(platform): add webhooks module to the server entrypoint - #319

Merged
ozsay merged 8 commits into
mainfrom
feat/platform-server-webhooks
Oct 18, 2026
Merged

ozsay merged 8 commits into
mainfrom
feat/platform-server-webhooks

Conversation

@ozsay

@ozsay ozsay commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #316 (base is that branch; retarget to main once it merges).

Summary

  • platform.webhooks.verifyEvent(rawBody, headers, { publicKeys, toleranceSeconds? }) verifies Standard Webhooks v1a (Ed25519) signatures with WebCrypto only, so it runs on Node 20+, Deno, Bun and edge runtimes. Returns a typed WebhookEvent; nothing is parsed before the signature passes. Makes no network calls.
  • platform.webhooks.createHandler({ publicKeys, on, onEvent, onSuccess, onError, toleranceSeconds? }) returns a fetch-style (request: Request) => Promise<Response>:
    • reads the raw body, verifies, and answers the webhook.test.v1 activation challenge itself (callbacks never see the probe);
    • runs onEvent, then the per-type handler from on (event narrowed per key), then onSuccess;
    • responds 204 on success (including types without a handler and unknown types), 400 on a verification failure, 500 on misconfigured keys (receiver_misconfigured), an unreadable body (request_failed) or a throwing callback (handler_failed);
    • onSuccess / onError may return a Response to override the default.
  • Errors: WebhookVerificationError (400) vs WebhookConfigurationError (missing/malformed keys, or unsupported_runtime when WebCrypto can't import Ed25519; 500). Base44 retries any non-2xx; the status only shows which side failed in its delivery log.
  • Unknown event types arrive as { type: "unknown", name, data }, matching the client's PlatformEvent; onEvent and on.unknown receive them, and they're answered 204.
  • Configuration: createPlatformServer() takes no options (nothing in the server entrypoint calls an API, so receivers need no API key). Each module takes what it needs per call. The webhooks module takes publicKeys on every call that verifies (verifyEvent, createHandler); there is no module-level init/config. No env reads, no key fetching.
  • Types: per-event data interfaces and WebhookEventMap are generated from the schemas published at https://base44.com/webhooks/schemas by npm run generate:webhooks (event list in scripts/webhook-event-types.json; --from <dir> for a local apper checkout).
  • Adds engines.node >=20, README section, two examples (verifyEvent + switch, and createHandler), and json-schema-to-typescript as a devDependency.
  • Mintlify reference: the server entrypoint is now in the reference. The pipeline expects one flat TypeDoc module, so a docs-only entry (scripts/mintlify-post-processing/reference.ts, with its own tsconfig.docs.json so nothing ships in dist) re-exports both entrypoints. New pages are createPlatformServer, the webhooks module, and the two webhook error classes with their codes. The functions nav group is renamed from "Client" to "Clients". The client's pages are byte-identical to main's output. Server JSDoc was rewritten to the docs guidelines.

Test plan

  • npm test -w @base44/platform (type tests incl. per-handler narrowing, 63 unit tests incl. tamper/relabel/stale/rotation/config and handler status/callback ordering, typedoc, packed-package runtime and declaration checks)
  • npm run create-docs -w @base44/platform; client pages diffed against main's output (identical)
  • npx eslint packages/platform

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/sdk@0.8.54-pr.319.a12cfb1

Prefer not to change any import paths? Install using npm alias so your code still imports @base44/sdk:

npm i "@base44/sdk@npm:@base44-preview/sdk@0.8.54-pr.319.a12cfb1"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "@base44/sdk": "npm:@base44-preview/sdk@0.8.54-pr.319.a12cfb1"
  }
}

Preview published to npm registry — try new features instantly!

@ozsay ozsay mentioned this pull request Oct 12, 2026
2 of 4 tasks
@ozsay
ozsay force-pushed the feat/platform-server-webhooks branch from d85e70c to 9b2915b Compare October 12, 2026 11:41
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Package Preview Available! (@base44/platform)


Install this PR's preview build with npm:

npm i @base44-preview/platform@0.2.0-pr.319.a12cfb1

Prefer not to change any import paths? Install using npm alias so your code still imports @base44/platform:

npm i "@base44/platform@npm:@base44-preview/platform@0.2.0-pr.319.a12cfb1"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "@base44/platform": "npm:@base44-preview/platform@0.2.0-pr.319.a12cfb1"
  }
}

Preview published to npm registry — try new features instantly!

@ozsay
ozsay force-pushed the feat/platform-server-webhooks branch 2 times, most recently from f0a1592 to 75a4b1c Compare October 12, 2026 12:08
@ozsay
ozsay added this pull request to stack #321 October 12, 2026 12:08
@ozsay
ozsay force-pushed the feat/platform-server-webhooks branch from bf7e148 to aa2094c Compare October 14, 2026 07:20
@ozsay
ozsay force-pushed the feat/platform-server-webhooks branch from aa2094c to 3576c90 Compare October 14, 2026 07:59
@ozsay
ozsay force-pushed the feat/platform-server-webhooks branch from 7bacfa2 to 1dd7d58 Compare October 15, 2026 07:33
Base automatically changed from feat/platform-server-entrypoint to main October 15, 2026 07:34
ozsay and others added 4 commits October 15, 2026 10:34
verifyEvent checks Standard Webhooks v1a (Ed25519, WebCrypto) signatures
and returns a typed event; handleChallenge answers the activation probe.
Event types are generated from the published JSON Schemas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
createHandler returns a fetch-style route handler that verifies, answers
the activation challenge, dispatches per event type and maps outcomes to
status codes, with onEvent/onSuccess/onError callbacks. verifyEvent stays
for callers who dispatch themselves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tory

createPlatformServer keeps only the shared serverUrl/apiKey.
verifyEvent and createHandler now require publicKeys in their options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Mintlify post-processing expects one flat TypeDoc module, so a
docs-only entry (scripts/mintlify-post-processing/reference.ts, with its
own tsconfig so nothing ships in dist) re-exports the client and server
entrypoints. Adds pages for createPlatformServer, the webhooks module and
both webhook error classes, and renames the functions group to Clients.
Client pages are byte-identical to before.

Rewrites the server JSDoc to the docs guidelines: verb-phrase summaries,
@param/@returns/@throws/@example, per-code guidance on the error codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ozsay
ozsay force-pushed the feat/platform-server-webhooks branch from 1dd7d58 to 4dc905f Compare October 15, 2026 07:34
ozsay and others added 2 commits October 15, 2026 10:45
…DMEs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread packages/platform/src/server/server.ts
Comment thread packages/platform/src/server/modules/webhooks.types.ts Outdated
Comment thread packages/platform/src/server/modules/webhooks.types.ts Outdated
Comment thread packages/platform/src/server/modules/webhooks.ts Outdated
- createPlatformServer() takes no options: serverUrl and apiKey were
  validated but never used, and receivers need only the public keys.
- Event types this SDK doesn't know arrive as { type: "unknown", name,
  data }, like the client's PlatformEvent, so known types keep narrowing
  and unknown ones can be logged. on.unknown handles them in createHandler.
- One retry rule in the docs: Base44 retries any non-2xx answer; 400 vs
  500 only shows in its delivery log which side failed.
- A failed Ed25519 key import is a WebhookConfigurationError
  (unsupported_runtime) and is evicted from the cache; a failed body read
  answers 500 request_failed instead of handler_failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ozsay
ozsay requested a review from NitzanSirota October 15, 2026 09:58
Comment thread packages/platform/src/server/index.ts Outdated
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ozsay
ozsay merged commit 81b0edb into main Oct 18, 2026
8 checks passed
amitbardos added a commit that referenced this pull request Oct 18, 2026
main added the webhooks module to @base44/platform/server (#319). The
package.json conflict keeps main's engines field beside this branch's single
devDependencies block; the lockfile is main's plus the React dev
dependencies, resolved from registry.npmjs.org.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants