Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
* text=auto eol=lf

*.gif -text
*.ico -text
*.jpg -text
*.jpeg -text
*.pdf -text
*.png -text
*.tgz -text
*.webp -text
*.woff -text
*.woff2 -text
32 changes: 32 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!--
Coordinated changes only; see CONTRIBUTING.md.
Do not include private source, diffs, receipts, credentials, keys, or customer data.
-->

## Scope

- Approved issue or context:
- Intended change:
- Explicitly out of scope:

## Validation

- Tests added or updated:
- Commands run and results:
- If testing is incomplete, explain why:

## Privacy and network impact

- [ ] No private code, credentials, keys, receipts, or customer data are included.
- [ ] This change adds or modifies no network egress, telemetry, provider
authentication, sync/upload behavior, or command execution.

If either box is unchecked, describe the data, destination, trigger, consent,
credential handling, and safeguards:

## Release impact

- User-visible behavior:
- Release impact: none / patch / minor / breaking
- Changelog, version, package, SBOM, release-reference, website, or documentation
updates required:
24 changes: 17 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ concurrency:

jobs:
test:
name: Node ${{ matrix.node }}
runs-on: ubuntu-latest
name: ${{ matrix.os }} · Node ${{ matrix.node }}
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: ['20.9.0', '22', '24']
steps:
- name: Check out source
Expand All @@ -35,17 +36,26 @@ jobs:
run: |
corepack enable
corepack prepare pnpm@10.28.2 --activate
- name: Install locked dependencies for Node 20.9
if: matrix.node == '20.9.0'
run: pnpm install --frozen-lockfile --config.engine-strict=false
- name: Install locked dependencies
if: matrix.node != '20.9.0'
run: pnpm install --frozen-lockfile
- name: Typecheck
if: matrix.node != '20.9.0'
run: pnpm typecheck
- name: Build deterministic release artifact
run: pnpm release:artifact
- name: Test
if: matrix.node != '20.9.0'
run: pnpm test
- name: Build
run: pnpm build
- name: Verify distributable package
if: matrix.node == '24'
- name: Test deterministic release integrity on Node 20.9
if: matrix.node == '20.9.0'
run: |
node packages/cli/scripts/test-deterministic-package.mjs
node packages/cli/scripts/test-release-verifier.mjs
- name: Verify and install distributable package
run: |
pnpm release:artifact
pnpm release:verify
pnpm test:install
37 changes: 34 additions & 3 deletions .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: Existing attested GitHub release tag, for example v0.2.1
description: Existing attested GitHub release tag, for example v0.2.13
required: true
type: string
confirm_publish:
Expand Down Expand Up @@ -37,7 +37,8 @@ jobs:
- name: Check out the selected tag
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs.tag }}
ref: refs/tags/${{ inputs.tag }}
fetch-depth: 0
persist-credentials: false
- name: Set up Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
Expand All @@ -59,6 +60,8 @@ jobs:
throw new Error(`requested tag ${process.env.RELEASE_TAG} does not match ${expected}`)
}
NODE
TAG_COMMIT="$(git rev-parse "refs/tags/${RELEASE_TAG}^{commit}")"
test "$(git rev-parse HEAD)" = "$TAG_COMMIT"
- name: Install locked dependencies
run: pnpm install --frozen-lockfile
- name: Download the existing GitHub release assets
Expand All @@ -67,6 +70,22 @@ jobs:
run: |
mkdir release
gh release download "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --dir release
gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --json assets > release-assets.json
node - <<'NODE'
const { assets } = require('./release-assets.json')
const version = require('./packages/cli/package.json').version
const actual = assets.map((asset) => asset.name).sort()
const expected = [
`codetruss-cli-${version}.sbom.cdx.json`,
`codetruss-cli-${version}.tgz`,
`codetruss-cli-${version}.tgz.sha256`,
'release-manifest.json',
].sort()
if (JSON.stringify(actual) !== JSON.stringify(expected)) {
throw new Error(`release assets differ from the exact publish set: ${actual.join(', ')}`)
}
NODE
rm release-assets.json
- name: Verify exact release bytes
env:
GH_TOKEN: ${{ github.token }}
Expand All @@ -76,7 +95,19 @@ jobs:
pnpm test:install
VERSION="$(node -p "require('./packages/cli/package.json').version")"
gh attestation verify "release/codetruss-cli-${VERSION}.tgz" --repo "$GITHUB_REPOSITORY"
- name: Dry-run the exact npm package path
run: |
VERSION="$(node -p "require('./packages/cli/package.json').version")"
npm publish "./release/codetruss-cli-${VERSION}.tgz" \
--dry-run \
--access public \
--registry=https://registry.npmjs.org \
--tag=latest
- name: Publish with npm trusted publishing
run: |
VERSION="$(node -p "require('./packages/cli/package.json').version")"
npm publish "release/codetruss-cli-${VERSION}.tgz" --access public --provenance
npm publish "./release/codetruss-cli-${VERSION}.tgz" \
--access public \
--provenance \
--registry=https://registry.npmjs.org \
--tag=latest
13 changes: 8 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,21 @@ jobs:
with:
subject-path: ${{ steps.artifact.outputs.archive }}
sbom-path: ${{ steps.artifact.outputs.sbom }}
- name: Create immutable GitHub release
- name: Create, populate, and publish immutable GitHub release
env:
GH_TOKEN: ${{ github.token }}
ARCHIVE: ${{ steps.artifact.outputs.archive }}
CHECKSUM: ${{ steps.artifact.outputs.checksum }}
SBOM: ${{ steps.artifact.outputs.sbom }}
run: |
gh release create "$GITHUB_REF_NAME" \
"$ARCHIVE" \
"$CHECKSUM" \
"$SBOM" \
release/release-manifest.json \
--draft \
--verify-tag \
--generate-notes \
--title "CodeTruss CLI $GITHUB_REF_NAME"
gh release upload "$GITHUB_REF_NAME" \
"$ARCHIVE" \
"$CHECKSUM" \
"$SBOM" \
release/release-manifest.json
gh release edit "$GITHUB_REF_NAME" --draft=false
113 changes: 112 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,125 @@
CodeTruss CLI follows semantic versioning. Release artifacts and their SHA-256
checksums are published at <https://codetruss.com/downloads/codetruss-cli-latest.json>.

