Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
211c718
test: require release provenance before publication
seonghobae Aug 6, 2026
72d8ca9
ci: gate release publication on provenance
seonghobae Aug 6, 2026
404f9e8
docs: define buyer-verifiable release provenance
seonghobae Aug 6, 2026
af17808
docs: record release provenance gate
seonghobae Aug 6, 2026
7d49171
test: isolate release artifacts from GPU bundles
seonghobae Aug 6, 2026
ccbb5b4
test: pin attestation action to exact release tag
seonghobae Aug 6, 2026
a73e1da
test: pin artifact download to an upstream release
seonghobae Aug 6, 2026
4e7ff34
ci: isolate and attest exact release artifacts
seonghobae Aug 6, 2026
2cbd186
docs: bind provenance actions to upstream release commits
seonghobae Aug 6, 2026
deeaabf
test: normalize workflow line endings
seonghobae Aug 6, 2026
002b801
test(release): reject duplicate CLI artifacts
seonghobae Aug 6, 2026
85957e3
test: require exact-head release checkout
seonghobae Aug 6, 2026
770b3fd
ci: bind provenance to exact release head
seonghobae Aug 6, 2026
6063fd2
docs: bind provenance evidence to exact head
seonghobae Aug 6, 2026
7d6b352
test: require exact-head quality checks
seonghobae Aug 6, 2026
93db7a5
ci: bind quality checks to exact head
seonghobae Aug 6, 2026
548de71
test(release): reject decoy checksum records
seonghobae Aug 6, 2026
0479650
fix(release): bind checksums to adjacent CLIs
seonghobae Aug 6, 2026
b5f46f3
docs(release): record checksum record binding
seonghobae Aug 6, 2026
7f30e1b
chore: record checksum binding hardening
seonghobae Aug 6, 2026
0c8d7aa
fix(release): support portable checksum verification
seonghobae Aug 6, 2026
3cb520a
test: require retry-safe release concurrency
seonghobae Aug 6, 2026
1e0f999
ci: keep explicit release reruns alive
seonghobae Aug 6, 2026
3c071d3
test(release): require retry-safe doctoring evidence
seonghobae Aug 6, 2026
ea76cd3
docs(release): explain retry-safe concurrency
seonghobae Aug 6, 2026
7a97da0
chore: record retry-safe release concurrency
seonghobae Aug 6, 2026
43ab8cd
fix(docs): satisfy retry concurrency contract
seonghobae Aug 6, 2026
a96e9f1
test(release): reject unexpected published artifacts
seonghobae Aug 6, 2026
e30899f
fix(release): reject unreviewed artifact entries
seonghobae Aug 6, 2026
b8d1b53
docs(release): define exact artifact allowlist boundary
seonghobae Aug 6, 2026
948f36f
docs(changelog): record exact release artifact admission
seonghobae Aug 6, 2026
8b0406c
fix(release): preserve checksum diagnostic precedence
seonghobae Aug 6, 2026
dae9186
docs(release): record diagnostic ordering
seonghobae Aug 6, 2026
9ea4faa
test(security): execute non-regular release rejection
seonghobae Aug 6, 2026
dbb1f5b
test(release): require tag and manifest version alignment
seonghobae Aug 6, 2026
2fd3db9
ci: stage PR 138 release version repair
seonghobae Aug 6, 2026
b891f38
feat(release): add fail-closed version verifier
seonghobae Aug 6, 2026
c0ae38a
fix(release): run version gate before packaging
seonghobae Aug 6, 2026
56c7855
test(release): measure version verifier at 100 percent
seonghobae Aug 6, 2026
544cd81
test(release): cover manifest and tag admission
seonghobae Aug 6, 2026
e28ae91
docs(release): record exact version admission contract
seonghobae Aug 6, 2026
cb4405e
docs(changelog): record release version gate
seonghobae Aug 6, 2026
996dd52
chore(ci): remove unused release version repair workflow
seonghobae Aug 6, 2026
d99f087
test(release): reject numeric prerelease leading zeroes
seonghobae Aug 6, 2026
9f7a079
fix(release): enforce SemVer prerelease numeric rules
seonghobae Aug 6, 2026
0274421
docs(release): record numeric prerelease SemVer rule
seonghobae Aug 6, 2026
1460d8d
docs(changelog): note strict prerelease SemVer validation
seonghobae Aug 6, 2026
c0f5684
test: reject flattened release artifact namespaces
seonghobae Aug 6, 2026
f11a009
fix: preserve release artifact namespaces
seonghobae Aug 6, 2026
83eefd0
docs: preserve release artifact namespace evidence
seonghobae Aug 6, 2026
e9cf4c1
docs: record preserved release artifact namespaces
seonghobae Aug 6, 2026
f327223
chore: preserve stacked architecture changelog evidence
seonghobae Aug 6, 2026
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
232 changes: 135 additions & 97 deletions .github/workflows/release.yml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Install Tauri system deps
run: |
Expand Down Expand Up @@ -47,6 +48,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
- name: Install build deps (llama.cpp native + tauri)
run: |
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and

