diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 26923d6..c159079 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -91,8 +91,9 @@ declarations at `dist/index.d.ts`. Local builds (outside CI) also emit Source maps are intentionally excluded from npm releases because they increase package size and are not required for normal CLI usage. The `files` field in -`package.json` whitelists only `dist/index.js` and `dist/index.d.ts`, so -`dist/index.js.map` is never published. If you add new build outputs under +`package.json` whitelists only `dist/index.js`, `dist/index.d.ts`, and the +copied assets (`dist/assets/forger.json`, `dist/assets/local/cli-overlay.yml`), +so `dist/index.js.map` is never published. If you add new build outputs under `dist/`, update `package.json` `files` accordingly. Inspect what would be published with: diff --git a/src/commands/branch/create.ts b/src/commands/branch/create.ts index 5e2c607..4d20c3a 100644 --- a/src/commands/branch/create.ts +++ b/src/commands/branch/create.ts @@ -297,12 +297,11 @@ async function waitUntilServing( /** * Poll the control plane until the branch reaches a terminal state. * - * A failed READ is not a failed branch. The control plane returning 502 once - * mid-poll used to end the command on the spot, while the backend went on to - * mark the branch ready ~15s later — leaving a real, billing branch behind a - * non-zero exit (agent-e2e runs 31832239687 and 32055449431). Transient - * failures therefore consume a poll interval and nothing more; only a real - * rejection (auth, 404, a terminal branch state) ends the loop early. + * A failed READ is not a failed branch: a 502 mid-poll must not end the command + * while the backend goes on to mark the branch ready, leaving a real, billing + * branch behind a non-zero exit. Transient failures therefore consume a poll + * interval and nothing more; only a real rejection (auth, 404, a terminal + * branch state) ends the loop early. */ async function pollUntilReady( branchId: string, diff --git a/src/commands/branch/reset.ts b/src/commands/branch/reset.ts index cd90ec9..7999e0d 100644 --- a/src/commands/branch/reset.ts +++ b/src/commands/branch/reset.ts @@ -11,8 +11,10 @@ import type { Branch } from '../../types.js'; const POLL_INTERVAL_MS = 3_000; // Reset re-runs pg_restore in-place, plus (for schema-only) the truncate -// finalize. Same order of magnitude as create — minutes for a small DB, -// longer for a populated one. Match create's 5-min budget. +// finalize. Minutes for a small DB, longer for a populated one. Note this +// does NOT match create's budget: create uses 15 min because slow regions +// were measured at 2–11.5 min (see create.ts); reset has not been +// re-measured, so its 5-min budget stands until it is. const POLL_TIMEOUT_MS = 5 * 60 * 1_000; // Retries for the post-timeout read that decides the verdict. Inside the loop // the interval is the retry; this one has no second chance. diff --git a/src/commands/local/start.ts b/src/commands/local/start.ts index fe5d644..ba9ea5c 100644 --- a/src/commands/local/start.ts +++ b/src/commands/local/start.ts @@ -334,6 +334,3 @@ export function registerLocalStartCommand(localCmd: Command): void { } }); } - -/** Exported for tests. */ -export const __testing = { parsePort, portOverrides, resolveStorage }; diff --git a/src/commands/local/stop.ts b/src/commands/local/stop.ts index 2336679..8dffd0f 100644 --- a/src/commands/local/stop.ts +++ b/src/commands/local/stop.ts @@ -105,10 +105,9 @@ export function registerLocalStopCommand(localCmd: Command): void { } } - // Before the success event, and before the --json early return. Both - // used to run first, so a partial delete was recorded as a success and - // exited 0 — and the catch below could not correct it, since telemetry - // only reports once per process. + // Must precede the success event and the --json early return: telemetry + // reports once per process, so a partial delete recorded as a success + // cannot be corrected by the catch below. if (remainingVolumes.length > 0) { throw new CLIError( `The containers are stopped, but ${remainingVolumes.length} volume` + diff --git a/src/lib/errors.ts b/src/lib/errors.ts index 0c95e87..454ca91 100644 --- a/src/lib/errors.ts +++ b/src/lib/errors.ts @@ -35,28 +35,15 @@ export class ProjectNotLinkedError extends CLIError { } } -export class NotFoundError extends CLIError { - constructor(resource: string) { - super(`${resource} not found.`, 4, 'NOT_FOUND'); - } -} - -export class PermissionError extends CLIError { - constructor(message: string = 'Permission denied.') { - super(message, 5, 'PERMISSION_DENIED'); - } -} - /** * True when a CLASSIFIED API failure says nothing about the operation being * polled, so a caller in a poll loop should read again rather than give up. * * Gateway 5xx is the case this exists for: `insforge branch create` polls the * control plane every 3s for up to 15 minutes, and a SINGLE 502 anywhere in - * that window used to abort a branch that the backend went on to finish - * creating seconds later (observed twice in agent-e2e: CLI out at ~90s and - * ~97s, branch ready at ~108s and ~113s). The branch still exists and still - * bills, so exiting is both wrong and expensive. + * that window must not abort a branch the backend goes on to finish creating. + * The branch still exists and still bills, so exiting is both wrong and + * expensive. * * Terminal by design: * - any CLIError with no `statusCode` — a locally raised error (a failed job, @@ -151,14 +138,6 @@ export function handleError(err: unknown, json: boolean): never { process.exit(1); } -export function getJsonFlag(cmd: Command): boolean { - let root: Command = cmd; - while (root.parent) { - root = root.parent; - } - return root.opts().json ?? false; -} - export function getRootOpts(cmd: Command): { json: boolean; apiUrl?: string; yes: boolean } { let root: Command = cmd; while (root.parent) { diff --git a/src/lib/guard/audit.ts b/src/lib/guard/audit.ts index d5ada10..01bfec3 100644 --- a/src/lib/guard/audit.ts +++ b/src/lib/guard/audit.ts @@ -31,5 +31,3 @@ export function audit(entry: AuditEntry): void { /* auditing must never block the guard */ } } - -export { AUDIT_FILE }; diff --git a/src/lib/local/checkout.ts b/src/lib/local/checkout.ts index 8d1f2db..cf9d218 100644 --- a/src/lib/local/checkout.ts +++ b/src/lib/local/checkout.ts @@ -1,12 +1,9 @@ /** * Fetch and run InsForge's own setup.sh to populate `.insforge/checkout/`. * - * The CLI used to carry a 266-line copy of the compose file plus the four files - * it inlines. That copy drifted within a day of being written — the connection - * pool alignment added upstream never reached it. So the stack definition comes - * from the repository now, through the script the repository already ships for - * exactly this: it owns the file list, the layout the compose file's relative - * mounts expect, and the secret generation. + * The stack definition is never vendored here: a copy drifts from upstream, and + * setup.sh owns the file list, the layout the compose file's relative mounts + * expect, and the secret generation. * * INSFORGE_NO_GIT=1 keeps `docker` the only thing a developer needs installed; * the script falls back to fetching each file over HTTPS. diff --git a/src/types.ts b/src/types.ts index bf76ca6..f0b9aa0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,10 +13,6 @@ export interface LoginResponse { user: User; } -export interface RefreshResponse { - token: string; -} - export interface Organization { id: string; name: string; @@ -25,11 +21,6 @@ export interface Organization { updated_at: string; } -export interface OrgMembership { - organization: Organization; - role: string; -} - export interface Project { id: string; organization_id: string; @@ -46,32 +37,10 @@ export interface Project { updated_at: string; } -export interface ProjectAuthResponse { - code: string; - expires_in: number; - type: string; -} - export interface ApiKeyResponse { access_api_key: string; } -export interface DatabasePasswordResponse { - databasePassword: string; -} - -export interface ConnectionStringResponse { - connectionURL: string; - parameters: { - host: string; - port: number; - database: string; - user: string; - password: string; - sslmode: string; - }; -} - // Stored credentials export interface StoredCredentials { access_token: string; @@ -196,13 +165,6 @@ export interface MergeConflictResponse { diff: DiffResult; } -// API Error -export interface ApiError { - code?: string; - error: string; - requestId?: string; -} - // OSS API types export type { ListFunctionsResponse, StorageBucketSchema, ListDeploymentsResponse, @@ -211,7 +173,7 @@ export type { ListFunctionsResponse, StorageBucketSchema, ListDeploymentsRespons CreateScheduleResponse, ListSchedulesResponse, GetScheduleResponse, ListExecutionLogsResponse, ListSecretsResponse, GetSecretValueResponse, CreateSecretResponse, DeleteSecretResponse, UpdateSecretResponse, CreateDeploymentResponse, CreateDirectDeploymentRequest, CreateDirectDeploymentResponse, - DeploymentManifestFileEntry, DeploymentManifestFile, UploadDeploymentFileResponse, + DeploymentManifestFileEntry, DeploymentManifestFile, StartDeploymentRequest, DeploymentSchema, DeploymentMetadataResponse } from '@insforge/shared-schemas';