Skip to content

feat: kosli get rego-policy --download writes a version's bundle to a file - #1290

Merged
jumboduck merged 6 commits into
mainfrom
feat/get-rego-policy-download
Oct 26, 2026
Merged

jumboduck merged 6 commits into
mainfrom
feat/get-rego-policy-download

Conversation

@jumboduck

@jumboduck jumboduck commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

kosli get rego-policy gets a --download FILE flag. With --policy-version, it writes the bundle of that version to FILE as a gzipped tar, exactly as the server sends it. It uses the bundle route that kosli-dev/server#7590 added. Part of kosli-dev/server#7380.

kosli get rego-policy pr-approved \
	--policy-version 3 \
	--download ./pr-approved-v3.tgz

Behaviour

  • It prints one line, for example Downloaded version 3 of rego policy 'pr-approved' to ./pr-approved-v3.tgz, in place of the version table.
  • --download without --policy-version is refused before any request. An empty --download is refused too.
  • An existing FILE is refused and kept. The error says to remove it or choose another file.
  • A 404 shows the server's message, and no file is created.
  • The bundle is not extracted. An earlier revision of this PR extracted it into a directory; that was dropped after review, and can follow as its own slice if users ask for it. To edit and republish, run tar -xzf first.

Tests

  • Unit test for BundleURL.
  • Command tests: the download, the refusal to overwrite, the refusal without --policy-version, the empty value, and the 404.
  • The empty-flag audit coverage and spec include download.
  • make lint: 0 issues. Not yet run end to end against a server with the bundle route.

Checklist

🤖 Generated with Claude Code

…directory

