Version cut 1.9.2: close the code review pass, bump the pin

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 <noreply@anthropic.com>
This commit is contained in:
mix
2026-09-22 13:22:22 +03:00
co-authored by Claude Sonnet 5
parent d83d326217
commit 7c8a98a1cf
7 changed files with 32 additions and 31 deletions
+21 -21
View File
@@ -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
+1 -1
View File
@@ -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):
+1 -1
View File
@@ -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}"
+3 -2
View File
@@ -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.
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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 |
|---|---|
+3 -3
View File
@@ -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.