mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-06 07:28:23 +00:00
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.
58 lines
3.1 KiB
Markdown
58 lines
3.1 KiB
Markdown
# 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.
|