Managed Connection design
Proposed — not implemented. Managed connection is a design for a future optional service. Nothing on this page is available yet. To connect today, see Access from your phone.
Status: proposed, not implemented. Product direction approved in discussion on 2026-10-20; implementation and security decisions below remain reviewable. Epic #22. Implementation tracker and work packages: roadmap. Extends RFC #1; related: #6, #12, #19, #20.
#Product and acceptance case
Your coding environment, accessible from anywhere, without networking setup.
The initial customer already has a dedicated EC2/Linux development machine with Claude Code, Git, GitHub credentials and repositories (often under ~/src). They pay for managed connectivity. They do not need our AI gateway, a coding plan, a new inference key, a Cloudflare account, their own domain, or Tailscale.
The acceptance case is: pair that machine once, open its permanent HTTPS address on a phone, select a local repository, and complete a Claude task, approval, follow-up, stop/resume and reconnect without SSH forwarding or changing model/Git credentials. Codex repeats this flow after its adapter in #19 is implemented. Connecting a host does not imply adopting arbitrary existing terminal sessions.
Execution, workspaces, credentials, session logs, runner lifecycle, approvals and future room coordination remain on the user's machine. The service does not rent compute, run agents, act as an LLM dispatcher, or resell model inference. Existing self-hosted access remains usable without a service account.
#Scope
| MVP | Deferred / separate |
|---|---|
| Standalone service account; one owner and one host per pilot account | Teams, invitations, shared ownership |
| Short-lived pairing; stable HTTPS; device sessions and revocation | Passkeys in self-hosted mode (#6); broad account recovery design |
| Linux host connector lifecycle and sanitized diagnostics | Windows/macOS installers; general SSH/port forwarding |
| Existing Claude installation and credentials | Codex adapter (#19); other agent adapters (#12) |
| Existing PWA, projects, worktrees, approvals and push | Room implementation (#20); cross-host rooms/federation |
| Manual/explicit task creation and permission selection | Automatic task execution on pairing; default Bypass |
| Optional connection subscription independent of inference | Gateway/GLM plan bundles and billing integration |
Pilot is invitation-only with an explicit host quota, not a free anonymous tunnel service. Initial Linux support targets the same Node/git/tmux prerequisites as host mode. Reboot recovery is a release requirement, not a promise made by the current tmux implementation.
#Architecture and trust
flowchart TD
Phone[Phone PWA] --> Edge[Cloudflare HTTPS + edge authentication]
Console[Account console] --> Broker[Managed account / pairing / provisioning service]
Broker --> CF[Cloudflare Tunnel / DNS / access-policy APIs]
Edge --> Tunnel[Outbound cloudflared connection]
Tunnel --> Origin[Loopback managed origin / authenticated CCR adapter]
Origin --> Plane[Existing host control plane]
Plane --> Runner[Claude runner; Codex later]
Plane --> Store[Local sessions, projects and future rooms]
Connector[Host enrollment / health connector] --> Broker
The account console holds host inventory and routes the browser to a separate origin per host. The host serves its PWA and session APIs through its own tunnel. The console does not proxy transcripts through its application database. Do not iframe tenant pages into the console or share authentication through permissive CORS. Session links bind both host identity and session ID.
Use a dedicated execution-host domain separate from the account/admin domain; prefer a separate registrable domain for tenant content. Use host-only cookies, no parent-domain cookies and no cross-host service-worker scope. An enrolled host is user-controlled and can replace its local server; routing it under our domain does not make its HTML trusted. The edge authentication gate must cover the entire hostname, including assets, APIs and any alternate route. Never offer a bare public hostname while provisioning is incomplete.
Cloudflare is an infrastructure dependency, not a requirement customers configure. Start with remotely managed named tunnels and an API-owned DNS namespace. Prefer Cloudflare Access as the edge gate, subject to the phase-0 feasibility check for SSO, account integration, limits and commercial suitability. If a different edge gate is required, record an ADR before implementing it; an unprotected tunnel is not a fallback. The service must enforce the owner binding at the edge so a malicious enrolled host cannot publish arbitrary content to other customers.
The managed origin independently authorizes every API operation. A tunnel token, trusted-looking header, guessed hostname, or service login alone is insufficient. Cloudflare handles HTTPS termination; the service operator and Cloudflare are trusted parties in v1. This is not an end-to-end-encrypted, blind relay.
An installed coding agent may send code/context to its configured model provider. “Execution stays on your host” does not mean code never leaves the machine. Optional chat bridges intentionally send selected content to their platforms.
#Customer portal and domain layout
Proposed product URLs (not deployed or reserved by this document):
uubright.com/connect: commercial introduction, pilot request and pricing.connect.uubright.com: standalone customer portal for sign-in, pairing, host status, opening a host, device revocation, disconnect and subscription status.ccr-cloud.uubright.com: public open-source documentation; no account required.- Host PWA URLs: generated host IDs under a separate registrable execution domain, to be chosen during phase 0. Do not serve user-controlled host content beneath the portal's registrable domain.
The pilot portal opens with one host card: name, Online/Offline/Connecting state, last contact and an Open workspace button. New users see Add your server, a host pairing command (proposed npm run connect), the code confirmation flow, and then Open workspace. Never ask for Cloudflare credentials, an inference API key or the existing host owner token. An offline card offers sanitized diagnostics and local recovery instructions; it does not imply tasks have stopped.
Daily coding happens in the existing host-served PWA at its protected HTTPS URL. Users can bookmark/install that PWA and return directly; the portal is for account and connection management. Billing UI comes after the manual invitation pilot. Gateway accounts and coding plans remain optional and separate.
#Authentication contract (freeze before parallel implementation)
Separate these credentials:
| Credential | Purpose / location |
|---|---|
| Service provisioning API token | Scoped Cloudflare management; service secret store only |
| Per-host tunnel token | Starts that host's connector; private host file; never account-wide Cloudflare access |
| Host device key | Authenticate enrollment/heartbeat and bind pairing; generated on host; private file |
| Short-lived managed grant | Authorize a specific account/device against one host; verified on the managed origin |
| Existing CCR owner token | Local/self-hosted access only; never uploaded, forwarded, or embedded in managed URLs |
| Claude/Codex/Git/model credentials | Stay in their existing host environment; never read during pairing |
Proposed origin-grant claims: version, issuer, audience, account_id, device_id, host_id, enrollment generation, scopes, issue/expiry times and unique grant ID. Only scopes needed by the owner UI are granted. Use standard signed-token verification with pinned algorithms/issuer/audience, bounded clock skew and a key-rotation policy; do not hand-roll a crypto protocol. New runtime dependencies still require the owner's approval under AGENTS.md.
Phase 0 must freeze the exact login provider, signed grant encoding, signing-key trust/bootstrap, edge identity mapping and session exchange before production implementation. Bind accounts by stable verified subject IDs, not email headers. A browser authorization code may travel through a redirect only as a single-use, short-lived, host/device-bound code with state/PKCE-style binding and log redaction; no reusable token or owner credential goes in a URL. Exchange over POST for a Secure, HttpOnly, host-only cookie. Use CSRF protection and exact Origin checks for mutations, WebSocket upgrades and login/session exchange. No wildcard CORS.
Proposed pilot limits: pairing expires in 10 minutes; browser grants last at most 5 minutes; connected hosts consume revocation updates at least every 60 seconds. These are application targets, not claims about Cloudflare defaults. Revocation must invalidate both the edge session/policy and origin device grants. Tests must prove a <=60s online target and <=5min hard upper bound under a partition, including existing streams. Expired identity closes SSE/WebSocket streams; a reconnect reauthenticates and resumes from the event cursor. No stale stream can continue reading indefinitely after revocation.
The managed listener is separate from the existing loopback owner-token listener and runner port. It must not accept a legacy owner token as an alternate public login. A request carrying conflicting managed identities is rejected. Local and self-hosted owner-token access remains unchanged. Managed auth is feature-gated and cannot accidentally enable itself merely because a header is present.
#Pairing, provision and disconnect
Proposed command shape (not available yet): npm run connect, with status and disconnect subcommands. Existing setup --cloudflare HOST remains the user-managed path; it must not be silently converted to our Cloudflare account.
- User signs into the standalone connection console and chooses Add host.
- The host command generates a private device key and requests a pairing intent. Display verification URL, user code, host label and fingerprint; do not install anything or expose a hostname before the host owner confirms the destination.
- The browser shows the host identity, local access implications, data handling and optional price. The user approves that exact host/account association. Short codes are rate-limited; expiration/replay/double-claim fails closed.
- A host-authenticated poll receives enrollment material, not the owner's API token. Provisioning follows
pending → authorizing → provisioning → online, with failed/revoked states, versioned identities and idempotency keys. - Reconcile tunnel, DNS and edge policy safely: establish deny-by-default protection before exposing traffic; stage/verify origin auth, then enable only the paired owner. Failure never leaves a publicly usable application.
- Write connector state privately (directory 0700, secrets 0600), install a supported background service, and verify both local and remote health. If a privilege change is needed, explain the exact command; do not silently sudo.
- Show the stable URL and next action. Restart/reconnect resumes the same host registration; it does not create another billable tunnel or rotate credentials unnecessarily. Existing agent/Git configuration remains byte-for-byte intact.
The broker records external resource IDs before retries; reconciliation tolerates crashes after each Cloudflare API call. Cleanup operates by stored ownership IDs, not a hostname supplied by a user. Names are generated by the service, cannot impersonate the console, and are not reassigned until a defined quarantine period. Never accept arbitrary upstream targets, ports, URL fetches or tunnel configs. The connector only exposes its configured CCR managed origin, never runner/SSH ports or cloud metadata. Users control their machine, so edge gating, rate limits and abuse handling are still required even with a fixed connector target.
Host disconnect disables managed ingress locally first and reports remote cleanup status. It removes only managed credentials/services and owned remote resources; it does not kill coding tasks, delete workspaces, uninstall agents, or revoke Git or model credentials. Cloud revocation immediately blocks new grants, attempts edge shutdown and pushes revocation to the host; display pending acknowledgement until the bound above is met. Preserve a local break-glass access path. A complete uninstall/account deletion handles DNS, tunnels, sessions and retained metadata.
#Reliability, privacy and operations
- Agent work and local room coordination do not depend on the connection service. A managed-service outage must not send interrupt/stop or require a host reset.
- The host event log remains the source of truth. A reconnect catches up using existing offsets; bounded retry/backoff avoids reconnect storms.
- Browser controls show Connecting, Connected, Reauthenticating, Host offline, Service unavailable, and Revoked separately. No offline mutation queue in v1. Do not automatically replay an approval after authentication expiry.
- Session mutation requests need durable command/idempotency IDs across uncertain HTTP responses. Same ID cannot create a second task, message or approval. Idempotency is keyed by principal, host and operation; different bodies with the same ID fail. If a crash leaves an action outcome uncertain, report that state and require reconciliation instead of automatically repeating the side effect. Runner acking alone is not browser-request deduplication.
- Health collection is limited to host identity, versions, connector status and diagnostic codes. Do not upload repository paths, transcripts, tool inputs, environment dumps or inference credentials. Support bundles are opt-in/redacted.
- Proposed pilot retention: 30 days of sanitized operational events; delete active credentials immediately on disconnect and clean recoverable external resources within 24 hours. Set and document a backup-expiration period before enrollment; do not promise deletion from immutable backups instantly.
- Redact cookies, authorization headers, pairing codes and connector tokens at all logging layers. Disable request-body capture and caching for control APIs.
- Use existing host Web Push initially. Push payloads can contain generic attention notices rather than code. Do not proxy model traffic through the connection service, or add a second push relay merely for billing/account integration.
- Quotas: pilot one host/account, enrollment/API/message/byte rates, bounded body sizes and streams. No general-purpose proxy or anonymous public serving. Record suspension, abuse-reporting and cleanup runbooks; validate vendor suitability.
- Service deployment, budget alerts, backups and signing-key rotation are owned by operators. No production deployment, Cloudflare purchase or domain change is authorized by this design document alone.
After host reboot, the connector/control-plane service may restart automatically, but interrupted agent tasks must be reconciled accurately. Do not silently rerun prompts or approvals; show stopped/recoverable state and require explicit Resume. This is service recovery, not a promise that tmux processes survive reboot.
#Existing agents, gateway and Rooms
Claude MVP uses CCR-launched/resumed sessions with existing host authentication. Discover installation/version without reading credential contents or silently spending model usage. Model access is verified only by an explicit user task. Interactive questions must have a supported answer path or a clear unsupported state; they must not silently disappear and let the agent assume an answer.
#19 remains the Codex implementation tracker. Extend its requirements to support an already-authenticated host without CCR, preserving its existing configuration; new-session selection and permission semantics belong to the agent adapter. Do not claim Codex works merely because its executable was discovered. #12 remains the broader agent-adapter umbrella.
The AI gateway and GLM coding plans are optional, later integrations with their own consent and credential setup. A connection account can exist without either. Packaging may bundle connectivity with inference later; the authorization model and inference routing cannot depend on that commercial choice.
#20 Rooms stay on the host: room log, membership, task claims, wake-ups, loop guard, turn/time budgets and owner approvals. The managed connection transports their existing UI/API without moving coordination into the cloud. A console may list several hosts later; cross-host rooms are still out of scope. Matrix/Discord are optional bridges with their own privacy boundaries, not the message bus. Agent posts cannot grant owner authority or approve another agent's tool calls.
#Release evidence and remaining decisions
See roadmap for blocking gates. Mocks prove contracts, not vendor integration. Before a paid pilot, test a real staging domain/Cloudflare account, a normal EC2 host, desktop Chrome and a physical iPhone/Android browser over a mobile network. Record browser/agent versions, explicit model usage, reconnect/revoke timings, reboot and tunnel/service outage outcomes, and cleanup of staging resources. Never run destructive tests on the owner's development machine by default.
Still to decide in phase 0: standalone identity provider and recovery policy; Cloudflare account/Access plan and customer-isolation limits; origin session exchange and identity mapping; service deployment repository/location; domain names; metering/pricing and payment provider; supported installation/service mode; exact retention/backups. These do not block writing the roadmap, but security and identity decisions block exposing a real managed host.