TOKN / field guide

Cloudflare publication and gateway

This document describes the implemented Cloudflare integration and its verification procedure. It does not assert that the current provider resources or public URL are live; use the saved deployment receipt and cloudflare-status output for that claim.

Request model

The public Worker is intended to serve https://tokn.bepc.cc. It serves the landing page, explorer UI, documentation, and versioned release archives from Workers Static Assets. The only dynamic routes implemented by the Worker are:

POST /rpc    -> Worker -> Access Service Auth -> tokn-origin.bepc.cc Tunnel
GET  /health -> Worker -> Access Service Auth -> tokn-origin.bepc.cc Tunnel

The Tunnel ingress terminates at the isolated web-gateway service, which forwards to the existing node. Explorer data is loaded by the static explorer UI through /rpc; there is no /explorer/api/* endpoint. Static pages can remain available during an origin outage, while dynamic failures return a controlled 503. The continuously running existing host remains the origin; this design does not provide origin redundancy and does not require a separate VPS while that host is available.

The Worker accepts only the methods above, rejects unknown/private paths, sends Content-Type and Accept upstream, and adds the Access service-token headers. It does not forward arbitrary incoming headers. /rpc request bodies are read into memory with a strict 64 KiB limit, upstream calls have a 15-second timeout, and there are no automatic retries because a lost POST response may follow a successful node operation. Upstream responses must be JSON; redirects and other content types become 503 responses. This is deliberate gateway behavior, not a generic reverse proxy.

No end-user account or CAPTCHA is required for the public read-only pages or RPC reads. Application-level wallet and write controls remain separate. Cloudflare does not create or approve the documented 100 TOKN useful-help grant or the manually reviewed 500 TOKN ten-new-block node proof.

Local commands

The commands are defined in the project justfile:

just cloudflare-install       # pinned npm dependencies in web/
just cloudflare-plan          # offline; no provider request
just cloudflare-infrastructure # provider writes: Tunnel, Access, DNS
just cloudflare-publish       # build verified assets and deploy Worker
just cloudflare-status        # provider status and saved release state

cloudflare-install needs Node/npm. The Python commands need Python 3. Docker Compose is needed to run the connector and gateway locally:

docker compose -f compose.cloudflare.yaml up -d

cloudflare-plan is offline and reports the configured public target. cloudflare-infrastructure is the mutation phase: it verifies the configured zone and token, creates or reuses only the named TOKN resources with an ownership receipt, configures the Tunnel ingress, creates the origin CNAME, and creates a service-only Access policy. cloudflare-publish requires that infrastructure and the pinned Wrangler installation exist; it builds the verified public release, rejects secret material, uploads assets, and deploys the Worker. cloudflare-status performs a provider Tunnel lookup and reports phase, URL, Tunnel status, connections, version, and service-token expiry without printing credentials.

The commands write private receipts under the project state/secrets directories. Keep those files mode 600. The Cloudflare API token, Tunnel token, Access client secret, account ID, and zone ID must never enter public assets, logs, git, or this document.

Worker publication details

The publisher generates dist/cloudflare/wrangler.json with run_worker_first for /rpc, /rpc/*, /health, and /health/*; the Worker itself intentionally accepts only exact /rpc and /health. It attaches the custom domain TOKN_DOMAIN, sets TOKN_ORIGIN_URL to the HTTPS origin hostname, enables observability with 10% head sampling, and disables invocation-log payload output. Generated public files are allowlisted and scanned for credential material before deployment.

Static asset delivery is free and unlimited under the current Workers Static Assets billing model, with no additional asset-storage charge. Workers Free currently allows 100,000 Worker requests/day, 10 ms CPU per invocation, 128 MB memory, 50 subrequests per invocation, and 25 MiB per static asset. This Worker buffers only its bounded RPC body and bounded JSON response; the 64 KiB application limit is stricter than Cloudflare's 100 MB Free request-body limit. A paid Workers plan is not required for the current feature set; do not enable paid usage without review.

Access and Tunnel boundary

The named remote Tunnel is tokn-origin.bepc.cc, separate from the Worker hostname. Its ingress points only to http://web-gateway:8080. cloudflared runs from the pinned Docker image in compose.cloudflare.yaml with the Tunnel token mounted read-only. The connector needs outbound connectivity; no creator, treasury, validator, wallet, or onion keys are copied into it.

The Worker receives ACCESS_CLIENT_ID and ACCESS_CLIENT_SECRET through Wrangler secrets. Access uses a Service Auth policy containing exactly the origin service token. The service token currently has an annual lifetime in the infrastructure request (8760h). Rotate it by creating the replacement, publishing the Worker, testing /health and /rpc, then revoking the old token. Cloudflare displays a client secret only at creation; never recover or print it from logs.

Verification and recovery

  1. Run just cloudflare-plan and confirm the intended public and origin hostnames without provider calls.
  2. Confirm the configured zone is the expected Cloudflare zone before any write. Run just cloudflare-infrastructure once and retain its private receipt.
  3. Start docker compose -f compose.cloudflare.yaml up -d; confirm the connector and web-gateway are healthy locally.
  4. Run just cloudflare-publish, then just cloudflare-status. Check the saved Worker publication result, Tunnel status, connector count, and service-token expiry.
  5. From an independent network, verify static /, /explorer/, /docs/, /manifest.json, and the versioned archive. Verify /health and a harmless read-only /rpc request separately. A static success does not prove blockchain availability.
  6. Test the failure boundary by stopping only the origin stack and confirming static files remain available while /health and /rpc return 503; restart it and repeat the live checks.
  7. For rollback, redeploy the last known-good immutable release and restore only the matching private provider receipt after inspecting current DNS, Access, and Tunnel state. Do not delete volumes, regenerate identities, or overwrite unrelated DNS records.

Official references