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
7 changes: 6 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,16 @@ jobs:
smoke_directory="$RUNNER_TEMP/aqua-smoke"
mkdir -p "$smoke_directory"
AQUA_ROOT_DIR="$native_root" aqua install
"$native_root/bin/stack" --version
expected_version=$(node -e 'process.stdout.write(JSON.parse(require("fs").readFileSync("distribution/distribution-contract.json", "utf8")).product.currentSourceVersion)')
test "$("$native_root/bin/stack" --version)" = "stack $expected_version"
"$native_root/bin/stack" init -o "$smoke_directory/diagram.stack"
"$native_root/bin/stack" check "$smoke_directory/diagram.stack"
"$native_root/bin/stack" render "$smoke_directory/diagram.stack" -o "$smoke_directory/diagram.svg"
test -s "$smoke_directory/diagram.svg"
"$native_root/bin/stack" completions bash | cmp distribution/generated/share/bash-completion/completions/stack -
"$native_root/bin/stack" completions zsh | cmp distribution/generated/share/zsh/site-functions/_stack -
"$native_root/bin/stack" completions fish | cmp distribution/generated/share/fish/vendor_completions.d/stack.fish -
"$native_root/bin/stack" manpage | cmp distribution/generated/share/man/man1/stack.1 -
- name: Validate release supply chain
run: |
node --check scripts/create-supply-chain-smoke-fixture.mjs
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

`stack-sh/cli` is the open-source native Rust `stack` command for Stack architecture diagrams.

