Skip to content

Releases: asyncdotengineering/plandesk

Plan Desk 5.0.0

Choose a tag to compare

@octalpixel octalpixel released this 04 Oct 04:36

Self-hosting is now one command or one button on Docker, Cloudflare Workers or Vercel, and every target prepares its own database. See Self-hosting → Deployment topologies.

Breaking

  • PLANDESK_SESSION_SECRET is no longer read. Rename it to PLANDESK_BETTER_AUTH_SECRET (same value). A server that still has only the old name refuses to start and says so.
  • S3 storage needs PLANDESK_STORAGE=s3. Setting PLANDESK_S3_* without it is now an error that says so, instead of a setting plandesk serve silently ignored.
  • Docker files are renamed. Dockerfile.server is now Dockerfile and docker-compose.hosted.yml is now compose.yaml, which reads .env (cp .env.example .env). The container listens on 7526, the same port as plandesk serve.
  • plandesk deploy fly is gone; no Fly configuration ever shipped. plandesk deploy vercel is new, and the cloudflare and docker guides describe what the repository actually deploys (Workers + Turso + R2, not D1 or Pages).
  • Removed package exports, none of which had a caller:
    • @plandesk/api: version, removeOrganizationMember, updateOrganizationMemberRole, parseActor, InvalidActorSerializationError, healthRouter. SyncService is now TriageService.
    • @plandesk/db: version, getArtifactByProjectAndId, getNoteByProjectAndId, viewConfig. upsertSubmission/UpsertSubmissionInput, revokeGuestSession, revokeRenderToken and listPrototypeLinksByFromArtifact moved to @plandesk/db/testing.
    • @plandesk/mcp-client: version.
    • @plandesk/cli and @plandesk/runner: the "." entry. Both are command-line packages; run their binaries.
  • Migration 0025 drops the unused sync_state table.
  • @plandesk/server is a new published package, and @plandesk/cli now depends on it: plandesk serve, the Docker image, the Worker and the Vercel function share its one composition. Publish it before the CLI that depends on it.
  • @plandesk/mcp-client and @plandesk/runner are not part of this release. Their export changes above ship with their own next versions; the published 1.0.0 and 0.1.0 are unchanged.

