Skip to content
MNPPI on GitHub

Cloudflare flagship stack

The default stack and operating controls for new MNPPI projects on Cloudflare.

Status
Current
Reviewed
July 23, 2026
Cadence
Review each quarter
Source
org-standards

The current MNPPI core stack remains the default Cloudflare architecture.

Keep pnpm, Workers Static Assets, Astro, React, Vite, Hono, D1, Drizzle, and Cloudflare-native services.

This standard adds required controls for:

  • GitHub governance.
  • Continuous integration.
  • Self-hosted runners.
  • Cloudflare build and deployment.
  • Release recovery.
  • Route exposure.
  • Runtime configuration.
  • Application programming interfaces.
  • Database changes.
  • Authentication and authorization.
  • Background work.
  • Observability.
  • Resource budgets.

The architecture standard is current. Each adopting project must pass the applicable acceptance checks.

SeekTheChurch completed its dev and staging migration on 2026-07-23. It retired Next.js and OpenNext from the application build.

The staging application now uses:

  • Astro static output for help and legal pages.
  • React and Vite for the shared-state application.
  • Workers Static Assets with scoped Worker-first paths.
  • Hono for same-origin application programming interfaces.
  • D1 through the app-owned Drizzle database boundary.
  • Cloudflare Workers Builds for the app and isolated ingest Worker.

The protected main branch and production environment have not completed cutover. The remaining standard gates are listed in the acceptance section.

This standard applies to new MNPPI production projects that use Cloudflare Workers.

Existing projects adopt the controls through a measured migration. Do not force a framework migration when the current architecture remains safe and supported.

Each project must record its selected profile:

  • Static site.
  • Static site with Worker application programming interfaces.
  • Interactive single-page application.
  • Multi-Worker application.
  • Background-processing application.
  • Stateful application.
  • High-risk application.

A high-risk application handles money, regulated data, privileged administration, or destructive automation. High-risk projects can use stricter controls than this baseline.

The terms must and must not identify required controls. The term should identifies the normal choice. An approved exception can replace a should rule.

An exception to a must rule requires:

  • One named owner.
  • One documented reason.
  • A limited scope.
  • A review date.
  • A rollback plan.
  • An expiration or permanent decision.

MNPPI/org-standards owns the versioned desired state.

It owns:

  • Required workflows.
  • Repository ruleset definitions.
  • Repository properties.
  • Renovate policy.
  • Runner policy.
  • Cloudflare configuration records.
  • Governance and drift audits.
  • Reference applications.
  • Exception records.

GitHub rulesets provide live merge enforcement. Cloudflare Workers Builds provides live production build and deployment.

Documentation alone does not prove enforcement. Audits must compare the desired state with live GitHub and Cloudflare settings.

Layer Organization standard
Package manager pnpm workspaces with a pinned package manager
Runtime Cloudflare Workers with a current compatibility date
Static delivery Workers Static Assets with asset-first routing
Static pages Astro static output
Interactive application React with Vite
Small interactions Astro with React islands
Cloudflare development @cloudflare/vite-plugin for Vite Worker projects
Worker tests @cloudflare/vitest-pool-workers
Client server state TanStack Query when the application needs remote-state management
Client routing TanStack Router for new non-trivial single-page applications
HTTP API Hono with Zod validation
Database D1 through a database package that uses Drizzle
Object storage R2
Configuration cache KV only for suitable eventual-consistency use
Background work Queues for buffered work and Workflows for durable multi-step work
Stateful coordination Durable Objects for serialized per-entity state
Staff authentication Cloudflare Access
Public authentication Magic links for verification or Better Auth for application sessions
Styling Tailwind CSS v4 with shadcn/ui and approved design tokens
Merge authority GitHub Actions and GitHub rulesets
Release build Cloudflare Workers Builds
Production deployment Cloudflare Workers Builds
Observability Workers Logs, release metadata, runtime measures, and approved trace pilots

Every protected branch must require a pull request.

