Repository navigation
Description
Problem Statement
The current pre-1.0 tree still exposes multiple authoring models, commands, release channels, package paths, Cloud features, schema history, and documentation that the release decisions have retired. An operator cannot tell which CLI and Cloud surfaces will exist at 1.0, and a self-hoster cannot rely on one documented image and environment contract. A daemon deployed at 1.0 also needs an explicit additive wire and store promise before formats freeze.
Solution
Ship the agreed 1.0 surface as one coherent cleanup. Cloud authors the Deploy Intent; the CLI operates a Cluster over SSH contexts. A 1.0 daemon can keep working and upgrade throughout 1.x without reenrollment or reinstall. The SDK stays inside the workspace, Cloud can run without Polar, and a self-hoster can run the released Cloud image with the required services and their own GitHub apps. Remove retired product, release, CI, and documentation paths. Keep the final repository cutover and Hosted DNS build in their separately tracked efforts.
User Stories
- As a Cloud operator, I want one Deploy Intent authoring model, so that no Compose input competes with saved Cloud configuration.
- As a CLI operator, I want a small 1.0 command tree, so that help shows only supported Cluster operations.
- As a CLI operator, I want one spelling for each Service action, so that aliases and duplicate root commands do not mislead me.
- As a CLI operator, I want unsupported deploy, build, run, image, DNS, and changes paths gone, so that an available command always has a supported 1.0 use.
- As a Cloud user, I want Cloud to remain an operator of my Cluster, so that it does not become runtime authority.
- As a Machine operator, I want a 1.0 daemon to read later optional fields in replicated data, so that mixed 1.x Machines remain operable.
- As a Machine operator, I want to upgrade within 1.x without reenrolling or reinstalling, so that stable means durable.
- As a Machine operator, I want certificate material and enrollment to use the frozen 1.0 contracts, so that upgrades do not require a store migration.
- As a release operator, I want only stable and beta channels, so that installers and upgrades resolve predictable releases.
- As a release operator, I want a stable upgrade resolver to avoid prereleases, so that a stable Machine is not silently moved to beta.
- As a Cloud developer, I want SDK config to use WASM and RPC to use napi, so that each boundary has one implementation.
- As a Cloud developer, I want the SDK consumed from the workspace, so that npm publishing and version pins are unnecessary.
- As a Cloud user, I want retired Variable Groups, cron, waitlist, and stale pages removed, so that the application presents the actual 1.0 product.
- As a Cloud maintainer, I want dead server functions removed with their callers, so that unsupported product paths cannot be invoked.
- As a self-hoster, I want Cloud to start without a Polar token and grant unlimited Organizations, so that billing setup is optional.
- As a self-hoster, I want a clear required environment contract and my own GitHub apps, so that startup failures name missing setup.
- As a self-hoster, I want a released Cloud image and compose deployment, so that web, worker, Inngest, Redis, and Postgres can run together.
- As a developer, I want one fresh Postgres baseline, so that a new installation matches the release schema.
- As a developer, I want one Postgres test harness, so that database tests do not maintain duplicate infrastructure.
- As a maintainer, I want stale docs, evidence, CI jobs, and image build paths removed, so that release instructions describe what actually ships.
- As a release operator, I want the agreed contract tests, CI, and release qualification to pass, so that the cleanup is verifiable before cutover.
Implementation Decisions
- Cloud-authored Deploy Intent is the only authored model. Delete Compose input, its Go helper, and
x-*authoring. The CLI intent-file loader is after 1.0. - The 1.0 CLI keeps
cloud,machine,service,volume,ingress,ctx,project,proxy,ps, andversionas Cluster operations over SSH contexts. Removedeploy,changes,build,run,image push/images,dns, eight duplicate top-level Service commands, all aliases, and Go-templateversion -o. This supersedes the conflicting portions of the earlier greenfield CLI spec. - Standalone Cluster management over iroh is after 1.0. Today a Management Capability is minted only through Cloud Pairing. Keep Cloud as a client of Machine RPC, not a Cluster controller.
- The stable promise covers daemon-facing replicated store and bodies, local Machine record, Machine RPC under
PROTOCOL_MAJOR, enrollment protocol, and release source. Evolve frozen formats only by optional additive fields with defaults and tolerant readers. No version gates or store migrations. Do not apply blanket field tolerance to authored config or unrelated trust boundaries. - Drop replicated
created_at/updated_at, use a typed certificate body, reset enrollment protocol to 1, and make the WireGuard port a constant. Preserve explicit security refusals when relaxing parsers. - Keep only
stableandbetaRelease Channels. Tag syntax and resolution details follow the separate release-tag decision ticket. - The SDK is an internal workspace package, never npm-published. Config uses WASM only; napi serves RPC only. Delete publish and pack scripts, npm workflow, optional native package dependencies, and version-pin checks.
- Delete Variable Groups, cron, waitlist, Envoy-era certificate/ACME evidence, Organization logs/deployments pages, unused server functions, and marketing pages except authentication;
/becomes a stub lander. Preserve live deployment and certificate behavior that those old surfaces merely presented. - Squash Cloud migrations to one baseline. The existing Railway Postgres is disposable and will be dropped at release; no production data migration is required for this pre-stable cleanup.
- Cloud requires database, app URL, auth and encryption secrets, GitHub OAuth and App credentials, and Inngest keys. Polar is optional; no Polar token means billing disabled and unlimited Organizations. Custom-domain gating is kept, reduced to an active-subscription check that self-hosted always passes (#977). Drop installer override, Variable Groups flag, and Inngest signing-key fallback. Exact billing-disabled and packaging behavior follows the open decision tickets.
- Release a Cloud image for self-hosting: web, worker, Inngest, Redis, Postgres, and operator-owned GitHub apps. Ployz-hosted relay, Hosted DNS, installer, and release binaries remain shared infrastructure. Image layout and compose details follow the open packaging ticket. The final image name is
ghcr.io/getployz/ployz-cloudafter cutover. - Delete root Dockerfile, duplicate CI paths, old promise-based Postgres harness,
docs/andevidence/. Keep and rewrite DESIGN, CONTEXT, STANDARDS, README, and RELEASE documents; leave skills untouched. Licensing is handled by its existing map ticket. History audit and public repo cutover remain separate, final map work. - Hosted DNS architecture and implementation remain separately tracked; this cleanup does not reintroduce daemon DNS RPCs or a reservation row. Full generated-domain qualification will be specified after Cloud domain ownership and self-host packaging are decided.
Testing Decisions
- Tests assert public behavior and persisted/wire contracts, not private dispatch or implementation helpers. Use existing seams only.
- CLI shape tests assert the exact 1.0 command tree and absence of removed commands, aliases, and flags.
- SDK contract tests assert WASM-only config and napi-only RPC from the workspace package.
- For every replicated body, a reader test adds an unknown field and checks that the same known value is recovered. Keep explicit forbidden-field checks where security requires them. Enrollment tests assert protocol 1.
- Installer and Release Channel tests assert stable/beta selection and stable never selecting a prerelease.
- Run the existing
baseline.postgres.testagainst the squashed fresh schema; remove the duplicate promise-based harness. - Cloud config tests assert required variables, Polar omission, and removal of fallback/override variables. Billing behavior follows the Polar-optional decision.
- The whole-repo seam is green CI plus
qualify-release.sh; extend qualification for generated domains and upgrade only when the separate Hosted DNS and packaging decisions make that test specifiable. Do not add another test seam.
Out of Scope
- Implementing Hosted DNS or deciding Cloud Cluster Domain ownership; these are separate map tickets.
- Standalone Cluster management over iroh, a CLI intent-file loader, self-hosted relay/DNS/installer, and a full marketing site.
- License file creation, repository history rewriting, repository cutover, and tagging the first stable release; each is separately tracked.
- Retrofitting compatibility for any pre-1.0 beta that never shipped stable.
Further Notes
Parent map: https://github.com/getployz/ployz2/issues/973. Source cleanup task: #975. The map's decisions govern conflicts with older open specs, including the earlier greenfield CLI and Cloud-to-Machine wire specs. Each implementation ticket should land green independently where practical; final CI and qualification gate the combined tree.
Activity
[-]Spec: 1.0 tree cleanup and release contracts[/-][+]Spec: first stable tree cleanup and release contracts[/+]