Cloudflare API execution
worker.ts dispatches native Request/Hono API routes directly, using the same
route exports and authorization helpers as Next.js. MCP, operation HTTP
projections, memory, canvas, secrets, runs, and the Hono REST catch-all therefore
avoid the Next server wrapper and its response lifecycle waitUntil task.
The playbook export, collaboration, snapshot, backup, connection catalogue,
registry search, and site-wide/per-playbook OAuth/skill discovery routes also use native
Request/Response handlers. Frontend pages use reviewed build-owned assets,
with OpenNext as fallback.
scripts/generate-worker-api-routes.mjs generates the dispatch manifest during
prebuild. It includes reservations for Next-specific routes so the REST catch-all
cannot shadow them. Specific routes take precedence over dynamic segments.
Handler modules are loaded lazily: public metadata does not initialize the MCP,
snapshot, secret, or Next page implementations. Catch-all parameters retain their
array shape, including optional empty paths. The configuration test re-export is
included explicitly. Unsupported methods, HEAD, and OPTIONS retain route-handler semantics. API
responses use the same security headers as Next and default to Cache-Control:
no-store. Authentication is checked on every request before cached discovery
content is returned; this is not a response cache or an authentication cache.
Federation timeouts cover response bodies as well as headers. SSE responses are read incrementally until the matching JSON-RPC result/error, then cancelled; notifications and other request IDs cannot satisfy the request. Upstream bodies are limited to 8 MiB. This also applies to OpenAPI specifications, operations, and OAuth token requests. Initialization notification responses are cancelled without waiting for an unnecessary body.
Connection logs record bounded, client-declared names/versions, User-Agent, and validated key prefixes (never tokens or request arguments). Discovery logs are sampled at 2%; they can help diagnose reconnect/discovery loops without logging every tool call. Client-declared identity is an attribution hint, not proof of which program or person sent a request.
Only full-document GETs of /, /docs, /blog, and published public Markdown
document/post paths without query strings, credentials,
session cookies, conditional/range headers, or Next/RSC headers are eligible for
the public HTML Cache API. NEXT_LOCALE is the only accepted cookie; cache keys
use the same locale selector as SSR plus the origin and Worker version ID.
Successful HTML is retained for five minutes, concurrent fills are coalesced,
and errors, redirects, Set-Cookie, JSON, and Vary-star responses are not stored.
Browser/CDN responses remain no-store, avoiding implicit locale or RSC mixing.
Authenticated pages and all API responses bypass this HTML cache. Changes that
introduce personalized server rendering on any allowlisted page require
removing that page from the cache allowlist. generate-public-page-paths.mjs
builds this exact path list from public Markdown filenames; unknown slugs,
subroutes, and asset requests are excluded. The manifest contains paths only,
so loading the Worker does not load the embedded blog content index.
The unpublished /.well-known/traffic-advice policy answers its existing 404
directly, without initializing Next to render a not-found page.
Registry search has its own bounded five-minute public-data cache with eight entries and concurrent-load coalescing; upstream headers and bodies share a ten-second timeout and a 2 MiB body limit. Credentials are never forwarded to the registry or stored in cache keys.
Public HTML produced during deployment
generate-public-html.ts starts the built standalone Next server on loopback
during the Worker build and produces complete HTML for every reviewed public
path in English, Hungarian, German and Spanish, plus separate full RSC and
prefetch and route-tree payloads from the same Next build. Only public Markdown and
localized README files are supplied. Requests have no cookies or credentials;
private secret/token/password environment variables are removed from the
renderer's environment and their values are checked against the generated HTML.
The build fails for non-200 responses, cookies, an incorrect locale, missing
client assets, loopback URLs or HTML exceeding 2 MiB. The output is deployment
assets, not embedded Worker source; no snapshot content is loaded by API calls.
Eligible GET/HEAD requests read the locale-specific file through the
ASSETS binding before initializing Next or using the fallback HTML Cache API.
This also avoids Next rendering on the first request in a new location when
the asset cache is empty. X-APB-Page-Source: STATIC and
X-APB-Page-Cache: ASSET identify this path. X-APB-Page-Variant distinguishes
HTML, navigation RSC, prefetch RSC and route-tree RSC. A signed-in visitor receives the same
public build-owned content: credentials, session cookies, router trees and query
strings are never forwarded to ASSETS. Only NEXT_LOCALE affects the asset
selection. These exact pages have no personalized server data or query-dependent
server content. /docs?page=... redirects to the published canonical doc path;
/login and /explore snapshots contain only their public initial UI, not
sessions, user stars or playbook rows. Their existing browser effects load auth
settings and live data after hydration; their API authorization is unchanged.
other query values do not change their server content. Private page paths and
all API paths are excluded. Draft mode, server actions
and unsupported Next internal protocols still reach Next. HEAD has no body,
security headers are restored, and browser responses remain no-store to
prevent locale mixing. Asset ETags/Last-Modified are not exposed as validators
for the locale-varying public URL. The snapshot uses its own weak ETag bound to
the Worker version, locale, path and HTML/Flight variant. Matching If-None-Match
returns 304; non-wildcard If-Match returns 412 because weak tags cannot strongly
match. Date conditions are ignored without Last-Modified. Range is optional and
receives the complete 200 representation with Accept-Ranges: none, never partial
Flight or a cold Next render. These headers are not forwarded to ASSETS.
Missing/unavailable assets fall back to Next and the bounded HTML Cache API. Private pages and requests excluded from the public policy still need Next; this change does not promise every such cold render fits the free-plan CPU allowance.
Normal navigation receives a full build-owned RSC payload rather than a response
tailored to a client router tree. Prefetch has its own payload; HTML is never
returned as RSC. The browser policy is no-store for all variants, and Vary
declares locale, cookies and router representation. There are no interception
routes in this application. Personalization or interception added to a reviewed
page requires removing it from the snapshot allowlist or extending the policy.
Native page redirects and misses
generate-page-route-patterns.mjs reserves the application's declared page
routes, including dynamic dashboard and invite paths. Existing API reservations
and metadata routes retain their handlers. Unknown public blog/doc slugs and
other missing URLs receive a small native 404, without Next initialization,
credentials or request data in the body. Static asset aliases are checked before
declaring a miss, and a binding failure falls back to Next. Canonical trailing
slashes, legal redirects and legacy documentation URLs use native redirects.
RSC misses return non-RSC 404 HTML so Next's browser router can perform a full
navigation to the error page; it is never a successful cached Flight response.
Avoiding repeated client and upstream requests
Explore waits 300 ms after nonempty search input before fetching playbooks. A new query cancels the previous timer/fetch, and a superseded response cannot replace current results even if its transport ignores cancellation. Loading Skills or MCP catalogue data no longer refetches the Playbooks tab.
Federated calls to tool names already declared in the freshly loaded server row skip an extra upstream tools/list discovery request. Upstream authentication and execution still run; undeclared names retain discovery and fallback behavior. A stale declaration fails at execution rather than bypassing upstream checks.
Discovery observability logs the first tools/list or resources/list event per five-minute identity/method/user-agent window in each Worker isolate; repeats are sampled at 2%. The window map is bounded to 128 entries. Initialize events remain logged. Only bounded client metadata and key prefixes are recorded; credentials, tool arguments, content and IP addresses are excluded. Window events are observations, not an exact client census or request counter.
MCP transport alone does not imply polling. Local audits should compare global MCP entries with plugin-bundled entries and inspect client initialization logs. Native Hermes memory uses REST memory routes and has no periodic tools/list poller. Other Hermes MCP clients or remote integrations require separate evidence.