Registration

The credential is asymmetric, and that is the whole design

The management client signs each call with an Ed25519 private key. You register the matching public key.

Nothing secret of yours ever reaches anyone, and nothing they hold is worth stealing from you. Every other property on this page follows from that one.

Three alternatives, and why each was rejected

Not a shared HMAC secret. Simpler, and strictly weaker: their breach becomes your breach. A per-customer HMAC secret means a compromise on their side yields keys replayable against every customer’s production Worker until each of them rotates. Under asymmetric, a full compromise leaks private keys that are useless the moment you revoke the public one — and revoking is a row you delete.

Not OAuth. OAuth exists so a third party can act on behalf of an end user without seeing their credentials. There is no user delegation on this leg — it is their server talking to your Worker — and turning every adopter’s Worker into an OAuth provider is a large surface for a property nobody needs. The one grant that would fit is a shared secret with extra ceremony.

Not Cloudflare Access service tokens or mTLS. Both work, and both move the authorization decision out of your Worker into Cloudflare’s edge configuration. That requires you to run Zero Trust, and it breaks the sentence this design exists to keep true: your Worker is the authority.

One keypair per connection

Per customer, per project, per environment. A leak exposes one connection rather than a fleet, and rotation and revocation are naturally scoped.

The keypair is generated by the management client, and the private half never leaves their infrastructure. The alternative — your CLI generating one and sending it over — puts key material on the wire for no benefit.

The flow

pithy dashboard connect --env prod

Every step below is pithy dashboard connect doing its work.

  1. A device-code flow against the management client’s origin — a short user code, and your browser opens. The same shape as wrangler login. This leg is genuine user delegation, which is why a browser flow belongs here and not on the machine-to-machine one.
  2. You approve. The CLI polls and receives a short-lived connect token.
  3. The CLI requests a connection for this project, this environment, the scopes you chose, and the seam’s address on this Worker.
  4. The client generates the keypair, keeps the private half, and returns the connection id, key id, public key and issuer.
  5. The CLI writes the registration into your D1. This is the one key the CLI ever writes.
  6. Nothing reports connected until a signed ping round-trip succeeds against your Worker.

The address is resolved, not passed

connect reads it from the project: the Worker’s domains declaration for that environment, else its first route pattern, else a hand-set base URL. It prints what it found and where it came from before registering.

--worker-url overrides — a proxy in front of your Worker has an address no config knows, and that flag is the only way to say so.

It also names the Worker. The administrative surface is composed on one Worker per project. In a project with several, connect refuses the ambiguity and asks for --worker <name> rather than guessing; a Worker composing no control plane is refused outright, because there is nothing to connect to.

The address changes. A custom domain, a renamed Worker, a moved environment — connect --update re-points both the URL and the base path. A connection whose ping fails surfaces as needs reconnecting, never as a silent dead link.

One connection per project and environment

A customer may register several projects, each with its own connection and keypair.

Sibling Workers are not separately addressable, and that is deliberate. The data being administered is shared through binding names rather than owned per Worker, so a second connection to a sibling would be a second credential onto the same rows.

Rotation: append, prove, then expire

Rotating and revoking is the operator’s side of what follows.

Never replace. The order is the entire safety property.

  1. Append. Register the new public key, signed with the current one. Your Worker verifies with the key it already trusts and appends. Trust flows forward from existing trust. Both keys are now valid.
  2. Prove. A real call — ping — signed with the new key, confirmed to succeed.
  3. Expire. Only then is the old key given an end date, naming the proven successor — and that call must itself be signed with the successor. Naming a live key is not proof you can sign with it; only signing with it is.

Reverse those, or swap without proving, and a bad rotation locks the client out permanently with no authenticated path back.

Two live keys is a normal state, not an exception.

Registration and expiry are separate calls on purpose. Folding them into one would make append-and-expire atomic — and atomic is precisely wrong here: the point is that the old key survives until the new one is proven.

The Worker refuses an expiry naming an unproven successor, and refuses one that would leave the connection with no live key at all. Lockout is the one failure mode with no recovery path.

Your infrastructure stays passive. Storing a new key is one write in a route handler. No Workflow, no cron on your side.

Rotation is a scope. A client never granted it cannot rotate, whatever it intends — better than a toggle somebody has to be trusted to honor.

Revocation is immediate and unilateral

Delete the registration, or pithy dashboard disconnect --env <environment>.

Requiring nothing from anyone else. That is the property that makes granting this access defensible at all.

One leaked key does not need the whole connection rebuilt. pithy dashboard revoke-key stamps that key revoked and leaves everything else in place. Revocation is checked before any validity window, so it takes effect on the next request.

It will take the last live key if you ask it to. Expiry is the orderly end of a rotation and is refused when it would leave nothing live; revocation is the disorderly one — and an adopter holding a leaked key must never be told they have to keep trusting it. The connection then denies every call, which is the correct state for a credential you no longer trust, and connect is the way back.

ESC