Repository navigation
chore(domain): stop guiding users to buy or delegate new domains - #378
Conversation
The platform paused new domain orders (domain_purchase_paused) and new BYO zone delegation (byo_delegation_paused) over the Cloudflare zone quota. Hide `domain search`, `domain buy` and `domain zone delegate` from help, keeping them registered so re-enabling is unhiding, and drop every printed hint that sends the reader to buy, search or re-run delegate. Attach/check/detach, bought-domain management and existing BYO zones are unchanged.
There was a problem hiding this comment.
4 issues found across 6 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="test/domain.test.ts">
<violation number="1" location="test/domain.test.ts:233">
P3: Removing this test drops the only coverage for `domainStatus` with `--org`, even though that path is unchanged. Keep a test that checks a canceled status with `--org` queries the named org and prints the canceled line.</violation>
</file>
<file name="test/zone.test.ts">
<violation number="1" location="test/zone.test.ts:112">
P3: The removed `zoneRecords('Byo.Example', { org: 'org9' })` case was the only test of `--org` routing and domain normalization for `zone records`. Keep a call-path assertion for it, such as checking the GET path is `/orgs/org9/zones/byo.example/records`, even though the reminder assertion is gone.</violation>
</file>
<file name="src/index.ts">
<violation number="1" location="src/index.ts:326">
P2: The agent-facing CLI reference still directs agents to this paused command, so hiding it from CLI help does not stop agents following the documented workflow. `AGENTS.md` requires syncing `skills/insta/cli-reference.md`; update that reference with this command change.</violation>
</file>
<file name="src/commands/domain.ts">
<violation number="1" location="src/commands/domain.ts:402">
P2: This removes the only recovery instruction for records the scan misses. `zoneRecords` only reads and prints records, so users cannot correct the managed zone there; retain the add-at-provider and re-run-delegate step before telling them to switch nameservers.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| const zone = dom.command('zone').description("Bring-your-own domains served from an InstaCloud-managed zone (nameserver delegation): point the domain's registrar at the pair `zone delegate` answers, and every attach's records — apexes included — are published for you. The alternative stays available: `insta domain attach` alone prints records to paste into your own zone") | ||
| zone.command('delegate <domain>').description("Delegate a domain you own elsewhere: builds its managed zone (seeded by a provider record scan — a HEURISTIC, so review `zone records` and add anything missing at your current provider BEFORE switching nameservers; re-running delegate re-imports) and answers the two nameservers to set at your registrar. A domain carrying live MX records is refused — move mail first or keep the records path (org admin; gated: zone.delegate — agent mode gates from a linked project, an unlinked --org call falls under org administration instead)") | ||
| const zone = dom.command('zone').description("Bring-your-own domains already delegated to an InstaCloud-managed zone: list them, review their records, or release them. For a hostname under a domain you own elsewhere, `insta domain attach` prints the records to add in your own DNS") | ||
| zone.command('delegate <domain>', { hidden: true }).description("Delegate a domain you own elsewhere: builds its managed zone (seeded by a provider record scan — a HEURISTIC, so review `zone records` against your current DNS BEFORE switching nameservers) and answers the two nameservers to set at your registrar. A domain carrying live MX records is refused — move mail first or keep the records path (org admin; gated: zone.delegate — agent mode gates from a linked project, an unlinked --org call falls under org administration instead)") |
There was a problem hiding this comment.
P2: The agent-facing CLI reference still directs agents to this paused command, so hiding it from CLI help does not stop agents following the documented workflow. AGENTS.md requires syncing skills/insta/cli-reference.md; update that reference with this command change.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/index.ts, line 326:
<comment>The agent-facing CLI reference still directs agents to this paused command, so hiding it from CLI help does not stop agents following the documented workflow. `AGENTS.md` requires syncing `skills/insta/cli-reference.md`; update that reference with this command change.</comment>
<file context>
@@ -321,14 +322,14 @@ ns.command('reset <domain>').description("Put the zone back on the registrar's o
-const zone = dom.command('zone').description("Bring-your-own domains served from an InstaCloud-managed zone (nameserver delegation): point the domain's registrar at the pair `zone delegate` answers, and every attach's records — apexes included — are published for you. The alternative stays available: `insta domain attach` alone prints records to paste into your own zone")
-zone.command('delegate <domain>').description("Delegate a domain you own elsewhere: builds its managed zone (seeded by a provider record scan — a HEURISTIC, so review `zone records` and add anything missing at your current provider BEFORE switching nameservers; re-running delegate re-imports) and answers the two nameservers to set at your registrar. A domain carrying live MX records is refused — move mail first or keep the records path (org admin; gated: zone.delegate — agent mode gates from a linked project, an unlinked --org call falls under org administration instead)")
+const zone = dom.command('zone').description("Bring-your-own domains already delegated to an InstaCloud-managed zone: list them, review their records, or release them. For a hostname under a domain you own elsewhere, `insta domain attach` prints the records to add in your own DNS")
+zone.command('delegate <domain>', { hidden: true }).description("Delegate a domain you own elsewhere: builds its managed zone (seeded by a provider record scan — a HEURISTIC, so review `zone records` against your current DNS BEFORE switching nameservers) and answers the two nameservers to set at your registrar. A domain carrying live MX records is refused — move mail first or keep the records path (org admin; gated: zone.delegate — agent mode gates from a linked project, an unlinked --org call falls under org administration instead)")
.option('--org <id>', "target org (default: linked project's org)").option('--json')
.action(guard((domain, o) => domainCmd.zoneDelegate(domain, o)))
</file context>
| const z = res.body as OrgZone | ||
| for (const line of zoneLines(z, opts.org)) info(line) | ||
| info(`the zone was seeded by a provider scan — a heuristic. Check \`insta domain zone records ${z.domainName}${orgArgOf(opts)}\` against your current DNS, add anything missing at your CURRENT provider (re-running delegate re-imports), and only then switch the nameservers.`) | ||
| info(`the zone was seeded by a provider scan, which can miss records. Check \`insta domain zone records ${z.domainName}${orgArgOf(opts)}\` against your current DNS, and only then switch the nameservers.`) |
There was a problem hiding this comment.
P2: This removes the only recovery instruction for records the scan misses. zoneRecords only reads and prints records, so users cannot correct the managed zone there; retain the add-at-provider and re-run-delegate step before telling them to switch nameservers.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/commands/domain.ts, line 402:
<comment>This removes the only recovery instruction for records the scan misses. `zoneRecords` only reads and prints records, so users cannot correct the managed zone there; retain the add-at-provider and re-run-delegate step before telling them to switch nameservers.</comment>
<file context>
@@ -402,7 +399,7 @@ export async function zoneDelegate(domainName: string, opts: RecordsOpts, deps?:
const z = res.body as OrgZone
for (const line of zoneLines(z, opts.org)) info(line)
- info(`the zone was seeded by a provider scan — a heuristic. Check \`insta domain zone records ${z.domainName}${orgArgOf(opts)}\` against your current DNS, add anything missing at your CURRENT provider (re-running delegate re-imports), and only then switch the nameservers.`)
+ info(`the zone was seeded by a provider scan, which can miss records. Check \`insta domain zone records ${z.domainName}${orgArgOf(opts)}\` against your current DNS, and only then switch the nameservers.`)
}
</file context>
| info(`the zone was seeded by a provider scan, which can miss records. Check \`insta domain zone records ${z.domainName}${orgArgOf(opts)}\` against your current DNS, and only then switch the nameservers.`) | |
| info(`the zone was seeded by a provider scan, which can miss records. Check \`insta domain zone records ${z.domainName}${orgArgOf(opts)}\` against your current DNS, add anything missing at your current provider and re-run \`insta domain zone delegate ${z.domainName}${orgArgOf(opts)}\` to re-import, and only then switch the nameservers.`) |
| }) | ||
| it('a canceled checkout says how to order again', async () => { | ||
| // New orders are paused (platform #689), so a canceled checkout names no way to order again. | ||
| it('a canceled checkout says why and does not send the reader to buy again', async () => { |
There was a problem hiding this comment.
P3: Removing this test drops the only coverage for domainStatus with --org, even though that path is unchanged. Keep a test that checks a canceled status with --org queries the named org and prints the canceled line.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At test/domain.test.ts, line 233:
<comment>Removing this test drops the only coverage for `domainStatus` with `--org`, even though that path is unchanged. Keep a test that checks a canceled status with `--org` queries the named org and prints the canceled line.</comment>
<file context>
@@ -228,21 +229,20 @@ describe('domain list / status', () => {
})
- it('a canceled checkout says how to order again', async () => {
+ // New orders are paused (platform #689), so a canceled checkout names no way to order again.
+ it('a canceled checkout says why and does not send the reader to buy again', async () => {
const { deps: d } = deps({ '/domains/orders': { items: [{ ...order, status: 'canceled', failedReason: 'checkout expired before payment' }] }, '/orgs/org1/domains': { items: [] } })
await domainStatus('myapp.com', {}, d)
</file context>
| await zoneRecords('Byo.Example', { org: 'org9' }, d) | ||
| expect(out()).toContain('re-run `insta domain zone delegate byo.example --org org9` to re-import') | ||
| expect(out()).toContain('compare them against your current DNS before switching nameservers') | ||
| // BYO delegation is paused (platform #687): the reminder no longer sends anyone to re-run it. |
There was a problem hiding this comment.
P3: The removed zoneRecords('Byo.Example', { org: 'org9' }) case was the only test of --org routing and domain normalization for zone records. Keep a call-path assertion for it, such as checking the GET path is /orgs/org9/zones/byo.example/records, even though the reminder assertion is gone.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At test/zone.test.ts, line 112:
<comment>The removed `zoneRecords('Byo.Example', { org: 'org9' })` case was the only test of `--org` routing and domain normalization for `zone records`. Keep a call-path assertion for it, such as checking the GET path is `/orgs/org9/zones/byo.example/records`, even though the reminder assertion is gone.</comment>
<file context>
@@ -105,11 +108,9 @@ describe('domain zone records', () => {
- await zoneRecords('Byo.Example', { org: 'org9' }, d)
- expect(out()).toContain('re-run `insta domain zone delegate byo.example --org org9` to re-import')
+ expect(out()).toContain('compare them against your current DNS before switching nameservers')
+ // BYO delegation is paused (platform #687): the reminder no longer sends anyone to re-run it.
+ expect(out()).not.toContain('zone delegate')
})
</file context>
jwfing
left a comment
There was a problem hiding this comment.
Summary
Copy-and-visibility-only change that stops the CLI pointing users at the paused buy / BYO-delegate paths; the hiding mechanism, the removed hints and the new help-surface test all hold up under mutation, and I found no blocking issue.
Requirements context
No /docs/superpowers/ and in fact no docs/ directory at all in this repo at a62874b — no matching spec/plan found, so I assessed against the PR body plus the repo's own written intent: AGENTS.md (§4 mirror command/flag changes in skills/insta/cli-reference.md; §6 MCP-tool rule) and .claude/skills/developing-insta-cli/SKILL.md. For the platform premise I read the companion PRs directly: InsForge/instacloud-platform #687 (BYO pause), #689 (purchase pause), #691 (BYO pause follow-up), instacloud-skills #180 and instacloud-mcp #100.
Verification I ran at this head (node v20.20.2, clean npm ci): tsc --noEmit exit 0; npx vitest run = 106 files, 2244 passed, 1 skipped (2245) — matches the body. CI at a62874b: test, test-windows and cubic all success.
Nine targeted negative controls, all RED (good coverage): un-hiding each of domain search / domain buy / domain zone delegate separately, and restoring each of the six removed hints (search → "buy one", canceled order → "order again", empty domain list → "(search: …)", empty zone list → "start one: …", zone records → "re-run … to re-import", zone delegate answer → "re-running delegate re-imports"). The new help-surface test really does pin all three hides, including zone being exactly list / records / release.
Findings
Critical
(none)
Suggestion
1. Functionality / release ordering — half the stated premise is not live yet (src/index.ts:288-295).
The body opens with "the platform has paused new domain orders (POST /orgs/:orgId/domains/orders answers 409 domain_purchase_paused)". The BYO half is true — platform #687 is merged, src/config.ts parses INSTA_BYO_ZONE_DELEGATION_ENABLED with an off-by-default regex and .env.example ships false, so byo_delegation_paused is real on main. The purchase half is not: domain_purchase_paused does not exist anywhere on platform main (code search: 0 hits; byo_delegation_paused: 5 hits), because #689 is still open. So if this merges and ships first, domain search / domain buy are undiscoverable while the platform still happily sells. The direction is conservative, so this is not blocking — but either land/ship this after #689, or soften the body's premise to "will answer" for the purchase half.
2. Functionality / UX — the review-then-switch contract lost its only remedy (src/commands/domain.ts:376-384, :430).
The old zone records line and the zone delegate answer told the reader what to do about a record the provider scan missed: add it at your CURRENT provider and re-run zone delegate to re-import. The new copy keeps the detection step ("compare them against your current DNS before switching nameservers") but names no remedy, and the CLI has none: the zone group is only list / records / release, nothing writes a record into a managed zone, and domain records 409s while the zone is managed (src/index.ts:314). Worth noting the dropped advice still works today — platform #691, which makes the pause cover re-runs, is open, so #687 only refuses new delegations. Suggest either keeping the re-run sentence until #691 lands, or naming the remaining escape hatch (insta domain zone release <domain> → back to the records path via domain attach) so a user who spots a gap in the review is not left at a dead end. (Same ground as cubic's P2 on src/commands/domain.ts:402; I agree with the concern, not with restoring the paused command unconditionally.)
3. Software engineering / test coverage — two deleted cases were the sole pin on behaviour this PR did not change. Both confirmed by running the same mutation at base (25a1fa3) and at head:
test/zone.test.ts:108-113dropped thezoneRecords('Byo.Example', { org: 'org9' })case. MutatingzonePath(src/commands/domain.ts:356-357) fromdomainName.trim().toLowerCase()todomainName.trim()is RED at base, GREEN at head (full suite 2244 pass) — the domain-name normalisation is now unpinned.test/domain.test.ts:233-240dropped the--orgcase. MakingdomainStatusignoreopts.org(orgDeps(opts, deps)→orgDeps({}, deps)) is RED at base, GREEN at head —--orgrouting fordomain statusis now unpinned.
Cheap fix: keep both cases, asserting only the request path (/orgs/org9/zones/byo.example/records,/orgs/org9/domains) now that the hint assertions are gone. (Confirms cubic's two P3s.)
Information
- The agent-facing surface is covered by companions the body undersells. "Not in this PR:
skills/insta/cli-reference.mdand the MCPinsta_search_domains/insta_buy_domaintools" reads as "not done", but both exist and are open:InsForge/instacloud-skills#180 ("docs(insta): stop teaching domain buy and BYO zone delegation", 48+/66-, 4 files) andInsForge/instacloud-mcp#100 (registers both tools only behindINSTA_DOMAIN_PURCHASE_ENABLED). Linking them in the body satisfiesAGENTS.md§4's "same change set" in the way this repo normally does (submodule PR) and answers cubic's P2 onsrc/index.ts:326outright.AGENTS.md§6 is not owed anything — no new leaf command. - Hidden ≠ refused, by design.
insta domain buystill runs and the user sees the platform's 409 message verbatim (src/api.ts:104→ApiError(res.status, res.body?.error …)); nothing in the CLI special-casesdomain_purchase_paused/byo_delegation_paused. That is the right call for a thin client, and it is what makes re-enabling a one-flag change — just flagging that an agent that already knows the verb gets the platform's wording, not the CLI's. - Mechanism check:
{ hidden: true }is the same mechanismenvandsetupalready use, and the new test proves each hidden path still resolves to its ownUsage:line, so this is genuinely reversible by deleting three flags. - Security: no security-relevant changes in this PR. No new user input, no new sink, no auth/authorization change, no dependency change (
package.json/ lockfile untouched); the only behavioural edits are printed strings and commander visibility flags. - Performance: nothing to report. No new request, loop, or allocation;
orderStatusLinesactually loses a parameter.
Verdict
approved — 0 Critical, 3 Suggestion, 5 Information. Informational only: the GitHub green check is a separate human action via the approve flow.
## What Release 0.1.26. It ships #378: `domain search`, `domain buy` and `domain zone delegate` drop out of help (they still run), and the hints that sent users to buy, search or re-run delegate are gone, matching the platform pauses that are now live. ## How `npm version 0.1.26 --no-git-tag-version`: `package.json` and `package-lock.json` only. After merge, tag `v0.1.26` on main to run `release.yml` (binaries, GitHub Release, npm). ## Verify - `npm run typecheck`, `npm test` and `npm run build` on Node 20. - After the tag: the GitHub Release has the binaries and `npm view insta version` answers 0.1.26. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
What
The InstaCloud platform has paused new domain orders (
POST /orgs/:orgId/domains/ordersanswers 409domain_purchase_paused) and new delegation of domains registered elsewhere (POST /orgs/:orgId/zonesanswers 409byo_delegation_paused). The CLI still advertised both and printed hints that led straight into those 409s.This PR stops the CLI from guiding users or agents to buy a domain or to delegate a domain registered elsewhere. Everything that still works is unchanged:
domain attach / check / detach, every verb for domains already bought through InstaCloud (list,status,renew,delegate,nameservers,records,transfer), and existing BYO zones (zone list / records / release).How
src/index.ts:domain search,domain buyanddomain zone delegateare registered with{ hidden: true }(the same mechanism asenvandsetup), so they drop out of help but still run. Re-enabling is removing the flag.src/index.ts: thedomaingroup description no longer offers buying. Thezonegroup andzone recordsdescriptions now describe existing zones and no longer tell anyone to run or re-runzone delegate.src/commands/domain.ts: removed the printed hintsbuy one: insta domain buy …(after search),order again: insta domain buy …(canceled order indomain status),(search: insta domain search <keyword>)(emptydomain list),start one: insta domain zone delegate <domain>(emptyzone list), and the "re-runzone delegateto re-import" advice inzone recordsand in thezone delegateanswer.README.md: theinsta domainrow no longer listssearchorbuy.skills/insta/cli-reference.mdand the MCPinsta_search_domains/insta_buy_domaintools still describe buying and BYO delegation.Verify
Run with Node 20.20.2:
npm run typecheck: passesnpm test: 106 files, 2245 tests passnpm run build: passestest/help-surface.test.ts:insta domain --helplists neithersearchnorbuy,insta domain zone --helplists exactlylist,records,release, neither root nor domain help mentions buying orzone delegate, anddomain search --help,domain buy --help,domain zone delegate --helpeach still resolve to their own usage line.test/domain.test.tsandtest/zone.test.tsnow assert the removed hints are absent.🤖 Generated with Claude Code