### Fixed

- Added retry-safe release concurrency so a new first attempt still supersedes stale work while an explicit GitHub Actions rerun cannot cancel itself inside the same concurrency group.
- Made architecture evidence tests independent of the process working directory, verified linked evidence files actually exist, enforced heading and exact-head continuity, and retained the two-word `snake_case` database-object naming contract.
- Hardened iCloud local-copy batch eviction with fresh per-item timestamps, deterministic planner/executor/recorder/clock seams, fail-closed immutable checkpoint handling, bounded manifest admission, symlink-safe control-path validation, and distinct operator diagnostics.
- Restored the cloud-copy public documentation regression contract after a temporary repair path removed it, so CI continues to fail when the new Rust or TypeScript approval surfaces lose beginner-readable documentation.

### Security

- Require explicit organization-tenant authority in both the frontend projection and durable Rust transfer gate when either the organization destination scope or the organization-sensitive review reason is present, preventing a missing, contradictory, or malformed candidate field from making cloud approval less restrictive; record the fail-closed decision, rollback boundary, realistic signal-matrix tests, and APA 7th references in `docs/architecture/cloud-review-tenant-authority.md`.
- Separate runtime mutation authorization from repository merge and release authorization: runtime approvals bind exact operation scope, fingerprints, schema, and trusted-clock freshness, while exact repository-head evidence remains a CI and release gate and never becomes an operator credential.
- Added buyer-verifiable release artifact provenance with checksum-first admission, immutable `actions/attest` pinning, tag-only OIDC and attestation authority, and publication that depends on successful exact-artifact provenance generation.
- Preserve per-artifact directories during attestation and publication downloads so duplicate release basenames cannot be hidden by last-writer-wins archive flattening before exact-set admission.
- Fail closed before packaging when `package.json`, Cargo, and Tauri versions disagree, when a version is missing or malformed, or when a release tag is not exactly `v<manifest version>`.
- Enforce Semantic Versioning 2.0.0 numeric prerelease rules and reject leading-zero identifiers such as `1.0.0-01` before packaging.
- Bound every release checksum record to the exact adjacent operational CLI basename and reject malformed, multi-record, redirected, traversing, absolute, or decoy checksum targets before digest verification.
- Reject every unexpected eighteenth release file and every non-regular artifact-tree entry before attestation or publication, preventing unreviewed diagnostics, dumps, logs, secrets, or unrelated executables from becoming durable release assets.
- Persist copy-approval provenance in immutable receipt lineage, reject stale, generic, mismatched, or tampered approvals, and retain explicit backward readability for pre-approval receipt formats.
- Generate the npm lockfile in an exact-head validation job with repository contents read-only and dependency lifecycle scripts disabled, bind the artifact to SHA-256 evidence, and grant `contents: write` only to a separate publication job that verifies the same-run artifact and unchanged branch head before committing the lockfile.
- Removed obsolete one-shot repair workflows and patch scripts so repository automation no longer retains dormant write-capable recovery paths.
102 changes: 102 additions & 0 deletions docs/doctoring/release-artifact-provenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Release artifact provenance

## Decision

DiskSage treats provenance as a release gate rather than optional release metadata. A tagged release may be published only after all operating-system build jobs finish, the exact uploaded artifact set is downloaded into a clean tag-only job, every shipped operational CLI checksum is verified, and GitHub creates signed build-provenance attestations for the files that will be published.

