rust-nostr 0.45 newly enables a 120-query-per-minute LocalRelay default. Production sync exhausted it because each SDK-managed NIP-77 NEG-MSG continuation consumes the same per-connection bucket, while the small per-connection quota alone is weak DoS protection because clients can multiply connections. Override the embedded relay allowance by 10x to 1,200 queries per minute while retaining a finite safety backstop. Keep the value internal rather than expanding the operator configuration surface, and document the effective limit and its rationale. Correctness assumes the existing subscription, message, write, event-size, and connection-admission controls remain the primary resource bounds. Per-IP or global rate limiting and proactive outbound historic pacing are deliberately excluded. This override is temporary: review its value after rust-nostr separates or otherwise revises NIP-77 continuation accounting. Validation: nix develop -c cargo check --lib.
3.1 KiB
Embedded relay limits
ngit-grasp embeds rust-nostr LocalRelay 0.45.0. The application selects every
effective limit explicitly so future dependency defaults cannot silently alter
production admission policy.
Effective limits
| Limit | ngit-grasp default | Operator configuration | NIP-11 |
|---|---|---|---|
| Total inbound connections | Unbounded | NGIT_MAX_CONNECTIONS |
No standard field |
| Active REQs per connection | 500 | NGIT_RELAY_MAX_SUBSCRIPTIONS |
max_subscriptions |
| Results per filter | 500 | NGIT_RELAY_FILTER_LIMIT |
max_limit, default_limit |
| Serialized event size | 192 KiB | NGIT_RELAY_MAX_EVENT_SIZE_BYTES |
No equivalent field |
| Event writes per minute | 60 | Fixed | No standard field |
| Queries per minute | 1,200 | Fixed temporary override | No standard field |
| Authentication events per minute | 30 | Fixed | No standard field |
| WebSocket messages per minute | 6,000 | Fixed | No standard field |
| WebSocket message size | 5 MiB | Fixed | max_message_length |
| Handshake deadline | 10 seconds | Fixed | No standard field |
| Subscription-ID length | 250 bytes | Fixed | max_subid_length |
| Filters per REQ | 20 | Fixed | No standard field |
| Subscription state per connection | 1 MiB | Fixed | No standard field |
| Active negentropy sessions per connection | 10 | Fixed | No standard field |
| Negentropy items per connection | 50,000 | Fixed | No standard field |
| Negentropy frame | 60,000 bytes | Fixed upstream | No standard field |
The filter setting is applied consistently to rust-nostr's explicit filter cap, per-query result cap, and omitted-limit default. Limits are per filter; results from multiple filters in one REQ are merged without an aggregate truncation.
The 192 KiB event default is three times rust-nostr's new 64 KiB default. Production history contains a valid NIP-34 patch event of about 149 KiB, so 64 KiB is incompatible with ngit-grasp's purpose. The raised limit remains bounded and below the 5 MiB WebSocket message ceiling.
The 1,200-query allowance temporarily overrides rust-nostr 0.45's newly
introduced 120/minute default. A finite per-connection bound remains one useful
DoS layer, but the upstream default is unusually restrictive for sync clients
and currently counts every SDK-managed NIP-77 NEG-MSG continuation as another
query. Review this 10× override after upstream changes that accounting; a small
per-connection quota is not a substitute for per-IP admission or global
resource bounds because clients can multiply connections.
Client adaptation
ngit-grasp refetches NIP-11 per connection session. Its outbound sync ledger
uses max_subscriptions, falling back conservatively when absent. Adaptive
historic pagination uses default_limit with a verification page and learns
from raw delivered page sizes. max_limit describes explicit filter limits;
historic sync currently omits limit, so it does not treat max_limit as an
omitted-filter page-size promise.
NIP-11 has no standard max_filters field in the current schema. Filter-count
and serialized-message budgets therefore remain conservative client-side
constants rather than falsely negotiated capabilities.