calcomblock/CLAUDE.md
Alex Dunmow 18b7825592 Extract calcomblock into a standalone wasm plugin repo
Convert the bundled backend/internal/plugins/calcomblock package into a
standalone reactor-mode wasm plugin, dropping every git.dev.alexdunmow.com/block/cms
import (forbidden in standalone plugins):

- package calcomblock -> package main; add wasip1 main.go with
  wasmguest.Serve(Registration). go.mod module
  git.dev.alexdunmow.com/block/calcomblock, block/core v0.18.2, no replace
  directives.
- Settings persistence: replace the pool-backed poolQuerier (direct SQL against
  the public-schema `settings` table, which a sandboxed plugin role cannot read)
  with capabilityQuerier over the SDK settings.Settings / settings.Updater
  capabilities. GetSiteTimezone now resolves via GetSiteSettings host-side.
- Vendor the small CMS-internal helpers the plugin used into internal/helpers
  (GetRealIP, StartCleanupLoop, MaskSecret, GetStringOr, the PluginSettingsQuerier
  settings helpers, PluginCrypto for tests) and internal/db (minimal Setting /
  UpsertSettingParams), each with a provenance header.
- Inline the captcha widget: vendor blocks.CaptchaWidget as a local
  CaptchaWidget templ (captcha_widget.templ) and regenerate templ; drop the
  block/cms/blocks import from booking.templ.
- blockConfig (server-authoritative captcha requirement via a
  page_block_snapshots scan) has no wasm-ABI capability, so it is left nil:
  honeypot + per-IP rate limit still apply. Documented as a follow-up.
- web: @block-ninja/ui workspace:* -> ^0.1.0 registry version; eslint.config.js
  repointed at ../../../cms/web/eslint.config.js; rebuild web/dist.
- Rewrite CLAUDE.md for the standalone wasm reality; add .gitignore.

Full test suite preserved and passing; builds to calcomblock-2.0.0.bnp;
check-safety passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 03:04:18 +08:00

2.4 KiB

calcomblock plugin

Standalone wasm Cal.com Booking plugin (reactor-mode wasip1, packed into a .bnp and hot-loaded by the CMS). Registers the calcom:booking block plus a chi HTTP handler mounted at /api/plugins/calcomblock/ (public booking + slots

  • webhook endpoints, admin-gated settings/test/event-types). The block editor is a Vite / Module-Federation bundle in web/ (exposed as remoteEntry.js), served host-side from the .bnp at /plugins/calcomblock/.

Extracted from the former bundled cms/backend/internal/plugins/calcomblock. The old .so/Air/go:embed workflow is gone — see ~/src/blockninja/plugins/AGENTS.md and the developing-blockninja-plugins skill for the current build/publish loop.

SDK boundary

Only git.dev.alexdunmow.com/block/core/... is importable — never block/cms/.... Two small things that used to come from cms/internal are vendored under internal/ with provenance headers:

  • internal/helpersGetRealIP, StartCleanupLoop, MaskSecret, GetStringOr, the PluginSettingsQuerier settings helpers, and a PluginCrypto (AES-256-GCM) used only by tests.
  • internal/db — the minimal Setting / UpsertSettingParams structs the settings helpers reference.

Settings persistence (wasm sandbox)

Settings go through the SDK settings capabilities, NOT direct SQL: a plugin's Postgres role is sandboxed to its own schema, so the CMS settings table (public schema) is unreachable. capabilityQuerier (settings_store.go) adapts settings.Settings / settings.Updater to the PluginSettingsQuerier interface and is wired in NewCalcomRouter.

Known limitation

The server-authoritative captcha requirement (CalcomBookingRequiresCaptcha, which scanned published page_block_snapshots) has no wasm-ABI capability equivalent, so blockConfig is nil: an enabled booking block still enforces the honeypot + per-IP rate limit, but the published-content captcha gate is not re-derived server-side. Restoring it needs a core capability exposing published-block content across the ABI.

Frontend

cd web && node node_modules/vite/bin/vite.js build   # rebuild dist (pnpm's run-wrapper
                                                     # trips on ignored build scripts)

web/dist IS committed and packed into the .bnp; rebuild it before ninja plugin build. @block-ninja/ui installs from the scoped Gitea registry (^0.1.0), not a workspace link.