The organization uses a sole-owner merge model. The repository owner can merge their own pull request after all required checks pass.

The baseline requires:

  • Zero approving reviews.
  • All required checks to pass.
  • The branch to be current.
  • All review conversations to be resolved.
  • No force pushes.
  • No protected-branch deletion.
  • No ruleset bypass actors.
  • Squash merge.
  • Linear history.

Do not require Code Owner approval. Do not add a required deployment reviewer that blocks the sole owner.

Rulesets should target ~DEFAULT_BRANCH. Protect every non-default production or promotion branch explicitly.

Repositories that use merge queues must run required workflows for pull_request and merge_group.

Each repository must expose one stable aggregate check.

The aggregate must:

  • Run for every protected pull request.
  • Use if: always() when it depends on other jobs.
  • Reject every unsuccessful mandatory dependency.
  • Keep one stable check name.
  • Avoid path-based absence.
  • Exclude advisory checks from its success decision.

Cloudflare build results must not replace the GitHub merge check.

GitHub Actions must use:

  • Read-only permissions by default.
  • Job-specific write permissions.
  • Full commit identifiers for actions and reusable workflows.
  • persist-credentials: false for checkout.
  • Frozen dependency installation.
  • Time limits for every job.
  • Concurrency controls where duplicate work has a cost or side effect.

Privileged workflows must not execute untrusted pull-request code. Do not use pull_request_target to check out and run pull-request content.

Mandatory jobs must not use continue-on-error. Secrets must exist only in the job or step that needs them.

Each project must select all applicable checks:

  • Tokenless frozen installation.
  • Formatting.
  • Lint.
  • Type checking.
  • Unit tests.
  • Worker runtime integration tests.
  • Application build validation.
  • Local D1 migration validation.
  • Static-route Worker-invocation tests.
  • Wrangler package dry run.
  • Workflow syntax and security checks.
  • Secret scanning.
  • Dependency vulnerability review.
  • Software bill of materials generation when useful.
  • Bundle and startup-time budgets.

A GitHub validation build is disposable. Cloudflare creates the authoritative production build.

Private trusted repositories can use MNPPI self-hosted runners. Public repositories and fork pull requests must use standard GitHub-hosted runners.

Jobs must use an approved runner group and purpose label. Runner labels identify routing. They do not prove isolation.

The current persistent pool is a documented migration state. The future pool should use one-job, just-in-time runners.

Disposable runners must:

  • Use one clean environment for each job.
  • Run as a non-root host user.
  • Avoid the host Docker socket.
  • Avoid privileged containers.
  • Avoid host directory mounts.
  • Apply resource limits.
  • Remove the container and workspace after the job.
  • Forward diagnostic logs.
  • Keep production credentials off the host.

Queued jobs must wait for their designated runner. Do not change labels, runners, or execution locations to bypass a queue. Do not cancel and resubmit jobs to improve queue position.

Use the public runner security standard with the internal runner topology and pilot records.

GitHub Actions decides whether code can merge. Cloudflare Workers Builds builds and deploys approved commits.

GitHub Actions must not contain the normal production deployment path. GitHub Actions must not contain routine production Cloudflare credentials.

Routine local production deployment is prohibited. An emergency command requires a documented break-glass procedure.

Production Workers Builds must use:

  • The actual protected production branch.
  • An explicit project root.
  • Pinned Node.js, pnpm, and Wrangler versions.
  • A tokenless frozen installation.
  • A minimal build command.
  • A deployment command that contains only approved release operations.
  • Reviewed build watch paths.
  • A dedicated least-privilege Cloudflare user token.

Cloudflare currently requires a user token for Workers Builds. Record this as an exception to the normal account-token preference.

Disable non-production branch builds by default. Disable Deploy Hooks by default. Treat a Deploy Hook address as a bearer credential.

Build watch paths control cost and noise. They are not a security boundary.