Added

  • The server prepares its own database. plandesk serve, the Docker image, the Worker and the Vercel function all run migrations, the better-auth tables and the workspace backfills before serving, under a 60-second lease row (__plandesk_lease) so only one instance migrates at a time. While another instance holds it, requests answer 503 {"error":"schema_behind","schema":…} and retry. A remote database no longer needs a manual plandesk migrate; the command stays for operators who prefer a CI step.
  • Deploy to Cloudflare and Deploy with Vercel from the repository root (wrangler.jsonc with pnpm run deploy; vercel.json). Both serve MCP at /mcp; the Vercel entry never did before.
  • Real S3-compatible storage (AWS S3, R2's S3 API, MinIO): signed PUT and GET, bytes proxied through the server. An unreachable bucket answers 502 storage_unavailable.
  • One environment reader for every target. Values are trimmed and blank means unset; GitHub and S3 settings are all-or-nothing and a half-set group names what is missing. Workers and Vercel answer 500 misconfigured naming the variable.

Changed

  • Storage kind local is now db (bytes in the database). local is still accepted in PLANDESK_STORAGE and plandesk.server.json.
  • Notes and comments written over REST or the web app are stored as HTML, converted from Markdown in the service, the same as MCP writes.
  • Uploaded files are served under a script-free sandbox CSP. An uploaded SVG carrying <script> cannot run on the Plan Desk origin when opened directly; SVG still renders in <img>.
  • [::1] is recognised as loopback for a server URL, like 127.0.0.1 and localhost.
  • The task lane shows and can be set on cards and the task drawer.
  • plandesk login has no default server. With no --server it reuses the one saved in ~/.plandesk/config.json, or tells you to pass --server <your Plan Desk URL>. It used to fall back to a host that serves only these docs.
  • plandesk admin invite-owner builds its claim link on your server's public URL: --base-url, then PLANDESK_BASE_URL or baseUrl in plandesk.server.json. It warns when it can only fall back to loopback.
  • Imported file URLs must be https: (or http: to a loopback host), and their userinfo is dropped. An org export that carries any other external_url is now refused on import, all or nothing; edit that URL in the export and import again. File responses also send Referrer-Policy: no-referrer.

Fixed

  • Writes on a remote database are atomic again. Every multi-statement write (goals, tasks, projects, documents, folders, artifacts, prototypes, canvas) ran BEGIN and COMMIT on separate libSQL streams, so on Turso or sqld a successful write answered 500 and a failed one was not rolled back. Local file boards were never affected.

Install or upgrade: npm i -g @plandesk/cli@latest (published: @plandesk/db, api, mcp, server, cli at 5.0.0). Upgrading from 4.x: the 4.x → 5.0.0 guide. Full history: CHANGELOG.md.

Plan Desk 4.0.0

Choose a tag to compare

@octalpixel octalpixel released this 04 Oct 04:36

A major release because three surfaces are removed and every write path now rejects input it cannot honour. Everything else is additive. The board migrates in place on the next plandesk serve (migrations 0021–0024); see Upgrading → 3.x → 4.0.0.

Breaking

  • Arguments the server cannot honour are rejected, not dropped. MCP tools were registered with a bare zod shape, which the SDK wraps in a non-strict object, so an unknown argument was stripped and the call reported success (create_task dropped commit_refs; scaffold_project_from_plan once dropped goal_id). Every MCP input schema is now strict, and REST POST /projects/:id/tasks and PATCH /tasks/:id answer 400 naming the unknown key. Fields a sibling tool already accepted were added where they were missing (create_task.commit_refs/due_date, create_document.status_line, update_document.parent_id, create_edge.arrow_direction, scaffold task fields). REST PATCH /tasks/:id now forwards assignee and due_date, which the canvas panel sent and the route lost.
  • sync_pull and plandesk pull are gone. They talked to @plandesk/sync-server, removed in 1.x; no server answered, and sync_pull always replied "not promoted". The sync_remotes table is dropped.
  • plandesk legacy-upgrade is retired. Anyone still on a 0.20.x board runs npx @plandesk/cli@3.6.0 legacy-upgrade once, then upgrades normally.

Added

  • A task can belong to no goal. goal_id: null detaches a task over MCP and REST, and creates one with no goal. Omitting goal_id still attaches to the current goal, and the create response now says how it resolved (goal_resolution). With no active goal, new work gets no goal and no placeholder "General" goal is created; get_next_task serves goal-less todos.
  • Search reads bodies. Document, note and task bodies are indexed (SQLite FTS5, trigram), so paths like docs/foo-bar.md match as typed. Results rank title hits first and carry an excerpt, in MCP search, REST /search and the command menu.
  • Documents can say which repo file they mirror, and when anything was last verified. source_path on documents; verified_at/verified_ref on documents and tasks, set only explicitly. check_references (MCP) and GET /projects/:id/reference-check report mirrored files that no longer exist. The disk is probed only on a loopback server; elsewhere the answer is unknown.
  • Share links say how far they reach. They are built on PLANDESK_BASE_URL when set, and carry reachable_from: this_machine | network.
  • Skills install with npx skills add asyncdotengineering/plandesk. Copies connect vendors into a repo are marked metadata.internal: true, so a connected public repo does not appear to publish them. The heaviest skills load their conditional material on demand.

Fixed

  • A project link sets its workspace. Opening /projects/:id in another workspace made the breadcrumb, switchers and search describe the old one. The project's own workspace now becomes active; a project you cannot read shows a not-found page at once instead of three retries.
  • Share links no longer show org chrome to guests. /p/<token> rendered inside the app shell, exposing the org sidebar and switchers.
  • The workspace breadcrumb opens the project list, not the workspace picker.
  • Unknown /api paths answer 404, not 405 Allow: GET, under plandesk serve.
  • plandesk-groom-task frontmatter is valid YAML, so strict skill loaders stop dropping it.
  • Factory run state has one path (.agents/factory/runs/), and metrics.jsonl is tracked, as the factory contract always said.
  • In-process callers can no longer act as owner by default. A service with no request context and no explicit principal now throws instead of assuming owner.

Removed

  • About 4,000 lines with no live caller: GitHub OAuth helpers left behind when better-auth took over sign-in, the sync client, the legacy upgrader, a one-release hook migration, and unreferenced symbols. Every vocabulary now has one owner, and MCP tools register from one table.

Install or upgrade: npm i -g @plandesk/cli@4.0.0. Full history: CHANGELOG.md.