Testing and validation
Every behavior that changes authorization, rendering mode, schemas, document persistence, theme migration, plugin declaration, or MCP visibility needs an automated test in its owning package.
Test count is not a quality target. Add a focused test for both the expected path and the security/failure boundary whenever a behavior changes.
Required checks
Run these commands from the repository root before committing:
pnpm test
pnpm check
pnpm build
pnpm test runs Vitest contract/adapter/security tests, real-workerd Cloudflare suites, and Chromium E2E. pnpm check runs TypeScript checks and astro check; pnpm build proves every workspace package type-checks and that the Morning Bell Astro example builds for the Cloudflare adapter. See Security validation for the binding and browser coverage.
The build also bundles every dedicated Worker with wrangler deploy --dry-run, including tenant workspace, plugin sandbox, and the physically separate public/private MCP services. The Astro deployment can be dry-run from its generated dist/server/wrangler.json, proving that static assets, D1, R2 media, session secrets, and remote service/Object namespaces do not collide.
Test boundaries
- Contracts: schema limits, the complete built-in marketing component catalog, page collection invariants, theme migration reports, role permissions, plugin manifests, and sensitive data-scope rules.
- Runtime: published requests bypass authentication; preview/edit require authorization and are private/no-store.
- Content and hosting adapter: draft-only changes, schema validation, section identity, optimistic versions, actor attribution, and publish delegation.
- Theme migration: explicit loss/addition decisions and schema-approved default sections.
- Theme persistence: validated site pins, paired migrated-draft calls, paired publication, and cross-tenant rejection.
- Forms: published-definition field allowlists, type checks, required values, and bounded text input.
- Site resources: navigation identity/limits, deep settings patches, and duplicate/cyclic redirect rejection.
- Page lifecycle: every approved template, stable duplicate identities, route/SEO updates, navigation synchronization, redirect creation/retargeting, total-order validation, and protected home/unique slug invariants.
- Resource persistence: schema revalidation, optimistic resource versions, independent publish state, actor attribution, and tenant-scope rejection.
- Atomic page bundle persistence: real SQLite transaction commit for pages/navigation/redirects, rollback on any stale version, and atomic publication of all three resources.
- Guarded commands: tenant scope, permission denial, explicit confirmations, exclusive concurrent claims, failure release, idempotent replay, and tenant-scoped ledger/audit persistence.
- Editor reference flow: content, approved variant and structural drafts, idempotent replay, confirmed publication, and published-snapshot isolation.
- MCP gateways: public tool/resource/prompt filtering, real protocol discovery, public rate limits, and private tools routed through guarded commands.
- MCP OAuth: supported-scope filtering, write-scope removal for viewer roles, one-time upstream state, same-origin/CSRF consent, grant ownership checks, and revocation.
- Structural editing: component structure policy, target identity, destination validity, and instance limits.
- Assets: tenant/site-scoped keys, per-kind MIME/size policy, image/video/document signatures, exact streamed-byte validation, attachment disposition, and immutable R2 metadata.
- External embeds: approved YouTube URL/iframe normalization, exact-host and HTTPS enforcement, malformed/lookalike rejection, raw-HTML elimination, canonical privacy-enhanced rendering, and upload/embed mutual exclusion.
- Auth: signed session integrity and expiration.
- Browser session boundary: signed-cookie identity conversion, strict cookie attributes, missing/cross-origin mutation rejection.
- OAuth and provisioning: S256 PKCE/state hashing, one-time/expired state, bounded token/UserInfo exchange, external identity mapping, revocable sessions, verified idempotent site creation, and conflict detection.
- Media pipeline: tenant-scoped allocation, streaming byte limits, image-signature mismatch quarantine, transformation bounds, cross-tenant rejection, schema-validated replacement, and immutable delivery metadata.
- CMS management: bounded JSON bodies, D1 invitation conflict checks, typed resource limits, form-definition validation, guarded resource publishing/restore, and reserved-path public-cache exclusion.
- Publish operations: version-addressed public indexing, cache invalidation, after-publish hooks, schedule version conflicts, supersession, bounded backoff, retry/dead-letter state, and confirmed status actions.
- Operations: real-R2 checksummed tenant backup/restore, per-user editor mutation quotas, usage accounting, read-only routing state, fixed retention tables, and private asynchronous cross-store erasure boundaries.
- Hosted service: host-neutral orchestration success/failure, exact DNS challenges, private deployer-binding responses, D1 environment/deployment/domain state, secret-reference-only persistence, grant role/expiry checks, and support-session denial without an active grant.
- Plugin supply chain: normalized release signatures, signer allowlists, artifact digest binding, tamper rejection, declarative migration limits, explicit sandbox service calls, and a non-public sandbox build.
- Cloudflare private boundary: host-derived scope, permission checks, cross-origin rejection before session work, cross-tenant non-disclosure, and private/no-store failures.
- MCP: public/private catalog filtering and role-gated engagement tools.
- Plugin SDK: manifest validation at plugin definition time, including MCP tool/resource/prompt access policies.
- Plugin runtime: declared-capability checks, declared/implemented hook matching, bounded hook execution, and declared storage namespaces.
- CLI scaffolds and deployment profiles: portable names, path containment, build/secret exclusion, atomic five-page site creation, built-in component/theme seeds, dry-run and overwrite controls, command parsing, two-to-five Worker profile selection, optional service-binding removal, diagnostics, and every generated artifact shape.
- Agency five-page browser flow: all five public routes, shared navigation, no anonymous edit metadata, theme marker, valid contact submission, extension entry, non-home draft isolation, preview, and publication. Browser acceptance also creates a Services page, verifies its four typed components and draft navigation, renames and publishes it, then deletes it and verifies both former paths redirect to the chosen surviving page.
- Project sites: the documentation and marketing sites define explicit desktop, tablet, and mobile layouts; navigation remains keyboard- and touch-operable; primary targets meet a 44-pixel minimum; hover enhancements are limited to hover-capable pointers; and reduced-motion preferences disable decorative movement.
The real-workerd gate now covers D1 migrations/routing, SQLite Durable Object identity isolation, R2 key separation and checksummed backup restore, Cache API invalidation, queue delivery, public KV indexing, mutation quotas, and public MCP Streamable HTTP startup. Full upstream OAuth exchange against an installation’s chosen identity provider, destructive disposable-tenant drills, and deployed Cloudflare account smoke tests remain environment-specific release checks; local tests cover their cryptographic, state, mapping, scope, authorization, and binding boundaries.