## 0.2.5 — 2026-07-14
## 0.2.13 — 2026-07-14

- Enable Git for Windows long-path support command-locally for every
CodeTruss-owned Git process and generated hook entry point. Exact private
evidence now remains usable in deep checkouts without changing the user's
repository or global Git configuration.
- Preserve the complete v0.2.12 SBOM, authentication-network-contract, hook,
verifier-isolation, and local-evidence hardening in a new immutable release
after the Windows compatibility matrix rejected the prior candidate.

## 0.2.12 — 2026-07-14 (unpublished)

- Preserve the complete v0.2.11 hook, Windows, verifier, and exact-evidence
hardening without replacing that candidate's immutable versioned bytes.
- Emit canonical Package URLs for scoped npm components in the deterministic
CycloneDX SBOM so registry and vulnerability tooling can match them.
- Correct the authentication network contract: `auth status` verifies the
saved credential with CodeTruss, while `auth logout` revokes it before
deleting the local copy; neither command sends repository data or receipts.
- Release review retained this candidate without publication after the Windows
matrix exposed a remaining Git `MAX_PATH` failure in deep private-evidence
directories. v0.2.13 carries the command-local long-path fix.

## 0.2.11 — 2026-07-14 (unpublished)

- Make agent hooks fail closed when exact baseline evidence, state locks, the
installed runner, or the local review process fails. A failed first Stop asks
for one repair turn; an already-active Stop reports the result without
creating an infinite continuation loop.
- Preserve retryability before final evidence is frozen and durably replay a
completed exact result after post-review transport failures, so a transient
crash cannot poison state or silently rerun a completed review.
- Bound the full hook pipeline inside its host deadline, terminate timed-out
verifier process trees, fairly allocate the remaining command budget, and
retain bounded head/tail output when a trusted verifier is noisy.
- Normalize Windows Git evidence against its native `NUL` sentinel, canonicalize
filesystem aliases before private-object-store containment checks, keep hook
state below native path limits, and keep the verifier deadline armed while
descendant-held output pipes remain open.
- Keep hosted analyzer indexing historically identical while enabling explicit
binary-aware local CLI indexing for archives, fonts, and WebAssembly assets.
- Include the hook-state migration and deterministic release-policy hardening
from the unpublished 0.2.6 through 0.2.10 candidates.
- Release review rejected this candidate before publication because its SBOM
encoded scoped npm package slashes noncanonically. The immutable artifact was
retained; v0.2.12 carries the corrected metadata.

## 0.2.10 — 2026-07-14 (unpublished)

- Freeze the hook-state migration only after its full-key precedence, candidate
collision cleanup, and empty legacy-root removal regressions passed. This
prevents the release artifact from racing the final privacy hardening.
- Include the migration and independent package-policy enforcement from the
unpublished 0.2.9 candidate.
- Independent release review rejected this candidate before publication after
finding that some Stop-hook operational failures did not block and that
verifier timeouts did not yet terminate the complete descendant process tree.

## 0.2.9 — 2026-07-14 (unpublished)

- Move compact hook state to a new versioned layout and explicitly retire the
legacy 64-character state tree, including owned private Git object stores, so
an upgrade cannot orphan captured task text or source evidence.
- Enforce a release-package policy independently from byte reproducibility:
fixed package identity and source links, no runtime dependency declarations,
no install lifecycle scripts, and matching CycloneDX component identity.
- Include the Windows path, cross-platform reproducibility, and strict release
verifier hardening from the unpublished 0.2.8 candidate.

