51e20ffc22
The plan is meant to hold only what is still open, but three of its numbered items had already been implemented and were still being read as pending work: the TRUSTED_PROXY_CIDR-gated X-Forwarded-For handling (A.1), the account settings page (A.6) and the go vet/go test CI workflow (C.10). Remove them and renumber; the residual scope note from A.6 (2FA, multiple admins) moves to section D, which is where deliberately deferred scope belongs. Same for the "done" notices at the top of the plan and the phase-by-phase retellings in progress.md: phases 12 and 13 are described in full in the CHANGELOG and git history, so the tracker now states what is closed and what is next, and nothing else. Three code comments cited plan item numbers that this renumbering would have silently pointed at a different item, and one cited a phase 13 section that no longer exists; they now state the fact instead of the reference. The CI test workflow was never recorded in the CHANGELOG, so its entry is added there before the plan item describing it goes away. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
85 lines
5.1 KiB
Markdown
85 lines
5.1 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to this project are documented here.
|
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [SemVer](https://semver.org/).
|
|
|
|
## [Unreleased]
|
|
|
|
- panel: new **Status** page — supervised processes, mail queue, TLS
|
|
certificate expiry, milter sockets and the server's own hostname/reverse-DNS
|
|
(FCrDNS) check — and it is now the panel's landing page. The local checks
|
|
refresh by polling; the DNS lookup is cached with a *Re-check* button.
|
|
- panel: the domain page shows a **DNS status** card: the published DKIM record
|
|
compared against the key this server actually signs with, plus SPF and DMARC.
|
|
The SPF check is deliberately shallow — it looks for a mechanism literally
|
|
covering this server's address and does not follow `include:`/`redirect=`, so
|
|
a record that authorises the server through an include is reported as "cannot
|
|
tell", not as a failure.
|
|
- panel: the domain list moved from `/` to `/domains`; `/` redirects to the
|
|
status page. The **Reload** button moved from the domain list to the status
|
|
page and now explains what it regenerates and when to use it.
|
|
- fix: the panel could never read the mail queue in the documented deployment.
|
|
`postqueue` relies on its setgid-`postdrop` bit, which `no-new-privileges`
|
|
(set in the shipped compose file) disables, so the *Queue* screen always said
|
|
"Could not read the mail queue". The `panel` user is now a real member of
|
|
`postdrop`.
|
|
- panel: navigation bar is now rendered once from the shared layout, so every
|
|
authenticated page has it — including the domain page and the delete
|
|
confirmation, which had no navigation links at all — and the current page is
|
|
highlighted instead of silently missing from the list.
|
|
- panel: new *Account* page to change the administrator's username and/or
|
|
password (the current password is required, throttled on the same limiter as
|
|
the login form). Changing the password invalidates all other sessions.
|
|
- panel: *Backup & migration* moved off the domain list onto its own *Backup*
|
|
page, with the full backup and the domain import as two separate cards.
|
|
- panel: the domain page now shows the *Sending server settings* (server,
|
|
port and encryption) needed to configure a mail client; port 587 is listed
|
|
only when `SUBMISSION_ENABLE=true` for this deployment.
|
|
- panel: *Copy* buttons on the DKIM record, on a newly issued application
|
|
login/password and on the sending server name.
|
|
- panel: the *Addresses* field is hidden while an application's address mode is
|
|
*Any address of the domain*, where the server ignores it.
|
|
- ci: disable provenance attestation on release image push, so the ghcr.io
|
|
manifest list shows only `linux/amd64`/`linux/arm64` (no `unknown/unknown`).
|
|
- ci: run `go vet` and `go test ./...` on every push to `main` and every pull
|
|
request, not only the image build on a release tag.
|
|
- security: optionally honour `X-Forwarded-For` for login/setup rate-limiting
|
|
when the request's direct peer is in the new `TRUSTED_PROXY_CIDR` list,
|
|
giving real per-client limits behind a reverse proxy instead of one global
|
|
bucket. Unset by default (unchanged `RemoteAddr`-only behaviour).
|
|
|
|
## [0.1.0] - 2026-07-15
|
|
|
|
Initial feature-complete implementation of the v1.0 specification (phases 0-11
|
|
of `docs/implementation-plan.md`).
|
|
|
|
### Added
|
|
|
|
- Panel (Go, single static binary) with SQLite persistence, one-time
|
|
crypto-random setup link, bcrypt admin auth, session cookies.
|
|
- Domain management with per-domain DKIM (RSA-2048, generated in pure Go) and
|
|
OpenDKIM KeyTable/SigningTable regeneration + privilege-safe reload.
|
|
- Application (sender identity) management: SASL credentials via `sasldb2`,
|
|
`smtpd_sender_login_maps` enforcing sender/domain ownership, no open relay.
|
|
- Full Postfix relay config generated from env at container start: SMTPS 465,
|
|
optional STARTTLS submission 587, SASL auth, TLS for outbound delivery,
|
|
anvil-based rate limiting (level 1).
|
|
- Journal milter (pure Go, `go-milter`) recording every send to `send_log`;
|
|
fail-open by design so a milter fault never blocks mail.
|
|
- Monitoring UI: send log, Postfix queue, and mail.log tail, all
|
|
HTMX-polling, HTML-escaped.
|
|
- Per-domain/per-application sending rate limit (level 2), enforced in the
|
|
journal milter at `MAIL FROM`, fail-open on the limiter's own errors.
|
|
- Full backup/restore (`tar.gz` of `/data`, consistent SQLite snapshot via
|
|
`VACUUM INTO`) with a version guard that refuses to start on a
|
|
manifest/binary version mismatch. Per-domain export/import for moving a
|
|
single domain between hosts without re-issuing DNS records.
|
|
- Deployment: Docker image + compose, reverse-proxy fragments for Apache
|
|
(default), nginx, Caddy, and Traefik; CI workflow publishing tagged,
|
|
multi-arch images to `ghcr.io` on `vX.Y.Z` tags.
|
|
- Security pass against spec 7.6 (exec safety, config-write sanitization,
|
|
server-side validation, rate limiting, session/cookie hardening, output
|
|
escaping, non-root panel) — full compliance, no code changes required.
|
|
- Live production deployment on `selfpost.example.com` with a real Let's
|
|
Encrypt certificate; end-to-end delivery confirmed (DKIM pass, SPF pass).
|