Skip to content

Commit 0c89f2b

Browse files
tonychang04claude
andauthored
feat(skills): insforge.toml config-as-code + compute scale-to-zero docs (#62)
* feat(skills): document insforge.toml config-as-code flow Adds guidance for the new `npx @insforge/cli config export/plan/apply` commands that ship with CLI #109 and backend #1216: skills/insforge-cli/SKILL.md - New "Configuration" command section listing export/plan/apply - Calls out version-aware capability gating: supported sections apply, unsupported go to skipped[] with an upgrade message; no PUT issued for unsupported sections - "TOML is for knobs only — never embed programs" rule with pointers to the dedicated commands for SQL / functions / compute / frontend - "Surface skipped[] verbatim" rule with sample agent message - env(NAME) reference convention for sensitive fields (forward-looking; CLI side ships with secrets-validation PR #110) skills/insforge/auth/backend-configuration.md - Recommends config apply over direct PUT /api/auth/config when changing settings-page knobs - Keeps PUT documented for the "flip one boolean from function code" case Both files reference behaviors not yet shipped on @insforge/cli@latest. Hold this PR until CLI #109 and backend #1216 land so agents don't see docs for commands they can't run. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(skills): remove auth/backend-configuration.md The file mixed admin HTTP endpoint reference (PUT /api/auth/config, List/Delete Users, Anon Token) with SDK-side discovery guidance. That violated the parent skill's own scoping ("client-side @insforge/sdk integration; for backend infrastructure, use the insforge-cli skill"). With config-as-code landing (CLI #109), auth backend config is now a CLI workflow, not an HTTP-only escape hatch: - Read settings: `npx @insforge/cli metadata --json` - Change settings: `npx @insforge/cli config apply` The SDK-relevant guidance (best practices, common mistakes, OAuth provider checks, verification flow branching) was already duplicated in auth/sdk-integration.md, so deleting the file loses nothing the SDK developer needs. The few admin-only endpoints (List/Delete Users) are better served as future CLI commands than as docs in the SDK skill. Updated: - skills/insforge/SKILL.md: drop the Auth row from the "Backend Configuration (Not Yet in CLI)" table; add a pointer to the new CLI Configuration section - skills/insforge/auth/sdk-integration.md: replace two stale links to backend-configuration.md with the corresponding CLI commands Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(insforge-cli): tighten config section and add references/config.md Restructured the new Configuration content to match the conventions the rest of the skill follows: - Inline section in SKILL.md is now a tight command list + the three load-bearing rules (TOML for knobs only, surface skipped[] verbatim, env() refs for secrets), with a pointer to the deeper reference - New references/config.md covers: typical end-to-end flow, output shapes for export/plan/apply --json, partial-apply semantics, file location, sensitive-field handling, --json consent rule, and a common-mistakes table - New "Configure project settings (insforge.toml)" entry under Common Workflows so agents discover the flow from the workflow index - New Non-Obvious Behavior bullet explaining the per-project version drift and why direct API calls are unsafe - Frontmatter description updated to mention insforge.toml as one of the things this skill covers, so the trigger surface is right Bumped skill version 1.4.0 → 1.5.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(insforge-cli): trim config docs to ship-only scope Skill previously described forward-looking surface (SMTP example with env(SMTP_PASSWORD), `ConfigValidationError` for sensitive-literal rejection, password policy / OAuth providers / custom subdomain via TOML). None of that ships in CLI #109 — only `auth.allowed_redirect_urls` is wired in src/lib/config-schema.ts. Trim to match reality: - Narrow Configuration section to the one supported field - Drop `env(NAME)` callout in SKILL.md (validation not implemented) - Drop SMTP example block + sensitive-field section in references/ - Add explicit "Scope today" line + "Coming soon" stub for forward path - Tighten cross-refs in insforge/SKILL.md and auth/sdk-integration.md so they don't imply password-policy / OAuth providers are TOML-managed Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(compute): document scale-to-zero default and Fly.io mapping Compute services now deploy with Fly's full scale-to-zero (auto_stop_machines: stop, auto_start_machines: true, min_machines_running: 0) — see InsForge/InsForge#1251. Document this in the skill so agents: - Know scale-to-zero is the default behavior - Set the right cold-start expectation (~1s on shared-1x) - Understand the CLI/skill can only dial it *up* toward always-on, never below zero (it's already the floor on Fly) - Map InsForge's behavior to Fly's exact field names so users familiar with Fly can predict what they're getting - Know that pre-existing services need a redeploy to pick up the new defaults Also notes that flags for `auto_stop_machines: off|suspend` and `min_machines_running > 0` aren't yet exposed via the CLI — route latency-critical services through support for now. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: use Machines API field names (autostop/autostart) The first draft documented the fly.toml field names (`auto_stop_machines` / `auto_start_machines`). Companion fix in InsForge/InsForge#1251 corrected the backend to send the Machines API short names — `autostop` / `autostart` — because that's what the `POST api.machines.dev/v1/apps/<app>/machines` body actually accepts (`auto_*_machines` are silently ignored). Rewrites the scale-to-zero section to: - Show the body InsForge actually sends (short names) - Cross-reference both spellings in one table so users coming from fly.toml docs and users debugging via `flyctl machines list --json` both see what they expect - Note that `min_machines_running` is honored only in the app's primary region Authoritative schema reference: fly.MachineService in https://docs.machines.dev/spec/openapi3.json Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: commit to scale-to-zero as v1's only mode Earlier draft hedged with "not yet exposed via the CLI" language for autostop/min_machines override flags. Decision: don't build those for v1. One mode, less surface area, simpler support story. Rewrites both files to be explicit: - "v1 is the only mode" — every service is scale-to-zero, no flags - Removes the "What the CLI/skill can change" matrix that implied flags were coming. Replaced with a short "Why no override flags" paragraph explaining the tradeoff and the support escape hatch. - Adds a direct instruction for agents: don't ask "set autostop to off" or "keep N warm" — there's no flag, nothing the skill can do, route to support instead. Prevents the agent from invoking imaginary flags and confusing the user. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(skills): trim per writing-skills — drop content with no agent action Compute scale-to-zero (v1): - Drop the 33-line dedicated section in compute-deploy.md (fly.toml vs Machines API field-name table, "Why no override flags", "Already-deployed services") — v1 has one mode with zero flags, so there's no agent decision to support. Replace with one FAQ line for agents debugging cold-start questions. - Drop the SKILL.md callout paragraph for the same reason. Config: - Trim references/config.md from 898 to 335 words. Remove "Why this exists", the TOML-is-for-knobs table, "Handling skipped[]" prose, and "Coming soon" — all duplicate principles already loaded by SKILL.md's Configuration section. Keep what's unique to the reference: output shapes for --json mode, file location, and the common-mistakes table. Net: -105 / +11 lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(config): clarify -y/--yes vs --auto-approve alias REFACTOR pass from writing-skills TDD test. GREEN subagent flagged the relationship between the global -y/--yes flag and the subcommand-local --auto-approve as ambiguous. Single-row tweak in the common-mistakes table: name which is global, which is the subcommand alias, and that they have the same effect. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ed14fea commit 0c89f2b

6 files changed

Lines changed: 119 additions & 187 deletions

File tree

skills/insforge-cli/SKILL.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
name: insforge-cli
33
description: >-
4-
Use this skill when managing InsForge infrastructure with the CLI: projects, SQL, migrations, RLS policies, functions, storage buckets, frontend deployments, compute services, secrets/env vars, Stripe payment keys/catalog/products/prices/webhooks, schedules, logs, diagnostics, import/export, or **managing backend branches** (creating a branch project to test risky schema/auth/RLS changes, merging a branch back to prod, resolving merge conflicts). For app code with @insforge/sdk, use the insforge skill instead.
4+
Use this skill when managing InsForge infrastructure with the CLI: projects, SQL, migrations, RLS policies, functions, storage buckets, frontend deployments, compute services, secrets/env vars, Stripe payment keys/catalog/products/prices/webhooks, schedules, logs, diagnostics, import/export, **declarative auth redirect URLs via `insforge.toml`** (applied with `config apply`), or **managing backend branches** (creating a branch project to test risky schema/auth/RLS changes, merging a branch back to prod, resolving merge conflicts). For app code with @insforge/sdk, use the insforge skill instead.
55
license: MIT
66
metadata:
77
author: insforge
8-
version: "1.4.0"
8+
version: "1.5.0"
99
organization: InsForge
1010
date: May 2026
1111
---
@@ -173,6 +173,22 @@ For frontend hosting see **Frontend Deployments** above.
173173
- `npx @insforge/cli secrets update <key> [--value] [--active] [--reserved] [--expires]` — update secret
174174
- `npx @insforge/cli secrets delete <key>`**soft delete** (marks inactive; restore with `--active true`)
175175

176+
### Configuration — `npx @insforge/cli config`
177+
178+
Manage `auth.allowed_redirect_urls` declaratively via `insforge.toml` (project root). For changing redirect URLs, prefer this over `PUT /api/auth/config` — the CLI gates on backend version and surfaces a clean skip if the backend predates the field, where the raw PUT may 200-and-silently-drop.
179+
180+
- `npx @insforge/cli config export [--out insforge.toml] [--force]` — pull live config into TOML. Sections the backend doesn't expose are omitted.
181+
- `npx @insforge/cli config plan [--file insforge.toml]` — diff TOML vs. live state; shows which changes will apply vs. be skipped on the connected backend.
182+
- `npx @insforge/cli config apply [--file insforge.toml] [--dry-run] [--auto-approve]` — apply the TOML. Per-change capability gate: supported changes apply; unsupported go to `skipped[]` with an upgrade message and **no PUT is issued for them**. `--json` returns `{ plan, applied[], skipped[] }`.
183+
184+
> **If `apply` returns `skipped: [...]`, surface verbatim.** The user's backend predates this section. Tell them which sections were skipped and to upgrade; do not retry, do not bypass with `curl` (silent drop). Sample message: _"I tried to set `auth.allowed_redirect_urls` but your backend is on an older version that doesn't support it yet. Upgrade your backend and re-run `npx @insforge/cli config apply`."_
185+
186+
> **TOML is for knobs only — never embed programs.** SQL → `db migrations`. Function code → `functions deploy`. Compute → `compute deploy`. Frontend → `deployments deploy`. TOML carries booleans, strings, and arrays — anything bigger lives in its own file managed by a dedicated CLI command.
187+
188+
**Scope today:** only `auth.allowed_redirect_urls`. Password policy, SMTP, OAuth providers, custom subdomain, and similar will land in TOML later. For other `auth.config` fields today, use the dashboard.
189+
190+
See [references/config.md](references/config.md) for output shapes and a common-mistakes table.
191+
176192
### Schedules — `npx @insforge/cli schedules`
177193
- `npx @insforge/cli schedules list` — list all scheduled tasks (shows ID, name, cron, URL, method, active, next run)
178194
- `npx @insforge/cli schedules get <id>` — get schedule details
@@ -278,10 +294,29 @@ Run with no subcommand for a full health report across all checks.
278294

279295
**Payments use Stripe as source of truth**: use `payments config set` for Stripe keys, `payments sync` before relying on existing catalog data, and create a new Stripe price instead of editing amount/currency. Runtime checkout and customer portal integration belongs in the `insforge` SDK skill.
280296

297+
**`config apply` is version-aware**: per-project backends drift in version. The CLI probes `/api/metadata` and gates `auth.allowed_redirect_urls` on whether the backend exposes it; if not, the change lands in `skipped[]` with an upgrade message and **no PUT is issued**. Never bypass with `curl` to "force" a skipped field — older backends may 200-and-silently-drop. Surface skips to the user and ask them to upgrade.
298+
281299
---
282300

283301
## Common Workflows
284302

303+
### Configure auth redirect URLs (insforge.toml)
304+
305+
```bash
306+
# 1. Pull current config to insforge.toml (writes in project root)
307+
npx @insforge/cli --json config export
308+
309+
# 2. Edit insforge.toml — add/remove entries under [auth] allowed_redirect_urls
310+
311+
# 3. Preview the diff
312+
npx @insforge/cli --json config plan
313+
314+
# 4. Apply (use --yes for non-interactive — required in --json mode)
315+
npx @insforge/cli --json --yes config apply
316+
```
317+
318+
If `apply` returns a non-empty `skipped[]`, the user's backend predates this section — surface the entries verbatim with the upgrade ask. Don't retry, don't fall back to `curl` (older backends may 200-and-silently-drop). See [references/config.md](references/config.md).
319+
285320
### Set up database schema with migrations
286321

287322
```bash

skills/insforge-cli/references/compute-deploy.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ A: Use `compute update <service-id> --image <new-image-url>`. The machine is res
269269
**Q: What happens to my service if Fly.io has an outage?**
270270
A: It's down. InsForge runs your containers on Fly's infrastructure — Fly's uptime is your uptime. For HA, you'd typically deploy multiple services in different regions (future feature).
271271

272+
**Q: Why is the first request after idle slow?**
273+
A: v1 services scale to zero when idle and wake on the next request (~1s cold start on `shared-1x`). No flag to disable in v1; contact support if you need always-on.
274+
272275
**Q: I see `MANIFEST_UNKNOWN` in a stack trace. What is it?**
273276
A: After `flyctl` pushes your image, Fly asynchronously aliases the digest from the builder's namespace to your app's namespace. Until that propagates (usually < 8 s) the Machines API returns `400 MANIFEST_UNKNOWN` even though the digest is correct. The InsForge cloud silently retries 4 times with backoff `[2s, 4s, 8s]`, so you almost never see it. If retries exhaust, you get a structured `COMPUTE_IMAGE_NOT_AVAILABLE` 400 with `nextActions` telling you to re-run — re-runs are idempotent and typically succeed instantly because the alias has had time to propagate.
274277

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# npx @insforge/cli config
2+
3+
Deep reference for `config export | plan | apply`. The SKILL.md Configuration section has the principles and rules; this file has output shapes and the error table.
4+
5+
**Scope today:** only `auth.allowed_redirect_urls`. Other auth knobs are dashboard-only.
6+
7+
## Commands
8+
9+
```bash
10+
npx @insforge/cli config export [--out insforge.toml] [--force]
11+
npx @insforge/cli config plan [--file insforge.toml]
12+
npx @insforge/cli config apply [--file insforge.toml] [--dry-run] [--auto-approve]
13+
```
14+
15+
## File location
16+
17+
`insforge.toml` lives at the project root, alongside `package.json` and `.insforge/project.json`. Safe to commit to git.
18+
19+
## Output shapes (`--json` mode)
20+
21+
`config export`:
22+
```json
23+
{
24+
"written": "/abs/path/to/insforge.toml",
25+
"config": { "auth": { "allowed_redirect_urls": ["https://app.com"] } },
26+
"skipped": []
27+
}
28+
```
29+
30+
`config plan`:
31+
```json
32+
{
33+
"changes": [
34+
{
35+
"section": "auth",
36+
"op": "modify",
37+
"key": "allowed_redirect_urls",
38+
"from": ["https://app.com"],
39+
"to": ["https://app.com", "https://staging.app.com"]
40+
}
41+
],
42+
"summary": { "add": 0, "modify": 1, "remove": 0, "kept": 0 },
43+
"skipped": []
44+
}
45+
```
46+
47+
`config apply`:
48+
```json
49+
{
50+
"plan": { /* same shape as plan output */ },
51+
"applied": [ /* DiffChange objects that were applied */ ],
52+
"skipped": [
53+
{
54+
"key": "auth.allowed_redirect_urls",
55+
"reason": "your backend doesn't expose auth.allowed_redirect_urls — upgrade the project to apply this section"
56+
}
57+
]
58+
}
59+
```
60+
61+
## Common mistakes
62+
63+
| Mistake | What to do instead |
64+
|---|---|
65+
| Calling `PUT /api/auth/config` directly to change `allowedRedirectUrls` | Use `config apply` — it's version-aware; direct PUTs can silently drop on older backends |
66+
| Treating `skipped[]` as an error to retry | It's intentional; surface verbatim with the upgrade ask and stop |
67+
| Running `config apply` in `--json` mode without `--yes` | Add `-y`/`--yes` (global) or `--auto-approve` (subcommand alias — same effect); otherwise fails fast with `CONFIRMATION_REQUIRED` |
68+
| Re-running with `--force` to "fix" a skip | `--force` is only for `export`'s overwrite gate; skips need a backend upgrade |
69+
| Setting password policy / OAuth providers / SMTP via TOML | Out of scope today — dashboard-only |
70+
71+
## Related
72+
73+
- `npx @insforge/cli metadata` — read-only view of all backend config slices
74+
- **insforge** SDK skill `auth/sdk-integration.md` — how SDK code reads auth config at runtime

skills/insforge/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,10 @@ These modules still require HTTP API calls because the CLI does not yet support
261261

262262
| Module | Backend Configuration |
263263
|--------|----------------------|
264-
| **Auth** | [auth/backend-configuration.md](auth/backend-configuration.md) |
265264
| **AI** | [ai/backend-configuration.md](ai/backend-configuration.md) |
266265

266+
> Auth redirect URL allowlist is now managed via the CLI — use `npx @insforge/cli config export/plan/apply`. Other auth settings (password policy, OAuth providers, verification methods) still live on the dashboard. See the **insforge-cli** skill's Configuration section.
267+
267268
### Risky backend changes? Use a branch first
268269

269270
When a code change in this skill depends on a **schema migration**, **new RLS policy**, **OAuth provider config change**, or any other backend change that could brick prod, create a backend branch first instead of editing the live project. Branches share `JWT_SECRET` (existing user JWTs keep working) but get a fresh database + EC2 + `API_KEY` / `ANON_KEY`, so you can test the SDK + backend change end-to-end in isolation.

skills/insforge/auth/backend-configuration.md

Lines changed: 0 additions & 182 deletions
This file was deleted.

skills/insforge/auth/sdk-integration.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,9 @@ Only render the reset form when `insforge_status=ready` and `token` is present.
362362
## Best Practices
363363
364364
1. **Always check auth config first** before implementing
365-
- Run `insforge metadata --json` to get auth config, or see [backend-configuration.md](backend-configuration.md)
365+
- Run `npx @insforge/cli metadata --json` to get auth config (`requireEmailVerification`, `verifyEmailMethod`, `resetPasswordMethod`, `oAuthProviders`, `allowedRedirectUrls`)
366366
- This tells you what features to implement
367+
- To **add a redirect URL** to the allowlist, use `npx @insforge/cli config apply` — see the **insforge-cli** skill's Configuration section. Other auth settings (password policy, OAuth providers, etc.) are dashboard-only today.
367368
368369
2. **The sign-up page must handle the full registration flow**
369370
- After calling `signUp()`, if `requireEmailVerification` is true, branch on `verifyEmailMethod`
@@ -450,7 +451,7 @@ if (enabledProviders.includes('github')) {
450451
## Recommended Workflow
451452
452453
```
453-
1. Get auth config → See backend-configuration.md
454+
1. Get auth config → npx @insforge/cli metadata --json
454455
2. Check what's enabled → Email verification? Which OAuth providers?
455456
3. Build appropriate UI → Code input vs magic link, OAuth buttons
456457
4. Implement sign-up → Handle requireEmailVerification response

0 commit comments

Comments
 (0)