## 0.2.8 — 2026-07-14 (unpublished)

- Byte-compare the complete packaged manifest, including lifecycle scripts and
dependency metadata, and require canonical release metadata and checksum
sidecars so a refreshed-but-tampered release cannot pass local verification.
- Bound private agent-hook state components to 96-bit hashed path keys and use
compact snapshot directories so exact evidence remains reliable under
Windows path limits; run CLI subprocess coverage through Node on every OS.
- Force LF source checkout across platforms, reject non-regular release inputs
even where symlink creation is unavailable, and include all deterministic
packaging and verifier hardening from the unpublished 0.2.7 candidate.

## 0.2.7 — 2026-07-14 (unpublished)

- Strictly verify the custom release envelope independently from the writer:
gzip framing, stored blocks, CRC32, ISIZE, USTAR magic, checksums, ownership,
modes, ordering, padding, terminators, exact entries, and `package.json.files`.
- Add boundary and corruption regressions, reject symbolic/non-regular package
inputs, enforce a 1 MB archive budget, and require every operating-system and
Node compatibility job to rebuild and match the immutable website archive.
- Keep engine enforcement strict on Node 22/24 while using a dev-dependency-only
override on Node 20.9; installed release archives receive no engine override.
- Include the deterministic packaging change from the unpublished 0.2.6
candidate.

## 0.2.6 — 2026-07-14 (unpublished)

- Replace `npm pack` release construction with a deterministic USTAR writer and
platform-independent stored-gzip encoder over the exact eight published
files. Website, GitHub Actions, provenance, and npm now verify one byte-for-byte
archive regardless of npm version, zlib build, or operating system.
- Separate Node.js 20.9 runtime smoke coverage from source-test coverage now that
modern Vitest requires a newer Node release. Node 20.9 still builds, installs,
verifies, and exercises the packaged CLI; Node 22 and 24 run the full source
suite.
- Include the verifier-isolation, baseline-repair, and lint-race hardening from
the unpublished 0.2.5 candidate.
- Public release review held this candidate before publication until the custom
format had an independent strict verifier and cross-platform SHA coverage.

## 0.2.5 — 2026-07-14 (unpublished)

- Keep final analysis, diff, and verifier evidence fail-closed while allowing a
repair to advance when an incomplete baseline becomes complete in the final
tree. The resolved historical limitation is explicit and forces
`REVIEW_REQUIRED`; it can never produce `PASS`.
- Include the external verifier isolation and binary-evidence hardening from the
unpublished 0.2.4 candidate.
- Dogfood and public CI rejected this candidate before release after finding a
transient lint race and platform-specific `npm pack` archive metadata.

## 0.2.4 — 2026-07-14 (unpublished)

Expand Down
60 changes: 60 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# CodeTruss Community Code of Conduct

## Our commitment

CodeTruss is committed to a welcoming, inclusive, and healthy community.
Everyone participating in CodeTruss spaces should be able to do so without
harassment or discrimination, including discrimination based on age, body size,
disability, ethnicity, sex characteristics, gender identity or expression,
experience, education, socio-economic status, nationality, appearance, race,
caste, color, religion, sexual identity, or orientation.

## Our standards

Expected behavior includes:

- Treating other people with empathy and respect
- Welcoming different viewpoints and experiences
- Giving and receiving constructive feedback
- Taking responsibility for mistakes and working to repair harm
- Protecting other people's private information

Unacceptable behavior includes:

- Harassment, threats, discrimination, or sexualized conduct
- Trolling, insults, derogatory comments, or personal attacks
- Publishing private information without explicit permission
- Any other conduct reasonably considered inappropriate in a professional
community

## Responsibility and scope

Maintainers are responsible for enforcing these standards and may remove, edit,
or reject content or contributions that violate them.

This Code of Conduct applies in CodeTruss repositories and community channels,
and whenever someone officially represents CodeTruss in public.

## Reporting and enforcement

Report abusive, harassing, or otherwise unacceptable behavior privately to
[zack@codetruss.com](mailto:zack@codetruss.com). Do not open a public issue with
sensitive details.

Reports will be reviewed promptly and fairly. Maintainers will protect the
privacy and security of reporters as far as reasonably possible. Depending on
the behavior, its impact, and any pattern of prior conduct, maintainers may issue
a correction or warning, restrict participation temporarily, or impose a
permanent ban.

## Attribution and license

This Code of Conduct is adapted and condensed from the
[Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).
It changes the original reporting instructions and condenses its enforcement
guidelines for the CodeTruss community.

Contributor Covenant version 2.1 is licensed under the
[Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).
Its Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
Loading
Loading