From 7c8a98a1cfeca98bfc9b684024f7316b47072539 Mon Sep 17 00:00:00 2001 From: Mix Date: Tue, 22 Sep 2026 13:22:22 +0300 Subject: [PATCH] Version cut 1.9.2: close the code review pass, bump the pin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 2026-08-19 full-tree code review's fixes were sitting in Unreleased alongside in-progress, docs-only panel-redesign prep. Per development.md § Roadmap track, docs-only prep gets no version cut until its product stage ships, so the review-pass entries (all real code/behaviour fixes, plus migration 0010, the DMARC-zip and port-25 e2e additions) move to a new [1.9.2] section; the panel-redesign and preflight roadmap items stay in a fresh Unreleased. Also drops two duplicate CHANGELOG bullets (bcrypt cost, rate-limiter eviction) that restated an earlier entry verbatim, and updates every 1.9.1 pin reference (docker-compose image, README quickstart, guide.md, development.md's planned-cuts table, schema-migrations.md's migration-0010 row, roadmap.md's review-closure links) to 1.9.2. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 42 +++++++++++++++++++-------------------- README.md | 2 +- deploy/docker-compose.yml | 2 +- docs/development.md | 5 +++-- docs/guide.md | 2 +- docs/roadmap.md | 4 ++-- docs/schema-migrations.md | 6 +++--- 7 files changed, 32 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a33c1c..affa1be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,22 +5,6 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version ## [Unreleased] -Review pass over `1.4.0`…`1.9.1`: port 25 no longer shares the submission -milter chain, DMARC reports are validated before they are stored, and the auto -rate limit is correct for a non-default level-1 window. Schema migration -`0010` (index only). Upgrading is a tag bump. - -A full-tree code review on 2026-08-19 (architecture, code quality, security, -GUI, tests, documentation, AGPL compliance; 38 findings) produced most of what -follows. Its four open items live in [roadmap.md](docs/roadmap.md); its working -document is not part of the release. - -### Changed - -- README hero line and a **Positioning** block in `docs/product.md` record the - tagline (`YOUR SMTP. YOUR RULES.`) and hero copy; the stamp subtitle stays - `SELF-HOSTED SMTP RELAY`. `docs/assets/selfpost-proof.html` updated to match. - ### Added - Panel redesign, account e-mail and notifications: a user's e-mail is its own @@ -155,6 +139,21 @@ document is not part of the release. ([docs/plans/preflight.md](docs/plans/preflight.md)) — instance-level infrastructure verification (rDNS, TLS, ports, HELO banner, proxy headers, DKIM socket, test email). Status: candidate. + +## [1.9.2] - 2026-09-22 + +Review pass over `1.4.0`…`1.9.1`: port 25 no longer shares the submission +milter chain, DMARC reports are validated before they are stored, and the auto +rate limit is correct for a non-default level-1 window. Schema migration +`0010` (index only). Upgrading is a tag bump. + +A full-tree code review on 2026-08-19 (architecture, code quality, security, +GUI, tests, documentation, AGPL compliance; 38 findings) produced most of what +follows. Its four open items live in [roadmap.md](docs/roadmap.md); its working +document is not part of the release. + +### Added + - SQLite migration `0010_send_log_app_login_index.sql` — `idx_send_log_app_login_created_at`. The journal-milter counts an application's messages on every `MAIL FROM`, and the domain page computes @@ -170,6 +169,12 @@ document is not part of the release. survived three releases because the suite only ever exercised the flags-off path. +### Changed + +- README hero line and a **Positioning** block in `docs/product.md` record the + tagline (`YOUR SMTP. YOUR RULES.`) and hero copy; the stamp subtitle stays + `SELF-HOSTED SMTP RELAY`. `docs/assets/selfpost-proof.html` updated to match. + ### Fixed - The setup account's password is hashed at bcrypt cost `12` like every other @@ -199,17 +204,12 @@ document is not part of the release. guard; one check now returns a context-specific message for self-demotion. - Settings flash text now reflects what actually changed and only mentions session sign-out when the password changed. -- Login/setup rate-limiter bucket eviction now prefers the nearest-expiry bucket - and does not evict currently blocked buckets. - Help page/drawer links now use `SourceURL` (`{{.SourceURL}}/blob/main/docs/...`) instead of a hardcoded repository URL. - Help drawer close controls include accessibility attributes (`role="button"`, `aria-label`) for the scrim and close action. -- Password hashing now uses explicit bcrypt cost `12` in settings/user password - updates, instead of `bcrypt.DefaultCost`. - Test coverage expanded for DMARC map token injection rejection and email validation edge cases (ASCII/local-part/domain/freemail cases). - - **Port 25 no longer runs the submission milter chain.** `smtpd_milters` is now always overridden on `smtp/inet` — to the optional antispam milter, or to nothing. Previously, with `INBOUND_ANTISPAM_MILTER` unset, inbound mail diff --git a/README.md b/README.md index 97a2ec8..c6cd0fa 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ docker run --rm -d --name selfpost-try \ -e SELFPOST_HOSTNAME=mail.local.test \ -e PANEL_COOKIE_SECURE=false \ -v selfpost-try-data:/data \ - ghcr.io/mixeme/selfpost:1.9.1 + ghcr.io/mixeme/selfpost:1.9.2 ``` **Get the setup URL** (pick one): diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 6dbb4f2..70fea17 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -21,7 +21,7 @@ services: selfpost: - image: ghcr.io/mixeme/selfpost:1.9.1 + image: ghcr.io/mixeme/selfpost:1.9.2 restart: unless-stopped environment: SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}" diff --git a/docs/development.md b/docs/development.md index 867affe..33cfc1b 100644 --- a/docs/development.md +++ b/docs/development.md @@ -107,7 +107,7 @@ than the default «meaningful step» rule in [§ Commits and release build](#com 2. Git tag `vX.Y.Z` and publish the GitHub Release only on explicit request (see [§ Release image](#release-image)). -**Planned version cuts** (from pin `1.9.1`; adjust if semver changes mid-track): +**Planned version cuts** (from pin `1.9.2`; adjust if semver changes mid-track): | Stage | ID | Cut | |---|---|---| @@ -119,7 +119,8 @@ than the default «meaningful step» rule in [§ Commits and release build](#com | 6 | panel-docs | `1.8.0` | | 7 | application auth IPs | `1.9.0` | | 8 | port-25 Postfix startup fix | `1.9.1` (PATCH) | -| 9 | inbound-antispam-panel | `1.10.0` (planned) | +| 9 | 2026-08-19 code review pass | `1.9.2` (PATCH) | +| 10 | inbound-antispam-panel | `1.10.0` (planned) | Docs-only prep (checklists in plans, no product code) uses the same per-step commit rule but **no** version cut until the next product stage ships. diff --git a/docs/guide.md b/docs/guide.md index d4d2b20..bd5366b 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -173,7 +173,7 @@ cat ./data/setup-token #### Fixed image tag `deploy/docker-compose.yml` pins an explicit version (`ghcr.io/mixeme/selfpost:X.Y.Z`), -deliberately never `:latest`. The current pin is `1.9.1`. Intermediate +deliberately never `:latest`. The current pin is `1.9.2`. Intermediate CHANGELOG sections (`0.2.0`…`0.6.0`) record development cuts from before that image was published. Pinning matters because of the backup version check (see [Full backup and restore](#full-backup-and-restore)): the panel binary's diff --git a/docs/roadmap.md b/docs/roadmap.md index 8ecc82a..3f155dd 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -54,7 +54,7 @@ listed above and none of them urgent: [csrf-tokens](#csrf-tokens), [template-data-typing](#template-data-typing), [structured-logging](#structured-logging) and [review-2026-08-followups](#review-2026-08-followups). What that review -produced is in [CHANGELOG.md](../CHANGELOG.md) `[Unreleased]`; its own document +produced is in [CHANGELOG.md](../CHANGELOG.md) `[1.9.2]`; its own document was removed once these four items carried everything still open, and stays in git history. @@ -262,7 +262,7 @@ estimate: 3–4 hours. **Goal:** the leftovers of the 2026-08-19 full-tree code review that are too small to be roadmap items of their own. Everything still open from that review is in the table below; the rest of it shipped in -[CHANGELOG.md](../CHANGELOG.md) `[Unreleased]`. +[CHANGELOG.md](../CHANGELOG.md) `[1.9.2]`. | Area | Item | |---|---| diff --git a/docs/schema-migrations.md b/docs/schema-migrations.md index 7b4fe05..d96ad00 100644 --- a/docs/schema-migrations.md +++ b/docs/schema-migrations.md @@ -23,9 +23,9 @@ Documentation. | Database file | `/data/selfpost.db` (bind mount) | | Compatibility | 1.x MINOR releases must boot a `1.0.0` data directory | -Last updated in **[Unreleased]** (`0010_send_log_app_login_index`); **1.9.1** +Last updated in **[1.9.2]** (`0010_send_log_app_login_index`); **1.9.1** had no schema change. The release column below records the cut a migration -shipped in — fill `0010`'s in at the next version cut. +shipped in. --- @@ -65,7 +65,7 @@ replace the embedded set (see [Planned 2.x squash](#planned-2x-squash)). | 7 | `0007_rate_limit_auto.sql` | 1.6.0 | DDL | `rate_limits.mode`, `auto_multiplier`, `auto_updated_at` | | 8 | `0008_dmarc_reports.sql` | 1.7.0 | DDL | `dmarc_reports`, `dmarc_report_records` | | 9 | `0009_application_auth_ips.sql` | 1.9.0 | DDL + data | `applications.auth_ip_restrict`, `auth_allowed_ips`; move legacy app `rate_limits.allowed_ips` into auth columns; clear those IPs on rate limits | -| 10 | `0010_send_log_app_login_index.sql` | Unreleased | DDL | `idx_send_log_app_login_created_at` — app-scoped rate-limit counts and per-application send statistics were scanning the `created_at` range | +| 10 | `0010_send_log_app_login_index.sql` | 1.9.2 | DDL | `idx_send_log_app_login_created_at` — app-scoped rate-limit counts and per-application send statistics were scanning the `created_at` range | **Kind:** *DDL* — schema only; *data* — `INSERT`/`UPDATE` that must stay correct for operators upgrading from older 1.x images.