Prepare for launch
The checklist for taking a draft product live — the gates publish enforces.
The checklist for taking a draft product live — the gates publish enforces.
A product is born as a DRAFT. Going live means passing the publish gates — the
same checks the dashboard's "Finish setting up" flow runs. farthershore product publish enforces them and prints a stable bracketed code with remediation when a
gate fails. This is the agent-operable version of the launch flow; work it top to
bottom before you invite subscribers.
publish refuses until all of these hold:
| Gate | How to satisfy it | Failure code |
|---|---|---|
| At least one plan | farthershore plan create … (or a @Plan member) | — |
| Every plan has a rate limit | A limits.requests rule on each plan | PLAN_RATE_LIMIT_REQUIRED |
| A product origin | --origin at create, or @Product({ origin }) | — |
| Stripe connected | farthershore connect stripe <product> (browser) | STRIPE_NOT_CONNECTED |
| Stripe verified (KYC) | Finish the Stripe onboarding in the browser | STRIPE_NOT_VERIFIED |
| Tax enrollment | Enroll in Stripe Tax in the dashboard | BILLING_TAX_NOT_ENROLLED |
Catch schema and cross-reference errors — a plan granting an undeclared
capability, a route reporting an undeclared meter — before anything touches live
state. build runs the same deterministic compile the platform does.
farthershore build --format json
build does not enforce the per-plan rate-limit gate (so byte-identical fixtures
can stay limitless), but publish does. Every plan must carry at least one
rate-limit rule, e.g. limits: { requests: { rate: 600, interval: "minute" } },
or publish fails with PLAN_RATE_LIMIT_REQUIRED.
farthershore plan list croncloud --format json
Every plan needs a rate limit. If a plan is missing one, add a limits.requests
rule and rebuild — or, for a CLI-created plan, the --rate-limit flag (default
600/min) supplies it.
Billing connection is a browser KYC flow — the one step that can't be done headless. Poll status until it clears:
farthershore connect stripe croncloud --format json
Resolve STRIPE_NOT_CONNECTED → STRIPE_NOT_VERIFIED → BILLING_TAX_NOT_ENROLLED
in order; each remediation is printed when the gate trips.
publish --dry-run runs the full compile and semver derivation and returns the
computed bump + reasons without cutting a tag. A breaking (blocking-risk)
change is refused unless you pass --accept-breaking.
farthershore product publish croncloud --dry-run --format json
Confirm the computed bump matches your intent.
farthershore product publish croncloud --format json
Publish auto-derives the semver bump and cuts a vX.Y.Z release. Existing
subscribers are grandfathered by default — see Change a price
for moving them.
ACTIVE is not the same as serving. product status returns a derived live
boolean (ACTIVE + a real release applied + the edge serving the snapshot) — poll
it until live: true.
farthershore product status croncloud --format json
Before real subscribers arrive, mint a test persona in a preview environment, call the gateway, and confirm usage lands:
farthershore persona bootstrap croncloud --env preview --plan pro --format json
farthershore usage summary croncloud --format json
farthershore build compiles clean.plan list shows ≥1 plan and each carries a rate limit.connect stripe reports connected + verified.product publish --dry-run shows the expected bump; publish cuts the release.product status reports live: true and a real latestReleaseVersion.