This design keeps three authorities separate:

1. `build` compiles and tests release candidates with read-only repository access, then uploads ephemeral workflow artifacts.
2. `attest-release` receives only `contents: read`, `id-token: write`, and `attestations: write`. It verifies the expected platform and CLI set before generating provenance.
3. `publish-release` receives `contents: write` only after `attest-release` succeeds. It cannot publish an unattested build because it has a durable `needs: attest-release` dependency.

Pull requests and manual non-tag builds still produce inspectable artifacts, but they cannot request an OpenID Connect identity, create durable attestations, or publish a GitHub Release through these jobs.

## Evidence contract

The authoritative implementation is `.github/workflows/release.yml`.

The release contract requires all of the following:

- checkout binds every platform build to `github.event.pull_request.head.sha` for pull requests and `github.sha` for tags or manual runs, rather than silently treating a generated pull-request merge ref as exact-head evidence;
- release concurrency uses `github.run_attempt == 1`, so a fresh first attempt supersedes stale work while explicit rerun attempts do not cancel themselves inside the same concurrency group;
- the three platform builds upload the exact bundle and operational CLI paths that later jobs consume;
- release workflow artifacts use the `release-disksage-*` namespace, which excludes concurrently uploaded `disksage-gpu-*` diagnostic bundles;
- attestation and publication downloads preserve each workflow artifact in its own directory instead of flattening archives, so duplicate basenames remain observable and last-writer-wins extraction cannot erase evidence before admission;
- release publication is absent from the matrix build job, preventing any matrix member from publishing before the complete set exists;
- the attestation and publication jobs run only for `refs/tags/`;
- the attestation job depends on the complete build matrix;
- Linux `.deb` and `.AppImage`, Windows `.msi` and NSIS `.exe`, and macOS `.dmg` bundles are present exactly once in their expected bundle paths;
- all six platform-specific operational CLIs and all six corresponding `.sha256` files are each present exactly once;
- the preserved release tree contains exactly 17 regular files and no symlink, device, socket, FIFO, or other non-regular entry, so unreviewed debug output, logs, dumps, or unrelated executables cannot become attested release subjects;
- every checksum file contains exactly one SHA-256 record naming its adjacent expected CLI basename, so alternate, absolute, traversing, or decoy filenames are rejected before digest verification;
- each checksum is verified before provenance generation;
- `actions/download-artifact` is immutably pinned to commit `37930b1c2abaa49bbe596cd826c3c89aef350131`, the upstream `v7.0.0` tag commit;
- `actions/attest` is immutably pinned to commit `59d89421af93a897026c735860bf21b6eb4f7b26`, the upstream `v4.1.0` tag commit;
- every published file is a subject of the generated attestation; and
- publication depends on successful attestation rather than merely running in parallel with it.

GitHub's action emits an in-toto Statement v1 containing a SLSA Provenance v1 predicate. SLSA specification version 1.2 is the current approved framework version, while the stable build-provenance predicate URI remains `https://slsa.dev/provenance/v1`.

## Buyer and operator verification

Download one release artifact without renaming or modifying it, install a current GitHub CLI, authenticate if the repository visibility requires it, and run:

```bash
gh attestation verify PATH/TO/ARTIFACT -R ContextualWisdomLab/disksage
```

The verifier must bind the artifact digest to `ContextualWisdomLab/disksage`. A successful result demonstrates that GitHub Actions produced an attestation for those exact bytes; it does not independently prove that the software is defect-free, that every dependency is trustworthy, or that the build platform satisfies a claimed SLSA level. Those are separate review and assurance questions.

For offline evidence collection, download the attestation bundle while network access is available:

```bash
gh attestation download PATH/TO/ARTIFACT -R ContextualWisdomLab/disksage
```

Retain the artifact, the downloaded bundle, the release tag, the source commit SHA, and the successful release workflow URL together. Do not substitute an attestation for a differently named or older artifact, even when the version string appears identical.

## Failure and stale-evidence behavior