The repository contains native validation, formatting, and rendering commands. [Stack CLI 0.3.0](https://github.com/stack-sh/cli/releases/tag/v0.3.0) is the first supported native binary release for macOS 13 or newer and glibc-based Linux 2.31 or newer, on arm64 and x86_64. GitHub Releases, Homebrew, and the owner-maintained Aqua registry are available; Cargo and self-update are still planned. The target matrix, artifact names, verification material, channel ownership, and rollback rules are defined by the [distribution contract](./docs/distribution.md), with signing and verification procedures in the [supply-chain guide](./docs/supply-chain.md).
The repository contains native validation, formatting, and rendering commands. [Stack CLI 0.4.0](https://github.com/stack-sh/cli/releases/tag/v0.4.0) is the supported native binary release for macOS 13 or newer and glibc-based Linux 2.31 or newer, on arm64 and x86_64. GitHub Releases, Homebrew, and the owner-maintained Aqua registry are available; Cargo and self-update are still planned. The target matrix, artifact names, verification material, channel ownership, and rollback rules are defined by the [distribution contract](./docs/distribution.md), with signing and verification procedures in the [supply-chain guide](./docs/supply-chain.md).

## Install

Expand All @@ -21,7 +21,7 @@ aqua install
stack --version
```

For a direct installation, download the archive for your target and its verification material from [GitHub Releases](https://github.com/stack-sh/cli/releases/tag/v0.3.0). Verify the checksum signature and both attestations by following the [supply-chain guide](./docs/supply-chain.md), then follow the [direct installation steps](./docs/distribution.md#direct-installation). The macOS artifacts are reproducibly ad-hoc signed, not Apple-notarized; Sigstore and GitHub attestations provide the publisher-identity check.
For a direct installation, download the archive for your target and its verification material from [GitHub Releases](https://github.com/stack-sh/cli/releases/tag/v0.4.0). Verify the checksum signature and both attestations by following the [supply-chain guide](./docs/supply-chain.md), then follow the [direct installation steps](./docs/distribution.md#direct-installation). The macOS artifacts are reproducibly ad-hoc signed, not Apple-notarized; Sigstore and GitHub attestations provide the publisher-identity check.

## Commands

Expand Down Expand Up @@ -61,9 +61,9 @@ stack manpage

`stack lsp` runs a native [Language Server Protocol 3.18 adapter](./docs/language-server.md) over standard input and output. It provides incremental document synchronization, versioned diagnostics, completion, hover, hierarchical document symbols, and whole-document formatting for `.stack` files. The adapter negotiates UTF-8, UTF-16, or UTF-32 positions and delegates language semantics and formatting to the pinned compiler and engine rather than reimplementing them. Standard output is reserved for framed JSON-RPC messages.

`stack update` is implemented for future receipted direct installations, with `--check`, exact-version selection, authenticated release-manifest and archive verification, and rollback-aware atomic replacement. It refuses Homebrew, Aqua, Cargo, and unknown ownership. The published 0.3.0 binary does not contain this command and its manual installation has no receipt, so the self-update channel remains planned. See the [self-update contract](./docs/self-update.md).
`stack update` is included in 0.4.0 for future receipted direct installations, with `--check`, exact-version selection, authenticated release-manifest and archive verification, and rollback-aware atomic replacement. It refuses Homebrew, Aqua, Cargo, and unknown ownership. The 0.4.0 release manifest does not activate `self-update`, and the documented manual installation creates no receipt, so the channel remains planned. See the [self-update contract](./docs/self-update.md).

`stack completions <bash|zsh|fish>` and `stack manpage` generate deterministic shell integration and an offline roff manual from the CLI command metadata. Future release archives carry the exact generated files; Homebrew installs them into its managed completion and manual paths, while direct, Aqua, and future Cargo users can generate them into user-owned locations without modifying shell startup files. See the [completion and manual guide](./docs/completions.md).
`stack completions <bash|zsh|fish>` and `stack manpage` generate deterministic shell integration and an offline roff manual from the CLI command metadata. The 0.4.0 release archives carry the exact generated files; Homebrew installs them into its managed completion and manual paths, while direct, Aqua, and future Cargo users can generate them into user-owned locations without modifying shell startup files. See the [completion and manual guide](./docs/completions.md).

`stack icons list [PROVIDER] [QUERY]` searches the asset-free catalog by ID, product name, or category. The catalog currently contains 1,051 IDs: 305 AWS, 45 Google Cloud, 639 Azure, and 62 curated developer and collaboration tool icons. This command reads only metadata embedded in the CLI.

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Supported versions

Stack CLI 0.3.0 is the supported stable binary release. Before 1.0, only the latest stable release receives release support; `main` is an unreleased development revision. Download supported binaries and their verification material from the [v0.3.0 GitHub Release](https://github.com/stack-sh/cli/releases/tag/v0.3.0).
Stack CLI 0.4.0 is the supported stable binary release. Before 1.0, only the latest stable release receives release support; `main` is an unreleased development revision. Download supported binaries and their verification material from the [v0.4.0 GitHub Release](https://github.com/stack-sh/cli/releases/tag/v0.4.0).

## Reporting a vulnerability

Expand Down
2 changes: 1 addition & 1 deletion aqua/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ done

`aqua update` must leave the pinned fixture unchanged until a newer stable release exists. `aqua update-checksum` must then reproduce `tests/aqua/aqua-checksums.json` exactly. The file locks all four release archives to the SHA-256 values obtained from the release checksum asset after Aqua verifies its Sigstore bundle.

On the native host, repeat without `--test` in an isolated `AQUA_ROOT_DIR`, then run `stack --version`, `stack init`, `stack check`, and `stack render`.
On the native host, repeat without `--test` in an isolated `AQUA_ROOT_DIR`, then run `stack --version`, `stack init`, `stack check`, and `stack render`. Generate bash, zsh, and fish completions plus the manual and compare every byte with the tracked release assets.

## Publish an update

Expand Down
2 changes: 1 addition & 1 deletion distribution/distribution-contract.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"availability": {
"state": "available",
"message": "Stack CLI 0.3.0 is available from GitHub Releases, Homebrew, and the owner-maintained Aqua registry. Cargo and self-update remain planned."
"message": "Stack CLI 0.4.0 is available from GitHub Releases, Homebrew, and the owner-maintained Aqua registry. Cargo and self-update remain planned."
},
"versioning": {
"scheme": "Semantic Versioning",
Expand Down
2 changes: 1 addition & 1 deletion docs/completions.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The published release archive stores the exact same bytes at these paths:
| fish | `share/fish/vendor_completions.d/stack.fish` |
| manual | `share/man/man1/stack.1` |

The source tree after Stack CLI 0.3.0 contains these commands and assets. The immutable 0.3.0 archives predate them; do not infer that an older installed binary can generate them.
Stack CLI 0.4.0 is the first published release containing these commands and assets. Older installed binaries cannot generate them.

## Homebrew

Expand Down
20 changes: 10 additions & 10 deletions docs/distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This document defines the shared release contract for the Stack CLI. It is normative for GitHub Releases, Homebrew, Cargo, Aqua, and `stack` self-update implementations. The machine-readable source is [`distribution/distribution-contract.json`](../distribution/distribution-contract.json).

[Stack CLI 0.3.0](https://github.com/stack-sh/cli/releases/tag/v0.3.0) is available as a supported GitHub Release for every target below, through the owner-maintained Homebrew tap for the hosts marked below, and through the checksum-locked owner Aqua registry. Cargo and self-update remain **planned** and have no supported install command yet.
[Stack CLI 0.4.0](https://github.com/stack-sh/cli/releases/tag/v0.4.0) is available as a supported GitHub Release for every target below, through the owner-maintained Homebrew tap for the hosts marked below, and through the checksum-locked owner Aqua registry. Cargo and self-update remain **planned** and have no supported install command yet.

## Supported platform matrix

Expand Down Expand Up @@ -81,7 +81,7 @@ brew uninstall stack-sh/tap/stack

For releases carrying the generated assets, the formula installs bash, zsh, and fish completions plus `stack.1` through Homebrew's standard path helpers. It does not edit shell startup files. The formula does not remove or replace Stack configuration and icon stores during an upgrade or uninstall. Formula updates verify release checksums, provenance, and SBOM attestations before changing the archive mapping. The fail-closed update and recovery procedure is maintained in the tap's [maintainer guide](https://github.com/stack-sh/homebrew-tap/blob/main/docs/maintaining.md).

Homebrew was activated after the immutable `v0.3.0` release assets were published. The release manifest therefore remains the publication-time record, while this contract and the tap CI record the later channel activation; release assets are not replaced to retrofit that state.
The Homebrew v0.4.0 formula was activated after the immutable release assets were published. Its macOS ARM64, Linux ARM64, and Linux x86_64 lifecycle tests verify the archived completion and manual bytes during install, upgrade, and uninstall. The release manifest remains the publication-time record with only `github-release` in `verifiedChannels`; this contract and the tap CI record the later channel verification without replacing any release asset.

## Aqua installation

Expand All @@ -101,7 +101,7 @@ registries:
ref: 42702cda91a4156901b9a601bd143c43dcf05766
path: aqua/registry.yaml
packages:
- name: stack-sh/cli@v0.3.0
- name: stack-sh/cli@v0.4.0
registry: stack-sh
```

Expand Down Expand Up @@ -132,24 +132,24 @@ stack --version

Commit `aqua-checksums.json` with the configuration. To upgrade after a new stable Stack release, run `aqua update`, review the version change, then run `aqua update-checksum` and `aqua install`. Aqua owns the replacement; `stack` self-update must refuse to overwrite it. The registry maintainer procedure and four-target test command are in [`aqua/README.md`](../aqua/README.md).

Aqua installs the executable declared by its registry mapping and does not own shell startup files or a global manual database. On a release that includes the generator, use `stack completions` and `stack manpage` to write the desired user-owned files as documented in the [completion guide](./completions.md).
Aqua installs the executable declared by its registry mapping and does not own shell startup files or a global manual database. Stack CLI 0.4.0 includes the generators; use `stack completions` and `stack manpage` to write the desired user-owned files as documented in the [completion guide](./completions.md).

Aqua was activated after the immutable `v0.3.0` release assets were published. The release manifest remains the publication-time record; the pinned registry commit, generated checksum lock, contract, and CI runs are the later activation evidence. No release asset is replaced.
The Aqua v0.4.0 pin was activated after the immutable release assets were published. CI verifies all four target mappings without executing foreign binaries, then installs the native archive and compares all completion and manual generator bytes. The release manifest remains the publication-time record; the pinned registry commit, generated checksum lock, contract, and CI runs are the later verification evidence. No release asset is replaced.

## Direct installation

Download [Stack CLI 0.3.0](https://github.com/stack-sh/cli/releases/tag/v0.3.0), select the archive whose target matches the supported platform table, and obtain all matching verification material. Complete the [supply-chain verification](./supply-chain.md), then extract and install the verified binary. Replace `{target}` with the exact release target:
Download [Stack CLI 0.4.0](https://github.com/stack-sh/cli/releases/tag/v0.4.0), select the archive whose target matches the supported platform table, and obtain all matching verification material. Complete the [supply-chain verification](./supply-chain.md), then extract and install the verified binary. Replace `{target}` with the exact release target:

```sh
tar -xzf "stack-v0.3.0-{target}.tar.gz"
tar -xzf "stack-v0.4.0-{target}.tar.gz"
mkdir -p "$HOME/.local/bin"
install -m 0755 "stack-v0.3.0-{target}/stack" "$HOME/.local/bin/stack"
install -m 0755 "stack-v0.4.0-{target}/stack" "$HOME/.local/bin/stack"
"$HOME/.local/bin/stack" --version
```

Add `$HOME/.local/bin` to `PATH` if it is not already present. This manual installation has no self-update receipt. The source tree after 0.3.0 contains `stack update`, but the published 0.3.0 binary does not, and this installation cannot be claimed retroactively without risking a package-manager-owned binary. Self-update remains unavailable until a later release and verified direct installer separately activate the channel. The command and receipt contract are documented in the [self-update guide](./self-update.md).
Add `$HOME/.local/bin` to `PATH` if it is not already present. This manual installation has no self-update receipt. Although 0.4.0 contains `stack update`, its release manifest does not activate `self-update`, and an unreceipted binary cannot be claimed retroactively without risking a package-manager-owned installation. Self-update remains unavailable until a later release and verified direct installer separately activate the channel. The command and receipt contract are documented in the [self-update guide](./self-update.md).

On a future archive that carries completion and manual assets, either copy the verified `share/` files into the matching system prefix or use the installed binary to generate user-owned files following the [completion guide](./completions.md). Do not copy these files from a different Stack version; CI and release verification require them to match the binary's command definition.
The 0.4.0 archive carries completion and manual assets. Either copy its verified `share/` files into the matching system prefix or use the installed binary to generate user-owned files following the [completion guide](./completions.md). Do not copy these files from a different Stack version; CI and release verification require them to match the binary's command definition.

## Channel ownership

Expand Down
2 changes: 1 addition & 1 deletion docs/self-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

`stack update` updates only a direct GitHub Release installation that has a matching Stack installation receipt. It never claims an unreceipted binary and never replaces an installation owned by Homebrew, Aqua, Cargo, or an unknown installer.

The command is implemented in the source tree after Stack CLI 0.3.0. The published 0.3.0 binary does not contain it, and the documented 0.3.0 manual installation does not create a receipt. The self-update channel therefore remains **planned** until a later release both activates `self-update` in its authenticated release manifest and has a verified direct installer that creates the receipt. Do not describe 0.3.0 as self-updatable.
The command is included in Stack CLI 0.4.0, but that release's authenticated manifest lists only `github-release`, and the documented manual installation does not create a receipt. The self-update channel therefore remains **planned** until a later release both activates `self-update` in its authenticated release manifest and has a verified direct installer that creates the receipt. Do not describe 0.4.0 as self-updatable.

## Commands

Expand Down
7 changes: 6 additions & 1 deletion scripts/aqua-registry.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ const configuration = fs.readFileSync(path.join(root, "tests/aqua/aqua.yaml"), "
const policy = fs.readFileSync(path.join(root, "tests/aqua/aqua-policy.yaml"), "utf8");
const registry = fs.readFileSync(path.join(root, "aqua/registry.yaml"), "utf8");
const distribution = fs.readFileSync(path.join(root, "docs/distribution.md"), "utf8");
const distributionContract = JSON.parse(
fs.readFileSync(path.join(root, "distribution/distribution-contract.json"), "utf8"),
);
const checksums = JSON.parse(
fs.readFileSync(path.join(root, "tests/aqua/aqua-checksums.json"), "utf8"),
);
const releaseVersion = `v${distributionContract.product.currentSourceVersion}`;

const targets = [
"aarch64-apple-darwin",
Expand Down Expand Up @@ -44,9 +48,10 @@ test("the registry maps exactly the four supported release targets", () => {

test("the checksum lock covers every archive and the registry revision", () => {
const revision = configuration.match(/^\s+ref: ([0-9a-f]{40})$/m)?.[1];
assert.ok(configuration.includes(`name: stack-sh/cli@${releaseVersion}`));
const expectedIds = targets.map(
(target) =>
`github_release/github.com/stack-sh/cli/v0.3.0/stack-v0.3.0-${target}.tar.gz`,
`github_release/github.com/stack-sh/cli/${releaseVersion}/stack-${releaseVersion}-${target}.tar.gz`,
);
expectedIds.push(
`registries/github_content/github.com/stack-sh/cli/${revision}/aqua/registry.yaml`,
Expand Down
13 changes: 13 additions & 0 deletions scripts/distribution-contract.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ test("source version drift is rejected", () => {
assert.throws(() => validateDistributionContract(candidate, cargoToml), /must match Cargo.toml/);
});

test("a stale stable release in the availability message is rejected", () => {
const candidate = changed((value) => {
value.availability.message = value.availability.message.replace(
`Stack CLI ${value.product.currentSourceVersion}`,
"Stack CLI 0.0.0",
);
});
assert.throws(
() => validateDistributionContract(candidate, cargoToml),
/must identify the verified stable GitHub release/,
);
});

test("an unverified crates.io package name is rejected", () => {
const candidate = changed((value) => {
value.product.publishedCargoPackage = "stack-cli";
Expand Down
Loading