Release CodeTruss CLI v0.2.57 - #48
Merged
Merged
Conversation
Syncs the 0.2.57 source from the private monorepo. Two false-positive fixes reach users here: Firebase web API keys stop being reported as committed credentials (0.2.56), and an error-code enum stops being reported as three leaked passwords (0.2.57). The mirror's own .gitignore would have silently swallowed the new `.env.production.fixture` — `.env.*` matches it — which would have shipped the 0.2.56 acceptance assertions with no fixture to run against. The monorepo hit the same trap and carries the same negation; this adds it here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Syncs the 0.2.57 source from the private monorepo, byte for byte against the monorepo git objects (230 paths compared by blob hash, 0 mismatches, 0 missing).
That digest was not copied into
release-reference.json:pnpm release:artifactwas run against this tree, resolved from this repository's own lockfile, and the rebuilt archivecmps clean against the monorepo's copy, against this repo'slatestpointer, and against the bytes codetruss.com is serving right now. All three digests inrelease-reference.jsonwere re-measured off the files — archive, SBOM, and thedist/cli.cjsextracted from inside the archive — rather than transcribed.The blob-hash comparison was run a second time against the 0.2.55 monorepo tree as a negative control: it reported 21 mismatched paths and exited 1, so a sync that silently dropped or stale-copied a file would not have passed. The
cmpchain has two negative controls of its own: against the published 0.2.55 archive, and against a byte-identical copy with one NUL appended. Both exit 1.Why this one is urgent
https://codetruss.com/downloads/codetruss-cli-latest.jsonalready advertises 0.2.57, and itsreleaseUrl—.../releases/tag/v0.2.57— currently 404s, because the release does not exist yet. Tagging this merge is what makes the advertised URL resolve. Homebrew still installs 0.2.55.What users are actually waiting on
Both changes in this archive are false-positive fixes, which for a tool whose output is a security verdict is the failure mode that costs the most trust.
0.2.56 — Firebase web API keys are no longer reported as committed credentials. A
VITE_/NEXT_PUBLIC_-prefixed key, and a Firebase config object passed straight toinitializeApp({…}), are published to every visitor by design; reporting them as leaks was CRITICAL and HIGH noise respectively. These were the last two CRITICAL false positives on the ten-repo benchmark corpus.0.2.57 — an error-code enum is no longer three leaked passwords. A value that merely spells out its own key (
IncorrectEmailPassword = "incorrect-email-password") carries nothing the identifier beside it did not. Repo-supplied scope globs are also bounded before they reach the matcher.The downgrade is deliberately narrow, and the narrowness is pinned by a fixture rather than by prose: a server-side Google API key in the same
.env, under a name the build tool does not publish, is asserted to stay CRITICAL.This release supersedes an unreleased one
0.2.56 was merged to the monorepo and never released — no tag, no GitHub release, no Homebrew bump. That has precedent here (0.2.42, 0.2.47 through 0.2.49, and 0.2.54 are all merged-but-unreleased, served from the site). It is not retroactively released; its changelog entry rides along in the chain and its change ships inside these bytes. The mirror carries download artifacts only for versions that were actually released, so
public/downloads/codetruss-cli-0.2.56.*is deliberately absent, exactly as 0.2.54 and 0.2.47 through 0.2.49 are.The mirror's own
.gitignorewould have silently dropped the new fixtureThis is the one mirror-owned source change here, and it is not cosmetic.
secretsescalates on a path matching/\.env/, so a fixture that reproduces the Firebase false positive has to be named like one —packages/cli/scripts/fixtures/acceptance/.env.production.fixture. The mirror's.gitignorecarries.env.*, which matches it. A naive sync would have committed the 0.2.56 acceptance assertions with no fixture for them to run against.To be precise about the blast radius rather than overstating it: this would not have been silent. Deleting the fixture and running the script fails with
an expectation names .env.production, which no fixture producesand exits 1, so CI would have gone red on all six contexts that run the suite — a blocked release, not a false green. The fixture was restored byte-exactly afterwards. It is still a real defect, because the failure would have looked like a broken test rather than a missing file, and the obvious fix under time pressure is to delete the assertion.Measured, not assumed. Before the change,
git check-ignore -qon that path exited 0 (ignored) and named.gitignore:11:.env.*as the matching rule. After, it exits 1, andgit status --untracked-files=alllists the file as addable. The negation is scoped to that one directory, which holds fabricated keys:.env.localandpackages/cli/.env.productionboth still exit 0. The monorepo hit this same trap and carries the same negation with the same reasoning; this brings the mirror in line.Note that
git check-ignore -vexits 0 on any pattern match, including a negation, so it cannot answer this question —-qandgit statuscan.The acceptance check is capable of failing, in both directions
packages/cli/scripts/test-acceptance.mjsgrew from 2 fixtures / 2 verdicts to 4 fixtures / 6 verdicts. It executes the builtdist/cli.cjs— notsrc/, not the hosted implementation — and locates each assertion by an anchor string in the fixture text rather than a written-down line number, so editing a fixture cannot silently retarget it.Demonstrated red from inside this repository before being trusted:
PUBLISHABLE_CREDENTIAL_TYPES(revert the 0.2.56 exemption).env.production:6 … severity CRITICAL, expected INFOandsrc/firebase.ts:8 … severity HIGH, expected INFOPUBLISHABLE_ENV_BINDINGto match any binding (over-apply the exemption).env.production:21 (MAPS_SERVER_KEY): severity LOW, expected CRITICAL — the negative control … must keep firingSo the check fails if the fix is missing and fails if the fix is too broad.
packages/analyzer-engine/src/secrets.tswas restored byte-exactly afterwards (blob50bae10a…, matching the monorepo), the 230-path blob comparison was re-run and still reported 230 identical, and the archive stillcmps clean against the monorepo copy — so the tree in this PR is not a patched-back approximation.Where it runs.
.github/workflows/ci.ymlstill gates itsTeststep onmatrix.node != '20.9.0', so the acceptance script runs in six of the nine compatibility contexts (Node 22 and 24 on ubuntu, macos, windows) and in the tag-triggered release job, which runspnpm testunconditionally. The 0.2.55 changelog claimed "all nine"; that was recorded as a known wart in the 0.2.55 formula bump. It is stated correctly here.Bundle delta
dist/cli.cjsgoes from 828,065 bytes (0.2.55) to 834,037 (+5,972), 32 changed lines out of 296, first difference at byte offset 169,475. The archive grows 962,141 → 979,549 bytes. The eight-file archive membership is unchanged.Unlike 0.2.55, this delta is real behaviour:
packages/analyzer-engine/src/secrets.tsgains the publishable-client-identifier logic,packages/cli/src/config.tsbounds repo-supplied scope globs, andreceipt.tsis split intoreceipt-markdown.ts,receipt-store.tsandreceipt-verify.ts(1,042 lines out, 1,053 across three new files).The frozen renderers still reproduce
Receipts stay on
local-registry-v5. No frozen digest moved.packages/cli/test/verify-receipt.test.tsis byte-identical between the 0.2.55 and 0.2.57 monorepo trees — the pinned block still reads v1928da3c4…, v2113d62de…, v3f38a8bde…, v4288de3e2…, v56ae337ce….That matters here more than usual, because
receipt.tswas split across three files. The test is not decoration: flipping the last hex character of the v4 expected digest fails withrenders 'local-registry-v4' to the exact bytes its signature covers(1 failed, 20 passed), and the file was restored byte-exactly afterwards (blob3ffadf4a…) and re-run green (21 passed).No published artifact was modified
git statusunderpublic/downloads/reports nothing outsidecodetruss-cli-0.2.57.*and thelatestpointers, so 0.2.44 through 0.2.55 still carry exactly the bytes they were attested with.packages/cli/CHANGELOG.mdis 168 additions, 0 deletions; the published 0.2.55 section hashes identically (a477e1a8…) before and after.pnpm-workspace.yaml,.npmrc,pnpm-lock.yaml,package.json(root),README.md,CONTRIBUTING.mdand.github/are unchanged — a blob-hash sweep of the whole repository shows the tree diverging from the monorepo on exactly the same 25 mirror-owned paths as at the 0.2.55 sync point, plus.gitignore's intended edit.CHANGELOG.mdat the root is regenerated frompackages/cli/CHANGELOG.md. The generator was checked by feeding it the 0.2.55 package changelog and confirming it reproduces the committed 0.2.55 root changelog byte-for-byte; run with a release version that has no section it throws, and with a wrong npm-trail version its outputcmps non-zero, so it is capable of failing. Its npm-trail sentence stays at 0.2.50, becausenpm view @codetruss/cli dist-tagsstill reportslatestas 0.2.50.Checked locally before opening
pnpm install --frozen-lockfileresolves with the lockfile untouched (the only source change topackages/cli/package.jsonis the version string).pnpm validatepasses against this branch: typecheck,release:artifact,pnpm test(35 files, 440 tests, plus the deterministic-package, release-verifier, changelog-policy and acceptance suites),release:verify, andtest:install. The rebuilt archive reproduced533bd51c…exactly, and the acceptance script printed:release:artifactis itself the byte-identity gate: it refuses to replace an existing versioned archive whose digest differs from the one it just built. It ran with the monorepo's copy in place and did not throw.The release workflow's
awkextraction of the changelog entry was dry-run against the regeneratedCHANGELOG.mdand returns 47 non-empty lines (3,569 bytes), so the release note will not be install-steps-only; the sameawkfor a version with no entry returns 0 bytes, which is the case the workflow refuses to publish.🤖 Generated with Claude Code