Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jwfing
left a comment
There was a problem hiding this comment.
Review: feat: services add --region + insta regions
Summary: A clean, well-scoped addition of user-selectable service regions — a new insta regions command and a --region flag on services add, with the body-building logic extracted into a pure, unit-tested helper. No blocking issues found.
Requirements context
No matching spec/plan found — this repo has no docs/superpowers/ or docs/specs/ directory, so I assessed against the PR description and the repo conventions in AGENTS.md / .claude/skills/developing-insta-cli/SKILL.md alone.
Findings
Critical
(none)
Suggestion
- Functionality —
src/commands/regions.ts:7-9:const { regions } = await api.request('GET', '/regions')followed byfor (const r of regions)will throw a non-iterableTypeErrorif the platform ever returns a body without aregionsarray. This mirrors the existingservicesListpattern ({ services }destructure with no guard), so it's consistent with the codebase and low-risk given the platform is the sole caller — noting it only as a hardening opportunity (e.g.for (const r of regions ?? [])), not a defect.
Information
- SW engineering —
test/services-add-body.test.ts:1: Uses thetest/expectAPI, whereas the sibling suitetest/services.test.tsusesdescribe/it. Both are valid in vitest; flagging only for stylistic consistency across the test dir. - Functionality —
src/commands/services.ts:52,61:buildAddServiceBodyembedsbranchinto the returned body, butservicesAddthen re-spreads the resolvedbranch(opts.branch ?? p.branch) over it. The result is correct (the resolved branch always wins, and the pure function's branch behavior is deliberately unit-tested), just mildly redundant — the branch is handled in two places. - Process —
AGENTS.mdnon-negotiable #4: Command/flag changes must be mirrored inskills/insta/cli-reference.md. That file lives in the insta-cloud superproject submodule (not present in this repo), and the PR body already notes the mirror update ships as a separate PR — just a reminder to land it so the agent-facing surface doc stays in sync.
Dimension coverage
- Software engineering ✅ — new pure helper
buildAddServiceBodyis unit-tested, matching the repo convention of testing pure helpers while leaving I/O command wrappers (servicesList,regionsList) untested. The--publicguard moving into the tested helper is a net improvement. - Functionality ✅ — validation is genuinely fail-fast:
assertType+buildAddServiceBodyrun beforeApiClient.load()/requireProject(), so a bad--region/--publicflag errors without any network or project resolution, exactly as the PR claims. Guards (--regionrejected for storage,--publiconly for storage) are correct and tested. - Security ✅ — no security-relevant risk: the region slug travels in a JSON request body (parameterized, no SQL/shell surface), nothing new is logged or returned, no auth/authorization paths change, and no dependencies are added.
- Performance ✅ —
insta regionsis a singleGET /regions; no loops, N+1, or hot-path work introduced.
Verdict
approved (informational — human approval via the separate approve flow). No Critical findings; the items above are all non-blocking.
Fermionic-Lyu
left a comment
There was a problem hiding this comment.
LGTM, Approved. (Relaying John-bot's approved verdict — approved with the maintainer account, since John-bot can't approve its own PR.)
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/commands/services.ts">
<violation number="1" location="src/commands/services.ts:51">
P3: An explicitly supplied empty region is not rejected for storage: `--region ""` makes `opts.region` falsy, so the guard is skipped and the request proceeds without a region. Checking for option presence instead of truthiness keeps the documented storage guard fail-fast.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| // Pure: build the POST body for `services add`, enforcing client-side guards (mirrors the platform). | ||
| export function buildAddServiceBody(type: string, name: string, opts: { branch?: string; public?: boolean; region?: string }): Record<string, unknown> { | ||
| if (opts.public && type !== 'storage') throw new Error('--public is only valid for storage services') | ||
| if (opts.region && type === 'storage') throw new Error('--region is not valid for storage services') |
There was a problem hiding this comment.
P3: An explicitly supplied empty region is not rejected for storage: --region "" makes opts.region falsy, so the guard is skipped and the request proceeds without a region. Checking for option presence instead of truthiness keeps the documented storage guard fail-fast.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/commands/services.ts, line 51:
<comment>An explicitly supplied empty region is not rejected for storage: `--region ""` makes `opts.region` falsy, so the guard is skipped and the request proceeds without a region. Checking for option presence instead of truthiness keeps the documented storage guard fail-fast.</comment>
<file context>
@@ -45,17 +45,24 @@ export function resolveComputeServiceId(services: Array<{ id: string; type: stri
+// Pure: build the POST body for `services add`, enforcing client-side guards (mirrors the platform).
+export function buildAddServiceBody(type: string, name: string, opts: { branch?: string; public?: boolean; region?: string }): Record<string, unknown> {
if (opts.public && type !== 'storage') throw new Error('--public is only valid for storage services')
+ if (opts.region && type === 'storage') throw new Error('--region is not valid for storage services')
+ return { type, name, ...(opts.branch ? { branch: opts.branch } : {}), ...(opts.region ? { region: opts.region } : {}), public: !!opts.public }
+}
</file context>
| if (opts.region && type === 'storage') throw new Error('--region is not valid for storage services') | |
| if (opts.region !== undefined && type === 'storage') throw new Error('--region is not valid for storage services') |
…--port) Both PRs extended 'services add': #61 added --region + client-side region guard; #63 (on main) added --image/--port + servicesAddRequestBody. Resolved by folding region into servicesAddRequestBody and the servicesAdd validation/output; dropped the now-redundant buildAddServiceBody + its test, moved region coverage into test/services.test.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
instaregion supportAdds the CLI surface for user-selectable service regions.
insta services add <type> <name> --region <slug>— sends the InstaCloud region slug (e.g.us-east) in the add-service body. Client-side guards:--regionis rejected for storage;--publiconly for storage. Validation runs before any network / project resolution (fail-fast on a bad flag).insta regions— lists the available regions fromGET /regions(supports--json).buildAddServiceBody(...).Depends on the platform PR (region on
addService+GET /regions). Requires a matchingskills/insta/cli-reference.mdupdate (separate PR).Testing
Full CLI suite green — 95 tests (incl. new
test/services-add-body.test.ts); typecheck clean.🤖 Generated with Claude Code
Summary by cubic
Adds region support to the CLI so users can pick a region when creating postgres/compute services and list available regions. Also unifies option handling with
--image/--port, improves help text, and keeps validation fail-fast.New Features
insta services add <type> <name> --region <slug>for postgres/compute;--regionis rejected for storage;--publiconly for storage. Region is sent in the request body.insta regionslists regions fromGET /regionsand supports--json.Refactors
servicesAddRequestBodyalongside--image/--port; updated CLI help inservices add.test/services.test.ts.Written for commit 432213d. Summary will update on new commits.