# 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.
