feat(relay): drop max_event_bytes + rate-limit configs; verify on by default

Removes config keys + policies that don't earn their complexity:
  - [limits].max_event_bytes / MaxEventBytesPolicy — duplicates
    [limits].max_ws_frame_bytes which is the right layer (Ktor frame
    cap at the wire), and the policy-level check ran AFTER the event
    was already parsed and bound for the store.
  - [limits].messages_per_sec, [limits].subscriptions_per_min /
    RateLimitPolicy — per-session token buckets without the matching
    per-IP / global-EPS infrastructure are mostly cosmetic; an
    operator who needs real rate limits will use a reverse proxy.

Also flips [options].verify_signatures default from `false` to `true`.
A relay accepting traffic from real clients should verify Schnorr
signatures, and verify-by-default closes the footgun of forgetting
the flag. The CLI gains `--no-verify` for explicit opt-out
(test fixtures, mirror replays); the old `--verify` is dropped (a
no-op now anyway).

Removed:
  - quartz-relay/.../policies/MaxEventBytesPolicy.kt
  - quartz-relay/.../policies/RateLimitPolicy.kt
  - 7 obsolete tests in PoliciesTest + 1 in PoliciesIntegrationTest
  - The matching config fields in LimitsSection
  - Sample config entries in config.example.toml
  - Wiring in Main.composePolicy

Added:
  - Test verifySignaturesCanBeExplicitlyDisabled covering the
    new explicit-opt-out path.

Total :quartz-relay tests: 59, 0 failures.
This commit is contained in:
Claude
2026-05-07 02:36:18 +00:00
parent 65311590f2
commit 9ebdfc0b81
8 changed files with 39 additions and 370 deletions
+7 -19
View File
@@ -25,10 +25,6 @@ contact = "admin@example.com"
host = "0.0.0.0"
port = 7447
path = "/"
# Set when behind a reverse proxy (nginx/Caddy/Cloudflare). Required
# before any IP-based rate limit means anything. Parsed today, enforced
# once rate limits land.
# remote_ip_header = "X-Forwarded-For"
[database]
# True keeps an in-memory SQLite db (events vanish on restart). Useful
@@ -39,32 +35,24 @@ file = "/var/lib/quartz-relay/events.db"
[options]
# Drop events whose Schnorr signature does not verify. Strongly
# recommended for any relay accepting traffic from real clients.
verify_signatures = true
# Verify Schnorr signatures on every EVENT. Default: true. Disable
# only for trusted-input scenarios (test fixtures, mirror replays).
# verify_signatures = true
# Require clients to NIP-42 AUTH before REQ/EVENT/COUNT.
require_auth = false
# Reject events whose `created_at` is more than this many seconds in the
# future. Parsed today, enforced once the matching policy lands.
# Reject events whose `created_at` is more than this many seconds in
# the future. Enforced by RejectFutureEventsPolicy.
# reject_future_seconds = 1800
[limits]
# Maximum byte size of an EVENT (canonical NIP-01 JSON form).
# Enforced by MaxEventBytesPolicy.
# max_event_bytes = 131072
# Maximum WebSocket frame size. Frames larger than this are dropped at
# the WS layer. (max_ws_message_bytes maps to the same setting since
# Ktor's WebSockets plugin only exposes per-frame caps.)
# max_ws_message_bytes = 1048576
# max_ws_frame_bytes = 1048576
# Per-session token-bucket caps. Enforced by RateLimitPolicy.
# messages_per_sec = 10
# subscriptions_per_min = 60
# Parsed but NOT YET ENFORCED.
# max_subscriptions_per_session = 32
# max_filters_per_req = 10
[authorization]
# Allow / deny lists. Allow is a permissive ceiling; deny still
# removes specific entries inside it. Enforced by Pubkey/KindAllowDenyPolicy.