Phase 7: monitoring UI — send log, queue, mail.log tail

Three HTMX-polled monitoring screens (spec 7.2.11-13): send log with
server-side domain/application filters and pagination, Postfix queue
(postqueue -p), and a mail.log tail. Fragment endpoints return HTML
snippets, not JSON (spec 7.1); all output is auto-escaped via
html/template (spec 7.6.7).

Adds store.QuerySendLog/CountSendLog/ListApplicationLogins,
postfix.Queue(), and logtail.TailLines (a point-in-time reverse read,
independent of the background follow loop). Verified on the dev server:
gofmt/vet/test green, docker build green, container e2e (filters,
60-row pagination, <script> escaping, real postqueue/mail.log output,
existing Reload button unaffected).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 23:22:08 +03:00
parent ab25d24706
commit cb25923a7b
16 changed files with 558 additions and 16 deletions
+21
View File
@@ -195,6 +195,27 @@ func (s *Store) ListApplicationsByDomain(domainID int64) ([]Application, error)
return out, nil
}
// ListApplicationLogins returns every application login across all domains,
// ordered, for the send-log monitoring screen's filter dropdown (spec 7.2).
// Logins are globally unique (spec 5.1), so no domain qualifier is needed.
func (s *Store) ListApplicationLogins() ([]string, error) {
rows, err := s.db.Query("SELECT login FROM applications ORDER BY login")
if err != nil {
return nil, fmt.Errorf("list application logins: %w", err)
}
defer rows.Close()
var out []string
for rows.Next() {
var login string
if err := rows.Scan(&login); err != nil {
return nil, err
}
out = append(out, login)
}
return out, rows.Err()
}
// ListLoginsByDomain returns the SASL logins of a domain's applications. Used to
// purge sasldb2 entries before a domain (and its applications via cascade) is
// deleted, while the logins are still known (spec 7.2.4).