diff --git a/CHANGELOG.md b/CHANGELOG.md index d09bdcb..1f62a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +Nothing yet. + +## [0.2.0] - 2026-07-05 + ### Security - Refreshed `Cargo.lock` to patch 10 RUSTSEC advisories in transitive @@ -44,6 +48,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CI now fails on `cargo deny check advisories licenses` (previously licenses-only and non-blocking); weekly stress tests pin `apache/iggy:0.8.0` instead of `latest` +- Crate marked `publish = false`: releases are repo-level only (GitHub + Releases + GitHub Pages docs) - cargo itself refuses to publish, so + the release pipeline's publish step is a harmless no-op - Updated `docker-compose.yaml` with full observability stack configuration - Simplified documentation section in README.md to reference `docs/` directory @@ -125,5 +132,6 @@ triggers (`docs/tech-debt/`): - Trusted proxy configuration for X-Forwarded-For validation - Input validation to prevent injection attacks -[Unreleased]: https://github.com/mlevkov/iggy_sample/compare/v0.1.0...HEAD +[Unreleased]: https://github.com/mlevkov/iggy_sample/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/mlevkov/iggy_sample/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/mlevkov/iggy_sample/releases/tag/v0.1.0 diff --git a/CLAUDE.md b/CLAUDE.md index 83193af..350e65e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -793,7 +793,7 @@ Triggered on version tags (`v*.*.*`): - Multi-platform builds (Linux x86/ARM, macOS x86/ARM, Windows) - GitHub Release with changelog - Documentation deployment to GitHub Pages -- Optional crates.io publishing +- No crates.io publishing: the crate is `publish = false` (repo-level releases only) ### Extended Tests (`extended-tests.yml`) Weekly scheduled runs: diff --git a/Cargo.lock b/Cargo.lock index 9edbd90..3a7b865 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2283,7 +2283,7 @@ dependencies = [ [[package]] name = "iggy_sample" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml index 8301531..f04911e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,16 @@ [package] name = "iggy_sample" -version = "0.1.0" +version = "0.2.0" edition = "2024" rust-version = "1.93.0" description = "A comprehensive demonstration of Apache Iggy message streaming with Axum" license = "MIT" +# Repo-level releases only - never published to crates.io (enforced here, +# not just in CI: cargo refuses to publish with this set) +publish = false repository = "https://github.com/mlevkov/iggy_sample" homepage = "https://github.com/mlevkov/iggy_sample" -documentation = "https://docs.rs/iggy_sample" +documentation = "https://mlevkov.github.io/iggy_sample" authors = ["Maxim Levkov"] keywords = ["iggy", "message-streaming", "axum", "async", "event-driven"] categories = ["web-programming", "asynchronous", "network-programming"] diff --git a/README.md b/README.md index 3347a24..84ae578 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Iggy Sample Application [![CI](https://github.com/mlevkov/iggy_sample/actions/workflows/ci.yml/badge.svg)](https://github.com/mlevkov/iggy_sample/actions/workflows/ci.yml) +[![Release](https://img.shields.io/github/v/release/mlevkov/iggy_sample?sort=semver)](https://github.com/mlevkov/iggy_sample/releases/latest) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Rust](https://img.shields.io/badge/rust-1.93%2B-blue.svg)](https://www.rust-lang.org) @@ -123,7 +124,7 @@ Expected response: { "status": "healthy", "iggy_connected": true, - "version": "0.1.0", + "version": "0.2.0", "timestamp": "2024-01-15T10:30:00Z" } ``` diff --git a/docs/tech-debt/README.md b/docs/tech-debt/README.md index 751ea0e..b74b450 100644 --- a/docs/tech-debt/README.md +++ b/docs/tech-debt/README.md @@ -11,3 +11,4 @@ condition under which the record MUST be resolved (not "someday"). | [TD-2026-07-04](TD-2026-07-04.md) | X-Request-Timeout enforcement | Review session 01 (silentfail M4) | Before advertising the header in any client-facing docs beyond CLAUDE.md | | [TD-2026-07-05](TD-2026-07-05.md) | Metrics exporter smoke test | Review session 01 (tests #7) | Next metrics-exporter-prometheus major/minor bump | | [TD-2026-07-06](TD-2026-07-06.md) | Durable-storage guide config re-validation | Review session 01 (consistency #10) | Next server image bump past 0.8.x | +| [TD-2026-07-07](TD-2026-07-07.md) | Pin third-party GitHub Actions to commit SHAs | Security review on v0.2.0 release PR | Next CI-focused change, or any new repo secret | diff --git a/docs/tech-debt/TD-2026-07-07.md b/docs/tech-debt/TD-2026-07-07.md new file mode 100644 index 0000000..8db3804 --- /dev/null +++ b/docs/tech-debt/TD-2026-07-07.md @@ -0,0 +1,28 @@ +# TD-2026-07-07: Pin third-party GitHub Actions to commit SHAs + +**Source:** automated security review on the v0.2.0 release PR (MEDIUM). +**Status:** open + +## Problem + +All four workflows reference third-party actions by mutable tag +(`dtolnay/rust-toolchain@stable`, `Swatinem/rust-cache@v2`, +`taiki-e/install-action@...`, `codecov/codecov-action@v4`, etc.). A +compromised or force-moved tag executes attacker-controlled code in CI with +access to the workflow's permissions and any secrets passed to that job +(supply-chain risk of the tj-actions/changed-files class). + +## Mitigations in place + +- The crate is `publish = false`, so `CRATES_IO_TOKEN` (if ever configured) + cannot result in a publish — cargo refuses before the token is used. +- Workflow permissions are narrowly scoped per job where elevated. + +## Binding trigger + +At the next CI-focused change (or if any secret beyond `GITHUB_TOKEN` is +added to the repo), pin every third-party action across all workflows to a +full 40-char commit SHA with a version comment +(`uses: owner/action@ # vX`), and enable Dependabot's +`github-actions` ecosystem updates to keep the pins fresh (already +configured for version updates — verify it bumps SHA pins too).