Skip to content

ChangeSafe v0.2.0

Choose a tag to compare

@devtranger devtranger released this 28 Jul 23:10
· 86 commits to main since this release
19e696a

ChangeSafe v0.2.0

The engine is installable. v0.1.1 made the GitHub Action usable by tagging
it; this release puts the library and the CLI on npm, which is the adoption
path the roadmap has always described — an embeddable library and a
CI-friendly command-line gate
.

Nothing about the trust model changes. No policy behavior changes, and no
verdict changes.

npx changesafe gate --domain terraform --input tfplan.json
npm i @changesafe/core @changesafe/domain-terraform
Package What it is
changesafe The CLI: gate, analyze, eval, verify, keygen, ledger, serve, scenario. One bundled file, no dependencies
@changesafe/core The domain-agnostic gate: proposal contract, universal policies, risk derivation, workflow state machine, receipts, the DomainAdapter contract. Depends on zod alone
@changesafe/domain-network The network domain: declarative state, allowlisted transactional patches, deterministic reachability, sandboxed simulation
@changesafe/domain-terraform The Terraform domain: normalizes terraform show -json and polices destruction, protection, and reversibility. Never runs Terraform

@changesafe/ai, @changesafe/ledger, and @changesafe/server stay
unpublished for now; they are the self-hosting pieces and join in v0.3.0.

These four tarballs were published by hand. npm retired the classic publish
tokens the release workflow was written against, so 0.2.0 went out from a
maintainer's machine and carries no provenance attestation — the registry
records the publisher, not the workflow and commit that built it. Verify this
release the way the repository has always asked you to instead: check out the
v0.2.0 tag and reproduce it (see Verification below).

Publishing moves to npm trusted publishing (OIDC) from the next release, which
attaches provenance automatically. @changesafe/core already has the
publisher configured.

Embedding the gate

import { evaluatePolicies, hasBlockingFinding } from "@changesafe/core";
import { networkDomain } from "@changesafe/domain-network";

const { findings, riskLevel } = evaluatePolicies(networkDomain, incident, proposal);
if (hasBlockingFinding(findings)) {
  // Nothing in this library can approve it. That is the point.
}

A DomainAdapter teaches core what a change means in your world; the
universal policies then work unchanged. packages/core/tests/standalone-domain.test.ts
implements a complete toy domain in one file if you want the shape of it.

What changed since v0.1.1

The packages ship compiled JavaScript and declarations instead of
TypeScript source, so npm i works and editors resolve types. The workspace
still develops against source — no build step joined the test loop.

The Action no longer builds itself in your CI. It previously ran
npm ci on this whole repository inside every consumer's workflow before
evaluating a single policy. The CLI bundle is committed and executed
directly; CI rebuilds it and fails if the committed bytes differ from the
source, so what runs in your pipeline is what was reviewed here.

changesafe gate no longer prints an experimental-SQLite warning on every
run. The ledger's node:sqlite import is loaded when a ledger is opened.

--app-version joins --receipt-id and --created-at for regenerating
or re-verifying an audited snapshot with a later build. Ordinary runs record
this build's own identity and need nothing.

Version numbers, and one that stayed put

Package versions and build identity move to 0.2.0: receipts now record
appVersion: "changesafe-cli-0.2.0".

The policy versions did not move — core-v0.1.0, network-v0.1.0,
terraform-v0.1.0 — because no policy behavior changed. They answer a
different question from the release number: which gate decided, not which
binary ran
. A receipt from v0.1.1 and one from v0.2.0 therefore remain
directly comparable, and policyVersion still means what it has always meant.
tests/integration/version-sync.test.ts enforces both halves of that.

The published v0.1.0 verification snapshot still reproduces byte for byte
(npm run verify:v0.1.0) across this bump.

Upgrading

Your situation Do
Using the Action Move the pin to @v0.2.0 (or @v0 to track patches). Nothing else changes
Vendoring the repository to get the engine npm i @changesafe/core and delete the vendored copy
Running the CLI from a clone npm i -g changesafe, or npx changesafe. The clone still works
Self-hosting the decision server No change. @changesafe/server is still consumed from source until v0.3.0

Verification

git checkout v0.2.0
npm ci
npm run verify:v0.1.0   # the published v0.1.0 snapshot still reproduces
npm test                # 448 passing, 2 skipped
npm run build:cli && node packages/cli/dist/changesafe.js scenario check   # 9/9

The red-team corpus still refuses every proposal it is supposed to refuse,
including when the gate is reached through the installed packages rather than
this workspace — tests/integration/publishable-packages.test.ts gates the
route-leak scenario through unpacked tarballs and requires CRITICAL.