The pipeline fails closed when an expected platform bundle, operational CLI, or checksum file is absent or duplicated. Artifact namespaces remain separate during download, so the same required filename contributed by two platform archives remains two filesystem entries and is rejected rather than silently overwritten. It validates checksum-record semantics and digests first so an invalid or redirected record receives the specific actionable diagnostic, then rejects any eighteenth regular file and every non-regular filesystem entry before attestation or publication. This exact-set rule prevents a build step from silently adding an unreviewed diagnostic archive, crash dump, log, secret-bearing output, or unrelated executable to the release. Path-scoped checks distinguish the Windows NSIS installer from the two separately shipped Windows operational CLI executables. The pipeline also fails when a checksum record names a file other than its adjacent operational CLI, contains additional fields or records, or presents a malformed digest. A checksum mismatch stops the attestation job. A failed, cancelled, skipped, neutral, missing, or stale-head attestation job cannot satisfy the publication dependency.

Concurrency cancellation applies only to a first workflow attempt. A newer first attempt may cancel stale work for the same ref, but an explicit rerun has `github.run_attempt > 1` and therefore cannot cancel itself. A rerun remains non-authoritative until every required exact-head job in that attempt completes successfully.

Attestations bind artifact digests, not mutable filenames. Rebuilding the same version produces different bytes and therefore requires new exact-build attestations. Evidence from an earlier workflow run or commit must never authorize publication of a later head.

## Privacy and security boundaries

The attestation describes build provenance and artifact digests. It must not include API keys, user data, local disk inventory, file paths from an operator workstation, model prompts, cleanup plans, or dynamic command output containing private host information. GitHub Secrets remain unavailable to pull-request-controlled release tests unless a separately reviewed workflow explicitly requires them. The exact 17-file allowlist is also a privacy boundary: unexpected diagnostics and transient build outputs are rejected rather than made durable through an attestation or GitHub Release.

All third-party actions in the release path use immutable 40-character commit SHAs. The attestation job receives no `contents: write` permission, and the publication job receives neither `id-token: write` nor `attestations: write`. This separation limits the impact of a compromised publication or attestation step.

## Rollback and migration

Rollback is a workflow-source revert, not deletion or reuse of old attestations:

1. revert the provenance workflow commit through an independently reviewed pull request;
2. rerun all exact-current-head test, security, packaging, and release-acceptance checks;
3. do not publish a replacement tag until the approved workflow state is on the protected branch; and
4. document why provenance was removed or changed in `CHANGELOG.md` and the release notes.

Already published attestations remain historical evidence for their original artifact digests. They must not be presented as evidence for replacement binaries. If a release artifact is withdrawn, mark the GitHub Release accordingly and publish a new version with new provenance rather than silently replacing assets under the same tag.

## MSA compatibility

Provenance is attached at the DiskSage release boundary and does not require `naruon`, `contextual-orchestrator`, or organization-central services at runtime. CWL services may consume the same verification contract as a module integration gate: verify the artifact against `ContextualWisdomLab/disksage`, bind the verified digest in deployment metadata, and preserve that digest across promotion and rollback.

## APA 7th references

GitHub. (n.d.). *Using artifact attestations to establish provenance for builds*. GitHub Docs. Retrieved August 6, 2026, from https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/use-artifact-attestations

GitHub. (n.d.). *Verifying attestations offline*. GitHub Docs. Retrieved August 6, 2026, from https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations/verify-attestations-offline

in-toto Project. (n.d.). *in-toto attestation framework specification (Version 1.2)*. GitHub. Retrieved August 6, 2026, from https://github.com/in-toto/attestation/blob/v1.2.0/spec/README.md

Supply-chain Levels for Software Artifacts. (n.d.). *SLSA specification (Version 1.2)*. The Linux Foundation. Retrieved August 6, 2026, from https://slsa.dev/spec/v1.2/

Supply-chain Levels for Software Artifacts. (n.d.). *Build: Verifying artifacts (Version 1.2)*. The Linux Foundation. Retrieved August 6, 2026, from https://slsa.dev/spec/v1.2/verifying-artifacts

## Reference verification note

The sources above were rechecked against their authoritative upstream locations on August 6, 2026. GitHub documentation was used for the supported action permissions and verification commands; upstream tag comparisons established the immutable action commits; the SLSA and in-toto specifications were used for provenance semantics and attestation structure. This document makes no unsupported claim that the workflow alone certifies a particular SLSA level.
50 changes: 50 additions & 0 deletions docs/doctoring/release-version-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Release version contract

