Compare commits
2
Commits
d83d326217
...
1ee509dcab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ee509dcab | ||
|
|
7c8a98a1cf |
+27
-19
@@ -5,21 +5,13 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); version
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
Review pass over `1.4.0`…`1.9.1`: port 25 no longer shares the submission
|
## [1.9.3] - 2026-09-22
|
||||||
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,
|
Panel-redesign prep, docs only: stage 1-2 mockups on all 33 screens, the
|
||||||
GUI, tests, documentation, AGPL compliance; 38 findings) produced most of what
|
accepted header/type-scale/contrast corrections, the account e-mail and
|
||||||
follows. Its four open items live in [roadmap.md](docs/roadmap.md); its working
|
inbound-delegation decisions, and the routes/quarantine/preflight roadmap
|
||||||
document is not part of the release.
|
screens. Nothing in `internal/web` changes; the design stays `candidate`
|
||||||
|
(3/21) until the redesign itself ships as `2.0.0`.
|
||||||
### 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
|
### Added
|
||||||
|
|
||||||
@@ -155,6 +147,21 @@ document is not part of the release.
|
|||||||
([docs/plans/preflight.md](docs/plans/preflight.md)) — instance-level
|
([docs/plans/preflight.md](docs/plans/preflight.md)) — instance-level
|
||||||
infrastructure verification (rDNS, TLS, ports, HELO banner, proxy headers,
|
infrastructure verification (rDNS, TLS, ports, HELO banner, proxy headers,
|
||||||
DKIM socket, test email). Status: candidate.
|
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` —
|
- SQLite migration `0010_send_log_app_login_index.sql` —
|
||||||
`idx_send_log_app_login_created_at`. The journal-milter counts an
|
`idx_send_log_app_login_created_at`. The journal-milter counts an
|
||||||
application's messages on every `MAIL FROM`, and the domain page computes
|
application's messages on every `MAIL FROM`, and the domain page computes
|
||||||
@@ -170,6 +177,12 @@ document is not part of the release.
|
|||||||
survived three releases because the suite only ever exercised the flags-off
|
survived three releases because the suite only ever exercised the flags-off
|
||||||
path.
|
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
|
### Fixed
|
||||||
|
|
||||||
- The setup account's password is hashed at bcrypt cost `12` like every other
|
- The setup account's password is hashed at bcrypt cost `12` like every other
|
||||||
@@ -199,17 +212,12 @@ document is not part of the release.
|
|||||||
guard; one check now returns a context-specific message for self-demotion.
|
guard; one check now returns a context-specific message for self-demotion.
|
||||||
- Settings flash text now reflects what actually changed and only mentions
|
- Settings flash text now reflects what actually changed and only mentions
|
||||||
session sign-out when the password changed.
|
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/...`)
|
- Help page/drawer links now use `SourceURL` (`{{.SourceURL}}/blob/main/docs/...`)
|
||||||
instead of a hardcoded repository URL.
|
instead of a hardcoded repository URL.
|
||||||
- Help drawer close controls include accessibility attributes (`role="button"`,
|
- Help drawer close controls include accessibility attributes (`role="button"`,
|
||||||
`aria-label`) for the scrim and close action.
|
`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
|
- Test coverage expanded for DMARC map token injection rejection and email
|
||||||
validation edge cases (ASCII/local-part/domain/freemail cases).
|
validation edge cases (ASCII/local-part/domain/freemail cases).
|
||||||
|
|
||||||
- **Port 25 no longer runs the submission milter chain.** `smtpd_milters` is
|
- **Port 25 no longer runs the submission milter chain.** `smtpd_milters` is
|
||||||
now always overridden on `smtp/inet` — to the optional antispam milter, or
|
now always overridden on `smtp/inet` — to the optional antispam milter, or
|
||||||
to nothing. Previously, with `INBOUND_ANTISPAM_MILTER` unset, inbound mail
|
to nothing. Previously, with `INBOUND_ANTISPAM_MILTER` unset, inbound mail
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ docker run --rm -d --name selfpost-try \
|
|||||||
-e SELFPOST_HOSTNAME=mail.local.test \
|
-e SELFPOST_HOSTNAME=mail.local.test \
|
||||||
-e PANEL_COOKIE_SECURE=false \
|
-e PANEL_COOKIE_SECURE=false \
|
||||||
-v selfpost-try-data:/data \
|
-v selfpost-try-data:/data \
|
||||||
ghcr.io/mixeme/selfpost:1.9.1
|
ghcr.io/mixeme/selfpost:1.9.3
|
||||||
```
|
```
|
||||||
|
|
||||||
**Get the setup URL** (pick one):
|
**Get the setup URL** (pick one):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
selfpost:
|
selfpost:
|
||||||
image: ghcr.io/mixeme/selfpost:1.9.1
|
image: ghcr.io/mixeme/selfpost:1.9.3
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}"
|
SELFPOST_HOSTNAME: "${SELFPOST_HOSTNAME:?set the mail/panel hostname, e.g. mail.example.com}"
|
||||||
|
|||||||
+4
-2
@@ -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
|
2. Git tag `vX.Y.Z` and publish the GitHub Release only on explicit request (see
|
||||||
[§ Release image](#release-image)).
|
[§ 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.3`; adjust if semver changes mid-track):
|
||||||
|
|
||||||
| Stage | ID | Cut |
|
| Stage | ID | Cut |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@@ -119,7 +119,9 @@ than the default «meaningful step» rule in [§ Commits and release build](#com
|
|||||||
| 6 | panel-docs | `1.8.0` |
|
| 6 | panel-docs | `1.8.0` |
|
||||||
| 7 | application auth IPs | `1.9.0` |
|
| 7 | application auth IPs | `1.9.0` |
|
||||||
| 8 | port-25 Postfix startup fix | `1.9.1` (PATCH) |
|
| 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 | panel-redesign prep (docs only, owner-requested cut) | `1.9.3` (PATCH) |
|
||||||
|
| 11 | inbound-antispam-panel | `1.10.0` (planned) |
|
||||||
|
|
||||||
Docs-only prep (checklists in plans, no product code) uses the same per-step
|
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.
|
commit rule but **no** version cut until the next product stage ships.
|
||||||
|
|||||||
+1
-1
@@ -173,7 +173,7 @@ cat ./data/setup-token
|
|||||||
#### Fixed image tag
|
#### Fixed image tag
|
||||||
|
|
||||||
`deploy/docker-compose.yml` pins an explicit version (`ghcr.io/mixeme/selfpost:X.Y.Z`),
|
`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.3`. Intermediate
|
||||||
CHANGELOG sections (`0.2.0`…`0.6.0`) record development cuts from before that
|
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
|
image was published. Pinning matters because of the backup version check (see
|
||||||
[Full backup and restore](#full-backup-and-restore)): the panel binary's
|
[Full backup and restore](#full-backup-and-restore)): the panel binary's
|
||||||
|
|||||||
+2
-2
@@ -54,7 +54,7 @@ listed above and none of them urgent: [csrf-tokens](#csrf-tokens),
|
|||||||
[template-data-typing](#template-data-typing),
|
[template-data-typing](#template-data-typing),
|
||||||
[structured-logging](#structured-logging) and
|
[structured-logging](#structured-logging) and
|
||||||
[review-2026-08-followups](#review-2026-08-followups). What that review
|
[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
|
was removed once these four items carried everything still open, and stays in
|
||||||
git history.
|
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
|
**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
|
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
|
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 |
|
| Area | Item |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ Documentation.
|
|||||||
| Database file | `/data/selfpost.db` (bind mount) |
|
| Database file | `/data/selfpost.db` (bind mount) |
|
||||||
| Compatibility | 1.x MINOR releases must boot a `1.0.0` data directory |
|
| 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
|
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` |
|
| 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` |
|
| 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 |
|
| 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
|
**Kind:** *DDL* — schema only; *data* — `INSERT`/`UPDATE` that must stay correct
|
||||||
for operators upgrading from older 1.x images.
|
for operators upgrading from older 1.x images.
|
||||||
|
|||||||
Reference in New Issue
Block a user