org-standards must record and audit:

  • Repository.
  • Branch.
  • Root directory.
  • Build command.
  • Deployment command.
  • Watch paths.
  • Runtime versions.
  • Token owner.
  • Worker name.
  • Environment.

A retried build uses the current Cloudflare settings. The release record must identify the settings version used for the retry.

Normal flagship projects do not require artifact signing or attestation.

Record these identifiers when Cloudflare provides them:

  • Git commit.
  • Cloudflare build identifier.
  • Worker version identifier.
  • Deployment time.
  • Health-check result.

Do not add exact-byte proof unless a customer, regulation, or high-risk profile requires it.

Use three release phases:

  1. GitHub validates the proposed change.
  2. Cloudflare builds and deploys the approved commit.
  3. Runtime checks verify identity and health.

A post-deployment failure is a release incident. It is not a failed merge check.

Each project must define:

  • A health check.
  • An error threshold.
  • A latency threshold.
  • A rollback trigger.
  • A forward-recovery path.
  • A release owner.

High-risk Workers should use version upload, smoke tests, and gradual promotion.

A Worker rollback does not restore D1, KV, R2, Queue, or Durable Object state.

Use expand-and-contract database changes:

  1. Add the new structure.
  2. Deploy code that supports the old and new structure.
  3. Migrate or backfill data.
  4. Verify the new structure.
  5. Remove the old structure in a later release.

Do not include an automatic destructive migration in a normal deployment.

Risky D1 changes require:

  • A reviewed migration.
  • Local continuous integration validation.
  • A Time Travel bookmark.
  • Old and new code compatibility.
  • A forward-recovery plan.

Workers Static Assets must serve a matching public asset before Worker code runs.

Use assets.run_worker_first as a path-pattern array for reviewed dynamic paths. Do not set run_worker_first: true for a complete site without measured evidence.

Each route inventory must record:

  • Delivery type.
  • Allowed methods.
  • Authentication.
  • Authorization.
  • Cache policy.
  • Worker invocation.
  • Failure response.
  • Owner.

Set html_handling explicitly. Set not_found_handling explicitly.

An unknown application programming interface route must not return the single-page application shell.

Test that representative public assets do not invoke the Worker. Confirm the result with post-deployment analytics.

_headers applies to Static Asset responses. Worker-generated responses must set their own security headers.

Cloudflare Access protects configured hostnames and paths. It does not automatically protect every project address.

Set workers_dev and preview_urls explicitly for every environment. Disable them when they are not needed. Otherwise, apply equivalent Access controls.

Cloudflare Access authenticates a caller. Application code must still enforce authorization.

Use @cloudflare/vite-plugin for Vite Worker projects.

The Vite plugin runs Worker code in workerd during vite dev and vite preview. It does not provide the Worker test runtime by itself.

Use @cloudflare/vitest-pool-workers for Worker integration tests.

Maintain one reference application. It must prove:

  • Vite.
  • React.
  • Hono.
  • Static Assets.
  • Worker bindings.
  • Environment selection.
  • Local tests.
  • Production packaging.

Vite selects a Cloudflare environment during the build. Do not assume a later Wrangler environment flag changes an already built output.

Use wrangler.jsonc as the committed configuration source.

New Workers must use:

  • A current compatibility_date.
  • The nodejs_compat compatibility flag.
  • Generated binding types from wrangler types.
  • Explicit environment bindings.
  • Explicit environment variables.
  • Explicit routes and domains.
  • Explicit workers_dev and preview settings.

Do not maintain a hand-written Worker Env interface. Run wrangler types --check in continuous integration.

Bindings and variables do not automatically inherit between environments. Test every staging and production binding name.

Store runtime secrets through Cloudflare secret controls. Do not store a secret value in vars.

Local values must use ignored files and the MNPPI Keychain and direnv pattern.

Use Astro as the static default. Use React islands for small interactive sections. Use a React single-page application for a shared client-state application.

Use TanStack Query when the application needs remote-state caching, retries, or invalidation. Do not add it to a static page without a product need.