## Decision

DiskSage fails closed before packaging when its buyer-visible release versions are not identical. `package.json`, `src-tauri/Cargo.toml`, and `src-tauri/tauri.conf.json` must each expose one identical Semantic Versioning value. A tag-triggered release must additionally use the exact tag `v<manifest version>`.

The authoritative executable policy is `scripts/ci/release-version.mjs`. The package `build` command runs that policy before coverage and Vite compilation. Tauri executes `npm run build` through `beforeBuildCommand`, so the same check precedes Linux, Windows, and macOS bundle creation without relying on one operating system's shell syntax.

## Evidence contract

The verifier:

- reads each JSON manifest as UTF-8 and requires one non-empty string `version`;
- reads exactly one literal `version = "..."` from Cargo's `[package]` section and refuses absent, duplicated, or workspace-inherited ambiguity;
- requires all three values to be identical;
- requires the shared value to satisfy Semantic Versioning 2.0.0, including rejection of leading zeroes in numeric prerelease identifiers such as `1.0.0-01` and `1.0.0-alpha.01`;
- treats branch and pull-request builds as version-consistency checks without inventing a release tag;
- when `GITHUB_REF` is a tag reference, requires `GITHUB_REF_NAME` to equal `v<manifest version>` exactly;
- emits stable privacy-safe diagnostics containing only repository-controlled version values; and
- runs under the ordinary read-only build authority before compilation, attestation, or publication authority exists.

`src/lib/releaseVersionContract.test.ts` verifies valid releases, prerelease/build metadata, Cargo section parsing, invalid JSON, missing and empty versions, duplicate Cargo versions, each manifest-disagreement path, malformed Semantic Versioning including numeric prerelease leading zeroes, tag drift, repository-root loading, and stable CLI success and failure behavior. `vitest.config.ts` includes the production verifier in the 100% statement, branch, function, and line coverage gate.

## Failure and stale-evidence behavior

A mismatch terminates `npm run build`; therefore Tauri cannot create a bundle and downstream provenance or publication jobs cannot receive release artifacts. A successful check from another commit, branch, tag, or workflow attempt is not reusable. Any manifest edit changes the exact current head and requires the complete Test, Release, security, review, approval, packaging, provenance, and release-acceptance gates to run again.

The contract does not bump versions automatically. Version changes remain explicit reviewed source changes across all three manifests and `CHANGELOG.md`. Release automation must never rewrite a tag or manifest to make a mismatch pass.

## Rollback and migration

Rollback requires an independently reviewed source revert. After a revert, run the exact-current-head coverage and packaging gates and confirm that all three manifests still agree. Do not reuse or replace assets under an existing tag; publish a new version with new provenance when replacement binaries are necessary.

## MSA compatibility

The verifier is standalone and requires no Naruon, contextual-orchestrator, model API, user data, or network access. CWL services that embed DiskSage may invoke the same package build contract or independently compare the three version sources and the deployment artifact digest before promotion.

## APA 7th references

npm, Inc. (n.d.). *Creating a package.json file*. npm Docs. Retrieved August 6, 2026, from https://docs.npmjs.com/creating-a-package-json-file/

Rust Project. (n.d.). *The manifest format*. The Cargo Book. Retrieved August 6, 2026, from https://doc.rust-lang.org/cargo/reference/manifest.html

Semantic Versioning. (n.d.). *Semantic Versioning 2.0.0*. Retrieved August 6, 2026, from https://semver.org/spec/v2.0.0.html

Tauri Programme within The Commons Conservancy. (n.d.). *Distribute*. Tauri. Retrieved August 6, 2026, from https://v2.tauri.app/distribute/

## Reference verification note

The authoritative publisher sources above were rechecked on August 6, 2026. They support the manifest locations, package version semantics, including the prohibition on leading zeroes in numeric prerelease identifiers, and distribution boundary used by this contract; they do not imply external certification of DiskSage.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "npm run coverage && vite build",
"verify:release-version": "node --input-type=module --eval \"import('./scripts/ci/release-version.mjs').then(({ main }) => main())\"",
"build": "npm run verify:release-version && npm run coverage && vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
Expand Down
Loading