Commit Graph
269 Commits
Author SHA1 Message Date
mixemeandCursor 10f5b4e8e1 docs: remove unused legacy icon.png asset
test / test (push) Canceled after 0s
Drop docs/assets/icon.png — superseded by brand SVGs and favicon.png,
with no references anywhere in the tree.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-27 14:55:14 +03:00
mix 50f1e4b298 docs: adopt YOUR SMTP. YOUR RULES. tagline and hero line
test / test (push) Has been cancelled
Record canonical positioning in product.md and refresh the stamp, README,
and brand proof page now that inbound relay is in scope.

docs: keep SELF-HOSTED SMTP RELAY on the stamp

Revert the mark subtitle; tagline and hero line stay in product.md and README only.
2026-08-22 12:06:29 +03:00
mixandClaude Opus 5 b29f4845ba docs: retire the code-review plan, its content now lives where it belongs
test / test (push) Has been cancelled
The review document was the last place several findings existed, so it could
not just be deleted. Everything still useful moved out first:

- roadmap items csrf-tokens, template-data-typing, structured-logging and
  review-2026-08-followups are now self-contained — each row names the file,
  the symptom and what "done" means, instead of pointing at a paragraph number
  in a plan file.
- security.md's CSRF accepted-risk bullet now names the csrf-tokens item, so
  the two records of that decision cannot drift apart unnoticed; the item says
  the same in the other direction.
- CHANGELOG [Unreleased] records the review itself in its intro rather than as
  an added file: the document was created and removed inside one unreleased
  cycle, so it never was part of a release.