Use TanStack Router for a new non-trivial single-page application. Do not replace a correct framework router without a migration reason.

Allow one combined Worker deployment when it keeps routing simple. Use separate Workers when security, ownership, or scale requires isolation.

Application programming interface contract

Section titled “Application programming interface contract”

Use Hono for new HTTP application programming interfaces. Use Zod at every untrusted boundary.

Validate:

  • Path parameters.
  • Query parameters.
  • Request bodies.
  • Relevant headers.
  • Webhook messages.
  • Queue messages.
  • Environment values.

Set request size and content-type limits.

Mutating endpoints must define:

  • Authentication.
  • Authorization.
  • Idempotency.
  • Error responses.
  • Timeout behavior.
  • Retry behavior.

Use Hono typed clients inside the same repository. Publish OpenAPI for an independent client, integration, or long-lived shared contract.

Use Cloudflare bindings instead of Cloudflare REST calls from Worker code. Use service binding remote procedure calls between Workers.

A service binding is a trusted transport. The receiving Worker must still enforce its caller and operation policy.

Use Cloudflare Access for workforce identity. Do not use it as the complete application authorization system.

Application sessions must define:

  • Secure and HTTP-only cookies.
  • SameSite behavior.
  • Session expiration.
  • Session revocation.
  • Cross-Site Request Forgery protection.
  • Account recovery.
  • Replay protection.

Public authentication must limit enumeration and repeated attempts. Use Turnstile or another approved abuse control where measured risk requires it.

Every public application must define:

  • Cross-Origin Resource Sharing policy.
  • Content Security Policy.
  • Security headers.
  • Rate limits.
  • Webhook signature validation.
  • Webhook replay prevention.

Feature code must use the project database package. The database package should use Drizzle for normal D1 queries.

Direct D1 access outside the database package is prohibited.

The database package can use a reviewed D1 platform application programming interface when Drizzle lacks a required function. It can also use reviewed parameterized SQL.

Each exception must include:

  • The missing Drizzle capability.
  • The contained implementation location.
  • Tests.
  • An owner.
  • A review date.

Drizzle Kit should generate committed migration files. Review every generated migration.

Do not change a migration after an environment applies it. Hand-authored migration SQL is allowed when a safe change requires it.

Use db.batch() for supported atomic groups. Review indexes and query plans for critical queries. Set rows-read and rows-written budgets for high-volume paths.

D1 read replication requires the Sessions API. Keep it as an organization pilot until the database package supports the required consistency model.

Cloudflare Queues provide at-least-once delivery.

Every Queue consumer must:

  • Be idempotent.
  • Set retry limits.
  • Use a dead-letter queue in production.
  • Handle poison messages.
  • Use partial acknowledgement when suitable.
  • Monitor depth, age, retries, and dead-letter growth.

Use Workflows for durable multi-step operations.

Workflow steps must:

  • Be deterministic.
  • Be idempotent.
  • Await each step.
  • Remain compatible with active instances.
  • Keep side effects inside reviewed step boundaries.

Use Durable Objects for serialized per-entity state.

Do not use one global object for unrelated tenants. New Durable Objects should use SQLite storage and remote procedure calls.

Alarms must be idempotent. Durable Object migrations require a separate release review. Class deletion can permanently delete state.

Use waitUntil() only for short, best-effort post-response work. Do not use it for required business processing.

Workers Logs are required in production. Automatic Workers Traces remain a controlled pilot.

Each project must define:

  • Log sampling by environment.
  • Trace sampling when traces are enabled.
  • Personal-data and secret redaction.
  • Release and Worker version fields.
  • Error alerts.
  • Latency alerts.
  • Retention or export.
  • A telemetry cost budget.

Use structured log records. Do not write secret values, session tokens, or unnecessary personal data.

GitHub continuous integration must record:

  • Compressed Worker size.
  • Worker startup time.
  • Static-route invocation proof.
  • Binding and type validation.
  • Platform-limit validation.

