release: 1.9.0
test / test (push) Waiting to run

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>
This commit is contained in:
2026-08-18 23:51:41 +03:00
parent a8ded7ecc8
commit b4a9b93cf2
26 changed files with 457 additions and 252 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ func testLevel2RateLimit(t *testing.T, sc *scenario) {
if err != nil {
t.Fatal(err)
}
if err := sc.panel.setRateLimit(fmt.Sprintf("/applications/%s/ratelimit", appID), ip, 1, 3600); err != nil {
if err := sc.panel.setRateLimit(fmt.Sprintf("/applications/%s/ratelimit", appID), 1, 3600); err != nil {
t.Fatalf("save application rate limit: %v", err)
}
+2 -6
View File
@@ -195,16 +195,12 @@ func (c *panelClient) addApplication(domainID, login, mode, addresses string) (a
}
// setRateLimit saves a level-2 limit (guide § Rate limiting) on an application
// (/applications/{id}/ratelimit). allowedIP is required for the trusted-IP
// override; domain ceilings are posted without IPs.
func (c *panelClient) setRateLimit(path, allowedIP string, maxMessages, windowSeconds int) error {
// or domain (/applications/{id}/ratelimit or /domains/{id}/ratelimit).
func (c *panelClient) setRateLimit(path string, maxMessages, windowSeconds int) error {
vals := url.Values{
"max_messages": {fmt.Sprintf("%d", maxMessages)},
"window_seconds": {fmt.Sprintf("%d", windowSeconds)},
}
if allowedIP != "" {
vals.Set("allowed_ips", allowedIP)
}
resp, body, err := c.postForm(path, vals)
if err != nil {
return err