Files
dckc 4b4ef8fea6 capsite: potluck, a fresh EmDash site (cloudflare:blog out of the box)
pnpm create emdash@latest potluck --pm pnpm --install --yes, per
https://docs.emdashcms.com/ ("Create your first EmDash site"); the
--yes defaults are cloudflare + blog. Replaces the old madmode/
starter (never committed).

Generated-by: create-emdash 1.2.0, run by Claude Opus 5.5
2026-10-07 19:57:43 -05:00

3.6 KiB

Sandbox boundaries

Registry plugins run against a capability-gated host API, not the complete trusted EmDash runtime. Design within exported authoring types and do not infer an API from internal repositories or admin routes.

Transport limits

  • ctx.http.fetch() preserves binary requests and responses across both runners, but complete bodies are buffered and limited to 8 MiB of decoded bytes.
  • Declared plugin route bodies are buffered with a 1 MiB default and 8 MiB author maximum. Raw route responses are buffered to 8 MiB.
  • Media byte reads default to 10 MiB and cannot request more than 16 MiB.
  • Neither test host reproduces deployed CPU, memory, or subrequest limits.

Trusted-only surfaces

  • page:fragments is accepted by shared authoring types but excluded from sandbox registration. Use validated page:metadata; raw HTML, scripts, and styles require a trusted native plugin.
  • React admin code, Astro render components, build-time integrations, host bindings, Node built-ins, TCP sockets, and direct database access require trusted site code.
  • Custom Portable Text definitions and Astro renderers remain native-only. Registry packages can use the declarative admin surfaces that the CLI serializes.

Content and schema limits

  • Schema access is read-only. Plugins cannot create, alter, attach, or delete collection definitions through ctx.schema.
  • Content writes do not expose permanent deletion.
  • Publication policy hooks can reject publish, schedule, and unpublish, but cannot transform the action or restore content.
  • Publication and restore actions require separate capabilities and opaque revisions.
  • Public URL resolution never returns previews.

Taxonomy, redirect, comment, and media limits

  • Taxonomy writes cannot manage definitions, attachments, term updates or deletion, or replace all assignments.
  • Redirect writes cannot set host-owned fields and remain subject to host validation.
  • Comment administration excludes trashed comments and linked user-account IDs. It cannot hard-delete or bulk-replace statuses.
  • Media metadata writes cannot upload, replace, move, or delete files. Byte reads and content hashes require separate authority.

Routes and admin UI

  • public: true removes host authentication. It does not create a restricted public view; validate requests and return the minimum data.
  • Raw routes use pluginResponse(), an allowlisted set of representation/download/redirect headers, host-owned caching and security headers, and no active same-origin browser content. They cannot back MCP tools.
  • Credential, cookie, Cloudflare Access, proxy authorization, and EmDash CSRF headers never cross declared route-header boundaries.
  • Saved-entry panels and actions receive canonical saved identity and version. Ordinary panel load and typing never send unsaved state. An explicit interaction can receive only extension-selected draft fields with admin.editor-draft:read, and can propose an atomic whole-field patch with the independent admin.editor-draft:patch capability. The host validates and previews a patch but never saves it automatically. Use capability-gated APIs to read saved content.
  • routeCtx.ui carries host-attested admin locale, direction, and surface. Manifest labels remain static strings; the host does not consume plugin translation catalogs.

Runner-only methods are not portable

Methods absent from public authoring types are not part of the registry contract even if one wrapper contains them. Write against SandboxedPlugin and exported context types, then test the feature through both bridges when behavior is runner-sensitive.