The organization warning threshold is 50 percent of the applicable bundle ceiling. The organization blocking threshold is 75 percent of that ceiling.

The startup-time warning threshold is 500 milliseconds. The startup-time blocking threshold is 750 milliseconds.

Projects can set stricter limits.

Runtime monitoring must record:

  • CPU p50, p95, and p99.
  • Request errors and exceptions.
  • Latency.
  • Memory pressure.
  • Subrequest use.
  • Queue backlog.

Each Worker must set an approved limits.cpu_ms value. Set the value from the route class and measured workload.

The project must set numeric CPU and latency budgets before production. Do not copy one CPU value into every application.

Static asset requests must not invoke Worker code unless a reviewed route requires it.

Being current does not require every new Cloudflare feature. Use stable features after reference validation. Use preview or beta features through measured pilots.

Feature Organization position Decision
Vite 8 Current stable Adopt after the reference application passes.
Cloudflare Vite plugin Approved Use for Vite Worker projects.
Workers Static Assets Approved Use for new sites and asset-heavy applications.
Workers Builds Approved with audit Use for production build and deployment after protected merges.
Workers Logs Approved Require in production.
Automatic Workers Traces Beta Use through an approved sampling and cost pilot.
Workers Vitest integration Beta tooling Use for Worker-runtime tests and track known limitations.
D1 read replication Organization pilot Require Sessions API support and a defined consistency model.
Smart Placement Beta Pilot only when latency and CPU data can show the result.
Secrets Store Open beta Track it and keep Worker secrets as the baseline.
Workflows Approved with budget Use for durable multi-step work with cost and recovery controls.
Durable Objects with SQLite Approved Use for new per-entity state.
TanStack Start on Workers Supported option Use only when the product proves a server-render requirement.
React Server Components Controlled option Do not use as the static-first baseline.

A platform pilot must:

  • Have one owner.
  • Have one reversible scope.
  • Define success measures.
  • Define rollback measures.
  • Measure CPU, latency, errors, cost, and operating effort.
  • Avoid unnecessary production data risk.
  • Produce a written adoption decision.

These versions were current in the public package registry on 2026-07-22. They are review evidence and not permanent policy pins.

Package Reviewed version
React 19.2.8
Vite 8.1.5
Astro 7.1.3
Hono 4.12.31
Drizzle ORM 0.45.2
Drizzle Kit 0.31.10
@cloudflare/vite-plugin 1.46.0
Wrangler 4.113.0
TanStack Query 5.101.4
TanStack Router 1.170.18
Tailwind CSS 4.3.3
shadcn 4.14.0

Use Renovate and the reference application to keep approved versions current. Do not copy this version snapshot into a permanent package policy.

Review this standard:

  • Every quarter.
  • After a material Cloudflare platform change.
  • After a material GitHub Actions change.
  • After a Node.js, pnpm, Vite, or framework major release.
  • After a significant security incident.

Each review must record:

  • Review date.
  • Owner.
  • Primary sources.
  • Changed decisions.
  • Deprecated decisions.
  • Active exceptions.
  • Required migrations.

A project can claim conformance with this standard when:

  • One reference application passes the approved Vite test matrix.
  • Static routes show no Worker invocation.
  • Dynamic routes use explicit path patterns.
  • Unknown application programming interface routes do not return an application shell.
  • Runtime database code follows the database-package boundary.
  • Every migration passes local validation.
  • wrangler types --check passes.
  • Workers Logs are enabled.
  • Resource budgets have numeric project values.
  • GitHub enforces the merge contract.
  • The repository owner can merge their own pull request after checks pass.
  • The just-in-time runner canary passes and cleans itself.
  • Workers Builds is the only normal production build and deployment authority.
  • The release record links the commit, build, version, and health result.
  • The rollback and data-recovery runbooks pass a review.

SeekTheChurch completed the architecture migration while this candidate standard was under review. Its final delta review must close the remaining gates before production cutover.