The server now serves every file of a rego policy version as one
gzipped tar (kosli-dev/server#7380). --download DIR, with
--policy-version, writes those files into DIR at the paths they were
published with, so a version can be inspected or replayed offline.

Every member is checked before any file is written: it must be a
regular file at a path inside DIR, and no file may already exist
there. A refused bundle leaves the directory as it was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added go Pull requests that update go code feat labels Oct 22, 2026
Comment thread internal/regopolicies/bundle.go Fixed
@claude

claude Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @jumboduck's task in 3m 6s —— View job


Follow-up review of the newest commits (1a3bf266, 2333f995)

  • Gather context (new commits, previous findings)
  • Evaluate status of each previous finding touched by new commits
  • Review new commits' changed lines for new issues
  • Post inline comments for resolved/new findings — none needed, see below
  • Post summary comment

Note: BEFORE=0fcec9e9 wasn't reachable locally (the branch was rebased — df6f38ae/0fcec9e9 now have new hashes 1a3bf266/2333f995), so per the fallback rule I used gh pr diff / gh api compare, confirming via git log that these two commits are exactly the ones added since the last review round.

Status of previously raised findings touched by these commits:

  • SnykCode path traversal, duplicate/colliding archive members, symlink escape, missing-ancestor-directory cleanup (all in internal/regopolicies/bundle.go) — resolved/moot, unchanged from the prior round: that file and its tests are gone, deleted in 1a3bf266 (df6f38ae pre-rebase). All corresponding review threads are already marked resolved on GitHub.
  • "Write failure leaves a stuck partial file with a misleading 'already exists' error" (cmd/kosli/getRegoPolicy.go, writeNewFile) — resolved by 2333f995 (0fcec9e9 pre-rebase). Verified in the current code (cmd/kosli/getRegoPolicy.go:157-174): writeNewFile now calls file.Close() unconditionally, keeps the first error from Write/Close, and os.Remove(path) runs whenever that combined error is non-nil — so a failed download no longer blocks a clean retry. The review thread is already marked resolved.

New issues in the changed lines: none found. I checked the diff 1a3bf266..2333f995 (doc text, runDownload/writeNewFile, the updated command tests, root.go flag text, and the bundle.go/bundle_test.go deletions) and confirmed no leftover references to the removed ExtractBundle/bundleFile types anywhere in the tree. Logic in writeNewFile is correct: a failure during OpenFile with ErrExist returns early without touching the filesystem; any other OpenFile failure returns before a file exists; a Write/Close failure after a file was created is now cleaned up.

Could not run go build/make lint/tests in this session due to tool permission restrictions (network/build commands required approval that wasn't available) — verification here is by code reading only.

0 new inline comments posted.

Comment thread internal/regopolicies/bundle.go Outdated
Comment thread internal/regopolicies/bundle.go Outdated
Comment thread cmd/kosli/getRegoPolicy.go
jumboduck and others added 2 commits October 22, 2026 18:44
Review of #1290 found ways past the promise that a refused bundle
writes nothing. A path held twice was written twice, and a path held
both as a file and as a directory failed after part of the bundle was
written. Both are refused now, before any write. The server does not
refuse the second case at publish, so a real bundle can hold it.

Writes go through os.Root with O_EXCL, so a symlink already inside the
directory cannot lead a write out of it. A bundle over 8 MiB
decompressed is refused, and directory entries are accepted. A test
pins the refusal of an empty --download, which the root command
already gives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jumboduck
jumboduck enabled auto-merge (squash) October 26, 2026 10:29
Comment thread internal/regopolicies/bundle.go Outdated
Comment thread internal/regopolicies/bundle.go Outdated
Comment thread internal/regopolicies/bundle.go Outdated
Comment thread internal/regopolicies/bundle.go Outdated
Comment thread cmd/kosli/getRegoPolicy.go Outdated
…ry left by a failed write

Review of #1290. The decompression cap is a 100 MiB safety bound, no
longer tied to the server's upload rule. Entry names go through
utils.LocalRelativePath, so a leading "/" is trimmed and ".. " or "..."
segments are refused as in the Azure unzip. The already-exists error
says how to recover. A directory the command created is removed when a
write fails; one that existed before is kept.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Comment thread internal/regopolicies/bundle.go Outdated
jumboduck added a commit that referenced this pull request Oct 26, 2026
…a file

Review of #1290. The bundle is written as the server sends it, a gzipped
tar, with no extraction. This drops internal/regopolicies/bundle.go and
its path-safety, size-cap and cleanup code. An existing file is refused
and kept. Extraction into a directory can follow as its own slice if
users ask for it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@jumboduck jumboduck changed the title feat: kosli get rego-policy --download writes a version's files to a directory feat: kosli get rego-policy --download writes a version's bundle to a file Oct 26, 2026
Comment thread cmd/kosli/getRegoPolicy.go Outdated
@claude

claude Bot commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Follow-up review of the new commits (002f85d5..df6f38a)

The approach changed substantially: ef8d15f9/002f85d5's directory-extraction code (internal/regopolicies/bundle.go + its tests) was deleted entirely. df6f38ae reimplements --download as pbeckham suggested — it now writes the server's gzipped-tar bundle unchanged to a single file opened with O_EXCL, with no tar parsing at all.

Status of previously raised findings:

  • SnykCode path traversal, duplicate/colliding archive members, symlink escape out of DIR, missing-ancestor-directory cleanup (mine), upload-cap/size-bound tracking, and the utils.LocalRelativePath suggestion — all resolved/moot: the file they applied to is gone, since the command no longer parses or extracts an archive. I replied on and resolved the one thread that was still open (ancestor-directory cleanup).
  • Empty --download "" refusal — still resolved via the existing root-command flag-wrapping guard; untouched by this diff and still pinned by a test.
  • "No --force, re-download always fails" (pbeckham) — still open/unaddressed, same behavior as before but now for a single file (already exists; remove it or choose another file). Acknowledged by the author as a possible future slice, not required here.
  • "Do we need to extract in this PR? A thinner --download FILE slice..." (pbeckham) — adopted: this is exactly what df6f38ae implements.

New finding in the changed lines (posted inline): writeNewFile (cmd/kosli/getRegoPolicy.go:157-169) doesn't clean up the file if file.Write fails partway — a failed download leaves a partial file behind, and retrying then hits the "already exists" error with no indication the existing file is actually incomplete/corrupt.

View job run

jumboduck added a commit that referenced this pull request Oct 26, 2026
Review of #1290. A partial file left by a write or close error made a
retry fail as "already exists". The file is now removed on either error,
so a retry starts clean. No test: a portable test cannot force a write
failure on a real file.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
jumboduck and others added 2 commits October 26, 2026 15:11
… file

Review of #1290. The bundle is written as the server sends it, a gzipped
tar, with no extraction. This drops internal/regopolicies/bundle.go and
its path-safety, size-cap and cleanup code. An existing file is refused
and kept. Extraction into a directory can follow as its own slice if
users ask for it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review of #1290. A partial file left by a write or close error made a
retry fail as "already exists". The file is now removed on either error,
so a retry starts clean. No test: a portable test cannot force a write
failure on a real file.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@jumboduck
jumboduck force-pushed the feat/get-rego-policy-download branch from 0fcec9e to 2333f99 Compare October 26, 2026 14:11
@jumboduck
jumboduck merged commit 39857ce into main Oct 26, 2026
21 checks passed
@jumboduck
jumboduck deleted the feat/get-rego-policy-download branch October 26, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants