Skip to main content

provide-uterm-cloudflare

Cloudflare Workers companion package for provide-uterm. Runs the provide-uterm control plane on Cloudflare Workers using Durable Objects, with a fleet-wide session registry backed by Workers KV.

What it does

Each terminal session gets its own Durable Object (SessionRuntime). The DO arbitrates WebSocket traffic between the runtime worker connector and browser clients, stores hijack leases and snapshots in SQLite, and publishes events to all connected browsers. A fleet-wide session list is maintained in Workers KV.

Installation

pip install provide-uterm-cloudflare

Or install from the monorepo with uv:

uv pip install -e packages/provide-uterm-cloudflare

Deploy

The worker entrypoint is src/worker_entry.py (referenced by main in wrangler.toml). It lives at the package src/ root on purpose: wrangler bundles the directory of the main file, so anchoring it there preserves the full provide/uterm/cloudflare/ tree in the bundle and the worker's qualified imports resolve as-is.

The Pyodide runtime also needs a flat vendor tree of the pure-Python deps the worker imports (structlog, provide.telemetry, and the provide.uterm.* modules). pywrangler sync produces a layout the worker can't import, so build it with the helper script, then deploy with wrangler directly (not pywrangler deploy, which would re-sync and overwrite the tree):

bash .ci/vendor_cf_worker.sh                          # build python_modules/
cd packages/provide-uterm-cloudflare
CLOUDFLARE_API_TOKEN=… npx wrangler deploy            # publish

# Required secrets (AUTH_MODE is jwt-only; the worker 500s without these):
npx wrangler secret put WORKER_BEARER_TOKEN           # >=32 high-entropy chars
npx wrangler secret put WEBHOOK_SECRET_KEY            # base64 AES-256 key

Key features

  • Durable Object per session — SessionRuntime DO holds all session state (leases, snapshots, event sequence) in SQLite.
  • Fleet-wide session registry — SESSION_REGISTRY Workers KV namespace; GET /api/sessions returns all active sessions across the fleet.
  • CF Access JWT auth — validates Cloudflare Access JWTs via JWKS; JWT_DEFAULT_ROLE env var assigns a role when the JWT carries no role claim.
  • Hijack REST API — POST /hijack/{id}/acquire, POST /hijack/{id}/send, POST /hijack/{id}/release, GET /hijack/{id}/snapshot.
  • WebSocket proxy — three WS endpoints per session:
    • /ws/worker/{worker_id}/term — runtime worker protocol (JSON frames)
    • /ws/browser/{worker_id}/term — browser/operator protocol (JSON frames)
    • /ws/raw/{worker_id}/term — raw stream mode for uterm listen telnet/SSH gateways
  • Hibernation-safe — uses CF WebSocket Hibernation API; state survives DO sleep/wake cycles.
  • WS session resumption — browser reconnects reclaim their role and hijack ownership via one-time tokens stored in DO SQLite; see docs/cf-do-architecture.md.
  • Quick-connect — POST /api/connect creates sessions in KV; SPA serves the connect form at /app/connect. Supports shell, websocket, and ushell connector types.

Auth modes

Set AUTH_MODE in wrangler.toml or .dev.vars. jwt is the only supported value — the worker is always internet-facing, so any other mode (dev/none are removed) raises a ValueError at config load.

Mode Behavior
jwt Validates CF Access JWT; role from claim or JWT_DEFAULT_ROLE. CF Access service-token JWTs (with a common_name claim and no human email claim) are accepted, but are only granted the admin role when JWT_SERVICE_TOKEN_ADMIN=1 is set (defaults off); otherwise they get their roles from the normal claim/scope/default-role path.

WORKER_BEARER_TOKEN is also required and must clear a 32-character / non-placeholder entropy floor.

Current gaps

Every intentional difference from the FastAPI backend — auth modes, capability refusals, the /api/health payload, hibernation, the tunnel transport — is tabulated with its reason and its pinning test in docs/cloudflare-divergence-matrix.md. Changing edge-runtime behavior means updating that table and its edge tests in the same commit. The gaps below are the ones that are not yet settled either way:

  • The quick-connect form creates sessions in KV but the CF worker cannot run shell/SSH/telnet connectors itself — a worker process must bridge in via WS.
  • The hijack REST surface is intended to match the FastAPI contract, but there are still backend-parity gaps; treat docs/protocol-matrix.md as the target contract, not a guarantee that every edge case is identical today. Cells in that matrix use the labels defined in docs/parity-labels.md.

Commands

uv run pywrangler dev        # local dev server (sync deps + wrangler dev)
uv run pywrangler deploy     # deploy to Cloudflare
uterm-cf build               # build only
uterm-cf deploy --env production

Docker alternative

# Build and run from repo root
docker build -f docker/Dockerfile.cf -t provide-uterm-cf .
docker run --rm -p 27788:27788 provide-uterm-cf

# JWT auth test
docker run --rm -p 27788:27788 \
  -e AUTH_MODE=jwt \
  -e JWT_JWKS_URL=https://<team>.cloudflareaccess.com/cdn-cgi/access/certs \
  -e JWT_ISSUER=https://<team>.cloudflareaccess.com \
  -e JWT_AUDIENCE=<aud-tag> \
  provide-uterm-cf

Tests

Unit tests (no network required):

uv run pytest tests/ -v

E2E tests against a local wrangler dev instance or the live worker:

E2E=1 uv run pytest -m e2e -v
REAL_CF=1 REAL_CF_URL=https://provide-uterm-cloudflare.neurotic.workers.dev uv run pytest -m e2e -v
  • Main package: provide-uterm
  • Terraform for KV provisioning: terraform/

Metadata

Release files for provide-uterm-cloudflare 0.5.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for provide-uterm-cloudflare 0.5.6
File Size Uploaded Provenance Actions
provide_uterm_cloudflare-0.5.6.tar.gz 278.1 kB With provenance Details for provide_uterm_cloudflare-0.5.6.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for provide-uterm-cloudflare 0.5.6
File Interpreter ABI Platform Actions
provide_uterm_cloudflare-0.5.6-py3-none-any.whl Python 3 none any Details for provide_uterm_cloudflare-0.5.6-py3-none-any.whl

Total release size: 401.2 kB

Release files / provide_uterm_cloudflare-0.5.6.tar.gz

Download URL provide_uterm_cloudflare-0.5.6.tar.gz
Size 278.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d3d7924e0b71d0075a0cff2178e928cf94f94a0fef1f6f9a8d3b95c960fa59b6
BLAKE2b-256 checksum
How to use checksums
71071c367945a350164c5c9b0cd15124bcdf7d45fc0b913798d09189c83db8d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / provide_uterm_cloudflare-0.5.6-py3-none-any.whl

Download URL provide_uterm_cloudflare-0.5.6-py3-none-any.whl
Size 123.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dacd88a3267494300b06c7a9fe1b5f904b77c8c59717759fbadcb4ce5c99ee97
BLAKE2b-256 checksum
How to use checksums
51c43c9d51544b8fce4380d64eb3ee39ba958757d91b579badb05454da01899b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Security for provide-uterm-cloudflare 0.5.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for provide_uterm_cloudflare-0.5.6.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page