Beta launch log: from local-first to a hosted control plane
Copy page
A running log of the 1.0.0-beta.1 launch. We update it as we go — including the things that broke.
What this beta is
Section titled “What this beta is”Plan Desk started as a local-first planning workspace: a task-graph on your machine, an MCP server your coding agent drives, zero accounts, zero cloud. That’s still the default and always will be. 1.0.0-beta.1 adds the other half — a hosted control plane so a team can share a board online — without giving up the local-first promise.
The headline changes:
- Auth is now 100% better-auth. GitHub social sign-in for the dashboard, a paste-a-token flow for the CLI, and project-scoped keys for agents. The old hand-rolled token table, device-code login, and sessions are gone.
- Two-actor model. A human provisions access (owner key); an agent inherits a scoped key and never logs in.
- A real migration path. The schema was reset for this rewrite, so
plandesk legacy-upgradelifts an old board into the new one — one command, nothing lost.
Install the beta:
npm i -g @plandesk/cli@betaYour existing @latest install is untouched — the beta ships under the beta npm tag.
Shipping it: what actually broke
Section titled “Shipping it: what actually broke”We deployed the hosted API to Cloudflare Workers + Turso as part of this launch. “It built in CI and passed a dry-run” is not the same as “it runs on the edge.” Deploying for real surfaced three genuine bugs — all of them the kind you only find by doing it:
fileURLToPath(import.meta.url)at module load. A few modules resolved a package path at import time (to read a version, to find the migrations folder). The Workers runtime can’t resolveimport.meta.urlto a filesystem path, so the Worker threw “path argument must be… Received undefined” on every deploy — before running a single line of our logic. Fix: make those lazy, so they only run when actually called (which, on the Worker, is never).- Storage hard-required S3 credentials. The Worker entry unconditionally constructed the S3/R2 adapter and threw if the creds were missing. That’s wrong — file storage is optional; the planning core doesn’t need it. Fix: only wire storage when its credentials are present, exactly like
plandesk servealready did. - An SPA redirect loop. The web build ships a
_redirectsfile (/* /index.html 200) for Netlify/Pages-style hosts. On Workers,not_found_handling = "single-page-application"already does that — having both created an infinite-loop rule Cloudflare rejects.
None were caught by the test suite or wrangler --dry-run, because they’re runtime/edge failures. The lesson, again: production is the only place some things are learned. All three are fixed and roll into beta.2.
A couple of smaller learnings:
- Turso wants an explicit
--groupif you have more than one. - Bootstrapping the first owner on a token-only hosted instance (no GitHub yet) has no self-serve path — we created it directly against the database. A
plandesk admin invite-owner --db <remote>is the proper fix, and it’s on the list.
Where it stands
Section titled “Where it stands”The hosted instance is live and the full stack is proven end to end: sign a request with an owner key → it resolves to owner through the live-role ceiling → create a project → it persists to Turso. Auth-gated, better-auth-wired, SPA served.
Still to come before public GA: GitHub sign-in on the hosted deploy (it’s token-only today), R2 file storage, a dashboard invite UI (invites are link-only right now), observability, and rate limiting. Those are the honest gaps — see the launch roadmap.
Next entries
Section titled “Next entries”We’ll append here as the beta proves out — GitHub sign-in going live, the first external testers, whatever else breaks. That’s the point of a beta.