Repository navigation
fix(cli): reject a non-numeric or non-positive --chunk-size before encrypt backfill starts - #1194
Draft
calvinbrewer wants to merge 1 commit into
Draft
calvinbrewer wants to merge 1 commit into
calvinbrewer wants to merge 1 commit into
Conversation
…crypt backfill starts `stash encrypt backfill --chunk-size abc` coerced the flag with `Number(...)` and handed the resulting `NaN` straight to the backfill engine, which bound it into the page query's `LIMIT $n`. Postgres refused it, but only after the config and encryption client had loaded, a connection had opened and the dual-write gate had recorded its acceptance, and the refusal surfaced under the generic "Backfill failed" message that deliberately hides database text. `0` was worse: `LIMIT 0` returns no rows, which the engine reads as "nothing left" and reports as a completed backfill. Negatives and fractions failed the NaN way. The decision of what a chunk size is now lives in one helper, `src/cli/chunk-size.ts`, so the forward and reverse backfills cannot disagree. It is applied twice on purpose: at the argv boundary in `main.ts`, where the raw text is still in hand and the error can quote exactly what was typed, and again at the top of `backfillCommand` for callers that bypass argv. Both exit 1 with the same author-controlled message, which carries no row data. The handler check runs before anything is loaded or opened. `stash decrypt backfill` (#1193, still open) validates its own chunk size inline today; it can adopt `resolveChunkSize` once it lands. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
🦋 Changeset detectedLatest commit: 8b8b2b5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
stash encrypt backfillis the CLI command that encrypts an existing plaintext column in place, in chunks of rows, so a table can be migrated without downtime. Its--chunk-sizeflag was never validated:--chunk-size abcbecameNaNand reached the backfill engine, which bound it into the SQLLIMIT. Postgres refused it, but only after the encryption client had loaded, a database connection had opened, and the dual-write safety gate had recorded its acceptance, and the user saw only the generic "Backfill failed" message.--chunk-size 0was worse:LIMIT 0returns no rows, which the engine reads as "nothing left to do" and reports as a completed backfill.The command now rejects anything that is not a positive whole number with a clear message that quotes the value, and exit code 1, before it loads or opens anything.
Changes
languages/typescript/packages/cli/src/cli/chunk-size.ts:parseChunkSize(text or number → validated row count, orInvalidChunkSizeError) andresolveChunkSize(same, with a default for an absent flag). Text is matched as plain decimal digits, so1e3,0x10andInfinityare rejected too.main.ts: the argv boundary parses--chunk-sizethrough the helper so the error can quote exactly what was typed.encrypt/backfill.ts:backfillCommandvalidates again through the same helper at the very top, for callers that bypass argv, and threads the resolved value (notoptions.chunkSize) into the engine and the progress line. ExportsDEFAULT_BACKFILL_CHUNK_SIZE = 1000.--chunk-sizenow shows(default: 1000)and says it must be a positive whole number.skills/stash-cli/SKILL.md: flag table updated to match.src/cli/__tests__/chunk-size.test.ts(the helper) andsrc/commands/encrypt/__tests__/backfill-chunk-size.test.ts(the handler exits 1 and never loads config, the encryption client, a pool, or the migrations schema).stashpatch.Verification
pnpm --filter stash test: 92 files passed, 7 skipped, 1529 tests passed, 0 failed. (A fresh worktree first needs the@cipherstash/authdebug binding built, or 17 files fail at import; that is environmental and unrelated.)pnpm run code:check: no errors (the pre-existing 197 warnings are unchanged).stash manifest --jsonandstash encrypt backfill --helpboth show the new--chunk-sizedescription and default, matching the skill.--chunk-size abc,0,1.5,1e3,""and--chunk-size=-5each print--chunk-size must be a positive whole number of rows (got "…").and exit 1.tsc --noEmitin the CLI package reports 27 pre-existing errors in files this PR does not touch (stalewasm-typesand@cipherstash/stack/schematypes in a fresh worktree); none in the changed files.Related
stash decrypt backfillvalidates its chunk size inline today. Once this lands it can switch toresolveChunkSize(options.chunkSize, DEFAULT_DECRYPT_CHUNK_SIZE)and drop its own check, so the two directions share one definition.Review notes
chunk-size.ts, then the guard at the top ofbackfillCommand.main.tsand the handler is deliberate: argv has the raw text for a good message, the handler is the only guard for programmatic callers.--chunk-size -5(space-separated) as the flag followed by an unknown-5flag, so the value is read as absent and the default applies.--chunk-size=-5is rejected correctly. That is a pre-existing quirk shared by every value-taking flag.🤖 Generated with Claude Code