- the declined finding (//go:build linux for the /proc reader) keeps its
  rationale in the roadmap so it is not raised again.

Also repaired three links to inbound-relay.md, deleted back when that feature's
plan was cleaned up: the two inbound plans now point at architecture.md § Mail
path for the as-built behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 00:48:13 +03:00
mixandClaude Opus 5 1e4746e52f docs: track every unimplemented review finding in the roadmap
test / test (push) Has been cancelled
Nothing from the 2026-08-19 code review now lives only in its plan file. Four
new roadmap items, all `candidate`:

- csrf-tokens — §4.4. The review recorded a decision to add per-session tokens
  but never turned it into a task, and security.md still argues the header
  checks suffice. The item says to settle which of the two stands first.
- template-data-typing — §7.1, map[string]any template payloads.
- structured-logging — §7.2 and §5.5, log/slog plus the per-package logf
  aliases.
- review-2026-08-followups — the small remainder: backup re-auth, the missing
  DMARC-service / handler / error-page / corrupted-backup tests, and the nine
  minor findings (§6.1, §6.2, §6.4, §7.4, §8.6, §9.3, §10.3-10.5) that were
  never carried into the phase tables.

§7.3 (build tags for the /proc reader) is deliberately not carried over: it was
declined during the pass, and both documents now say so, so it does not get
re-raised at the next review.

The plan's status table links each open row to its roadmap item, and the
roadmap's recommended-order note points back at the plan. Also unlinked two
CHANGELOG references to plan files deleted after those releases shipped; the
text stays, the dead links do not.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 00:09:43 +03:00
mixandClaude Opus 5 ab2cd885c4 review follow-up: close the gaps left by the phase1-6 pass
test / test (push) Has been cancelled
Verified the tree against docs/plans/code-review-2026-08.md and finished the
tasks that were only partly done, plus two defects the pass introduced.

- bcrypt: the setup account was still hashed at DefaultCost (10). The work
  factor now has one definition, auth.BcryptCost = 12, used everywhere.
- rate limiter: protecting blocked buckets from eviction was unbounded — an
  attacker with many source addresses could grow the map by making each one
  fail its way to blocked. Blocked buckets are now evicted past
  maxBuckets * 4, nearest expiry first, logged once per window. Tests cover
  both halves.
- postqueue: the 5s timeout left the output size unbounded; reads are now
  capped at 4 MiB and report truncation.
- spec references: the ~76 `spec N` citations CHANGELOG [0.5.0] claimed were
  gone are removed from build/, deploy/, the first two migrations and the
  release workflow, with the affected comment paragraphs re-wrapped. Comments
  only; shell/YAML/SQL syntax re-checked.
- schema-migrations.md: schema section was headed v9 with the chain at v10,
  and three links pointed at deleted plan files.
- internal/configsafe: the shared empty/forbidden-character check behind the
  OpenDKIM and Postfix config writers; each writer keeps its own forbidden set.
- dropped the parseDomainRateLimitForm/parseAppRateLimitForm pass-throughs
  left behind by the parser merge (only their own tests still called them).
- plan doc now carries a status table: what shipped, what was already in
  place, what was declined (//go:build linux for the /proc reader) and the
  open CSRF-token question.

Not done, each its own phase: typed template data structs, log/slog, DMARC
service and handler tests, error-page/corrupted-backup tests, backup re-auth.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:03:05 +03:00
4204ee279c phase4-6: harden help/docs links and auth defaults
test / test (push) Has been cancelled
Close remaining low-priority review follow-ups by removing hardcoded help URLs, improving help drawer accessibility, raising explicit bcrypt cost, and adding validation/injection coverage; also bound postqueue reads with a timeout to avoid hangs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 19:15:30 +03:00
mixandCursor 81190a7aad phase1-3: apply review fixes and docs alignment
test / test (push) Has been cancelled
Implement phase 1 and 2 review actions (DMARC UI CSS fixes, bounded DMARC ingest stdin,
rate-limit eviction hardening, settings/user handler cleanup, shared atomic/supervisor helpers)
and phase 3 documentation/changelog updates including roadmap and accepted-risk notes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 19:06:33 +03:00
mixandCursor 5a41d34cac docs: record implementation decisions in code review plan
test / test (push) Has been cancelled
Resolved open questions: fail-open+log for auth IP, add CSRF tokens,
typed template structs, slog migration, rate limiter eviction policy
(nearest-expiry, blocked buckets protected), guide URL as full path.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 17:23:21 +03:00
0aa7318a41 docs: add full codebase review plan
test / test (push) Has been cancelled
38 findings across architecture, code quality, security, GUI, tests, documentation, and AGPL compliance. Prioritised 6-phase implementation plan with model recommendations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 15:33:43 +03:00
mixandClaude Fable 5 1b13487356 docs: record 2026-08-19 security review of the 1.3.0..1.9.1 diff
test / test (push) Has been cancelled
No exploitable findings across inbound relay, DMARC ingestion, auto rate
limiting, auth-IP allow-lists, and the new panel surface. Two deliberate
behaviours the pass examined are now recorded as accepted risks:
unauthenticated DMARC report ingest and fail-open auth-IP enforcement.
This closes the note that the inbound-relay path awaited its own review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 15:32:07 +03:00
mixandCursor fb26f7656a docs: remove plan documents for already-shipped features
test / test (push) Has been cancelled
Plans for domain-stats-auto-ratelimit, dmarc-reports, inbound-relay, panel-docs, queue-retries, and send-log-retention are deleted — all shipped between 1.3.1 and 1.7.0. Only unimplemented plans remain.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 14:58:28 +03:00
mixandCursor d88a8a6cba docs: add preflight installation-check page plan and roadmap entry
test / test (push) Has been cancelled
Captures the design for a /preflight page that verifies instance-level infrastructure (rDNS, TLS, ports, HELO banner, proxy headers, DKIM socket, test email). Status: candidate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 14:57:03 +03:00
mixandClaude Opus 5 aa9a95ce4a fix: e2e port-25 check misparsed wrapped master.cf continuation lines
test / test (push) Has been cancelled
Found running the new checkPort25ConfigCombinations on selfpost.mixfed.ru: it
compared against raw, unnormalized master.cf text. postconf -F "*/*/chroot=n"
(unconditional, runs after our smtp/inet edits) rewraps the whole file using
master.cf's own line-continuation convention, splitting a single -o value
across lines and re-flowing what were separate -o lines into one paragraph.
Valid Postfix syntax -- postfix check passes -- but plain substring matching
against the raw text broke on it.

parseSMTPInetOptions now joins continuation lines into one token stream and
reconstructs each "-o param=value" assignment before comparing, verified
against a real captured stanza in port25_config_check_test.go. Full make e2e
(13 scenarios plus the two new parser unit tests) is green on the server.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 14:40:48 +03:00
mixandClaude Opus 5 23d52bab7c fix: port-25 milter chain, DMARC report validation, auto rate-limit window
test / test (push) Has been cancelled
Review pass over the 1.4.0-1.9.1 work.

Port 25 no longer inherits main.cf's submission milter chain: smtpd_milters
is always overridden on smtp/inet, to the antispam milter or to nothing.
Without that, OpenDKIM (strict, tempfail) gated relayed mail during a signing
outage, and the journal-milter filed inbound mail into the outbound send log
under the sender's domain -- so Deliveries showed other people's mail and a
forged From: consumed that domain's level-2 budget. architecture.md already
described the intended behaviour; the code now matches.

DMARC reports are checked before they are stored: the policy domain must be a
configured sending domain, and must match the +tag of a per-domain hosted
address. The rua address form is predictable, so anyone able to reach it could
file reports under any domain and evict genuine ones through the retention cap.
Zip attachments are now decompressed as well as gzip.

The auto level-2 ceiling is scaled to the level-1 window before the multiplier
is applied; any window other than 3600s shifted the allowance by window/3600.

Migration 0010 indexes send_log(app_login, created_at) -- both the per-MAIL
FROM rate-limit count and the per-application statistics were scanning the
created_at range.

e2e now regenerates the Postfix config in-container for all four port-25 flag
combinations and requires postfix check to pass; the 1.9.1 crash-loop shipped
in 1.4.0 and survived three releases because only the flags-off path was
exercised.

Migration 0009 stays as shipped -- its conversion branch only fires for a
database carrying application-scope allowed_ips from before 1.9.0. The schema
reference notes that the old list was permissive and the new column is
restrictive; the guide documents the allow-list as a sending control on a
fail-open path, not an authentication boundary.

Also: gofmt across cmd/ and internal/, unused duplicate validators dropped from
internal/web/validate, export no longer swallows store errors.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 14:17:39 +03:00
mixandCursor b81a261d01 docs: verify CHANGELOG against full git history since repo creation
test / test (push) Has been cancelled
Correct historical gaps: compose cap_add (CAP_FOWNER/FSETID/KILL) in [0.2.0], nav Backup/Sign-out icons in [0.3.0], Export/Danger layout in [1.2.5], and move GHCR per-arch tag cleanup from [1.3.0] to [1.3.1] where the fix landed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 01:11:31 +03:00
mixandCursor 72126b63af docs: align operator and as-built docs with code after 1.9.1.
test / test (push) Has been cancelled
Port 25, DMARC routes, restore Resync vs reload, image pin, and roadmap
index were stale relative to the running panel and Postfix config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:54:11 +03:00
mixandCursor 4a51db277b release: 1.9.1
test / test (push) Has been cancelled
Fix port-25 Postfix startup when inbound relay, DMARC ingest, or antispam milter are enabled; consolidate schema-migrations and inbound antispam/quarantine roadmap docs in the changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:47:45 +03:00
mixandCursor 6adbb41459 fix: port-25 Postfix config when inbound, DMARC, or antispam are enabled
postconf -P cannot set master.cf -o values with whitespace; patch smtp/inet
directly and route DMARC ingest through a dmarc-ingest symlink.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:43:59 +03:00
mixandCursor 1e4623b6e1 docs: agree inbound antispam panel plan for 1.10.0.
test / test (push) Has been cancelled
Add journal and allow/deny list design, quarantine candidate, roadmap entries, and Composer to Opus to Fable routing note.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:32:03 +03:00
mixandCursor bb26e5022e docs: add schema-migrations reference for SQLite chain and legacy.
test / test (push) Has been cancelled
Centralises migration history, 1.x rules, and the 2.x squash gate so
roadmap and architecture no longer carry a stale v5 snapshot.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 00:12:37 +03:00
mixandCursor b4a9b93cf2 release: 1.9.0
test / test (push) Has been cancelled
Application client IP allow-list restricts which addresses may submit as a SASL login; level-2 rate limits override the domain ceiling per application (higher or lower, capped at L1). Migration 0009, authips form, milter enforcement, export/import, and operator docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 23:51:41 +03:00
mixandCursor a8ded7ecc8 Document all full-backup capture methods in the operator guide.
test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 23:13:26 +03:00
mixandCursor 33ee08f7b6 release: 1.8.0
test / test (push) Has been cancelled
Add in-panel Help: CSS-only drawer with seeded Status and domain topics,
«?» entry points on cards, and guide.md boundary for what stays in-repo.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 23:00:08 +03:00
mixandCursor 27aeadc71d release: 1.7.0
test / test (push) Has been cancelled
Receive DMARC aggregate reports on port 25 and show parsed summaries in the panel. Close Unreleased; pin compose and docs to 1.7.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 22:53:36 +03:00
mixandCursor c1ec4fbd79 release: 1.6.0
test / test (push) Has been cancelled
Add 30-day send statistics and auto level-2 rate limits on the domain page. Close Unreleased; pin compose and docs to 1.6.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 22:26:51 +03:00
mixandCursor 8538b8d5f6 release: 1.5.0
test / test (push) Has been cancelled
Close Unreleased for send-log retention in Settings; pin compose and docs to 1.5.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 22:01:26 +03:00
mixandCursor 909145e5c8 Add send-log retention days to panel Settings.
Global administrators can set delivery journal retention (7-365 days) in SQLite;
SEND_LOG_RETENTION_DAYS seeds the initial default and the log-tailer re-reads
the value every prune cycle without a restart.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 21:57:48 +03:00
mixandCursor d0bf4a4226 release: 1.4.0
test / test (push) Has been cancelled
Close Unreleased for inbound relay; pin compose and docs to 1.4.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 23:20:18 +03:00
mixandCursor 0d98d92642 Add optional inbound relay (backup-MX) behind INBOUND_RELAY_ENABLE.
test / test (push) Has been cancelled
Port 25 accepts only configured domains and listed recipients, then forwards to an upstream; the outbound path is unchanged when the flag is off.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 23:17:30 +03:00
mixandCursor 6218540211 release: 1.3.1
test / test (push) Has been cancelled
Close Unreleased for retry-policy panel, persistent queue, and self-contained backups; pin compose and docs to 1.3.1.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 22:19:42 +03:00
mixandCursor 705239568b Show this Postfix's retry policy on Mail queue and delivery history.
test / test (push) Has been cancelled
Numbers come from a one-shot postconf -h at panel start so a manual override is visible after restart, without inventing an attempt count.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 22:12:03 +03:00
mixandCursor 46191172d6 docs: roadmap checklists, Progress column, commit/version protocol
test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 21:47:04 +03:00
mixandCursor b99f60c1d6 docs: add roadmap plans for domain stats, auto rate limit, and send-log retention
test / test (push) Has been cancelled
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 14:53:39 +03:00
mixandCursor 41c3e6e896 Persist Postfix queue and ship self-contained full backups.
Move the mail queue under /data so recreate no longer drops deferred mail, and archive data/, compose, .env, and certs/ together for restore on a fresh host.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 14:36:55 +03:00
mixandCursor c6a75ce775 docs: add DMARC report mockups and fold add-domain into lists
test / test (push) Has been cancelled
Domains and Inbound keep the add field in the list card. The DMARC candidate hub drills into a domain roll-up and a parsed aggregate report, including a third-party fail. The running panel is unchanged.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-16 21:44:20 +03:00
mixandCursor f47cf39802 docs: rebuild panel UI mockups on the design system
test / test (push) Has been cancelled
Split the hash-sheet prototype into one HTML file per screen, composed from stack, pair, measure, and fill. system.html is the grammar; shell.js is shared chrome. The running panel is unchanged.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-16 15:29:22 +03:00
mixandCursor 9edb39a8ee docs: iterate panel UI mockups from review
test / test (push) Has been cancelled
Restore Status readings, inbound MX DNS and recipient modes, two-column Backup and Settings, domain-card help, and Host/name Type field height.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-16 00:24:46 +03:00
mixandCursor f517e8da41 docs: add panel UI refresh mockups
Click-through gallery for current and roadmap screens, with a hybrid width proposal and a phone layout for emergency ops. The running panel is unchanged.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-15 23:47:55 +03:00
mixandCursor 2f888dc7be ci: drop per-arch GHCR tags via GitHub Packages API
test / test (push) Has been cancelled
imagetools has no rm subcommand; the merge cleanup had been failing silently. Document Gitea-to-GitHub tag mirror pitfalls in development.md. CHANGELOG [1.3.0] updated.

Co-Authored-By: Cursor <cursoragent@cursor.com>
v1.3.0
2026-08-15 22:57:34 +03:00
mixandCursor 5598b62e4e release: 1.3.0
test / test (push) Has been cancelled
Close Unreleased for security, tests, docs, and release CI; pin compose and docs to 1.3.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 21:51:29 +03:00
mixandCursor 32f5085c48 docs: record release CI workflow changes in [Unreleased]
The three post-1.2.5 CI commits that tie image publish to a published GitHub
Release and trim per-arch GHCR tags were missing from the changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 21:47:09 +03:00
mixandCursor 5601f73622 ci: consolidate release workflow and trim GHCR tags
test / test (push) Has been cancelled
Run release.yml directly on release:published instead of a dispatcher
workflow. Remove per-arch tags from GHCR after the manifest merge so only
X.Y.Z remains visible to operators.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 21:44:33 +03:00
mixandCursor e17b1680bd ci: dispatch release build from release-on-publish workflow
test / test (push) Has been cancelled
GitHub recorded release published at 16:44:21Z but no release.yml run
started. A thin release-on-publish workflow listens for publish and starts
release.yml via workflow_dispatch (always creates a run). release.yml now
checks out vX.Y.Z from the version input, not main HEAD.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-14 19:48:20 +03:00
mixandCursor 5b63da0e49 ci: trigger release workflow on published GitHub Release
test / test (push) Has been cancelled
Bare git tag pushes no longer start the image build; publishing a GitHub
Release does. workflow_dispatch still requires an explicit X.Y.Z version.
Docs explain draft vs published releases and that deleting a tag on GitHub
converts a published release back to draft.

Co-Authored-By: Cursor <cursoragent@cursor.com>
2026-08-14 19:43:06 +03:00
mixandCursor e9aaed1c7b docs: reconcile [Unreleased] with full git history since 1.2.5
test / test (push) Has been cancelled
Expand the doc-alignment entry to cover guide RBAC and restore Resync
wording; trim the P2 entry of claims superseded by that pass while keeping
its /license route-table addition with a cross-reference.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:40:46 +03:00
mixandCursor 1bd71c10d0 docs: align operator docs with routes, sessions, and restore
test / test (push) Has been cancelled
Fix architecture route RBAC, restore Resync, and session/password wording;
correct guide restore/session/PTR claims and README port-587 text; point
the CSRF ADR at authz.go for global route gating.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:36:24 +03:00
mixandCursor 74acf09212 docs: verify [Unreleased] against git since 1.2.5
test / test (push) Has been cancelled
Move restore Resync under Fixed to match e70ba90, and extend the restore
test bullet with the resync boot step and TestResyncAfterRestoreHealsDriftedMaps.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:30:12 +03:00
mixandCursor ba07decbb0 docs: bring [Unreleased] up to date with guide and review closure
Record the operator-guide restructure, merge the stale code-review plan
entry with its completion note, and align the restore Resync bullet with
the current backup package comment.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 19:24:29 +03:00
mixandClaude Sonnet 5 4fc5cff266 docs(guide): add worked restore commands to Full backup and restore
test / test (push) Has been cancelled
The section explained what a restore means conceptually but gave no
runnable commands. Add a step-by-step in-place restore, a
move-to-a-new-host variant, and the encrypted-backup decrypt-first
sequence, plus the actual version-mismatch error text so operators
know what to expect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 19:18:54 +03:00
mixandClaude Sonnet 5 ac8c2af500 docs(guide,architecture): move internal env vars out of the operator guide
test / test (push) Has been cancelled
Internal (non-operator) env vars were listed in guide.md's Environment
variables section even though the guide's own text says operators
aren't meant to touch them. They now live in architecture.md §
Configuration, the as-built/internals doc; guide.md keeps a one-line
pointer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 19:13:33 +03:00