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

53 lines
2.4 KiB
Markdown

# 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/helpers``GetRealIP`, `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
```bash
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.