Files
selfpost/CHANGELOG.md
T
mix fc53ae1314 panel: shared nav, account settings, backup page, connection settings
Phase 12 (UI/UX). The navigation bar now renders once from layout.html
instead of being copied into each content template, so it is present on
every authenticated page — including the domain page and its delete
confirmation, which had no links at all — and the current page is
highlighted via .Active rather than quietly dropping out of the list.

New /account page changes the administrator's username and/or password:
the current password is required and the attempt is throttled on the same
limiter as the login form, so this route cannot be used to brute-force
past that limit. A password change invalidates every other session while
keeping the one performing it; a rename carries that session over.

Backup and domain import move from a card in the middle of the domain
list to their own /backup page, one card each; the handlers themselves
are unchanged, only the page the import form renders its errors on.

The domain page gains a "Sending server settings" card (server, port,
encryption) so a client can be configured without reading the docs; 587
is listed only when SUBMISSION_ENABLE is true for this deployment, which
is a deploy-time flag the panel cannot verify at runtime.

Client-side (static/panel.js, no libraries): Copy buttons on the values
that get carried elsewhere (DKIM record, new application credentials,
server name), and the Addresses field is hidden while the address mode is
wildcard, where the server ignores it.

Verified in a container on the dev server: setup, login, every page's
nav and active item, domain and application creation, all account-form
paths including cross-session invalidation, import errors, full backup
download. gofmt/vet/test/docker build green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 21:34:59 +03:00

65 lines
3.7 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: 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`).
- 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).