# Sections 3-6 Gaps Implementation Design > Approved 2026-02-23. Implements all remaining gaps in Protocol Parsing, Subscriptions & Subject Matching, Authentication & Authorization, and Configuration. --- ## Section 3 — Protocol Parsing ### 3a. INFO Serialization Caching Add `byte[] _infoJsonCache` on `NatsServer`. Build once in `StartAsync()` after `ServerInfo` is populated. Rebuild only on config reload. `NatsClient.SendInfo()` uses cached bytes for non-nonce connections. For NKey connections (which need a per-connection nonce), clone `ServerInfo`, set nonce, serialize fresh. **Files:** `NatsServer.cs`, `NatsClient.cs` ### 3b. Protocol Tracing Add `ILogger` to `NatsParser`. Add `TraceInOp(ReadOnlySpan op, ReadOnlySpan arg)` that logs at `LogLevel.Trace` after each command dispatch in `TryParse()`. Controlled by `NatsOptions.Trace` (which sets log level filter). **Files:** `NatsParser.cs`, `NatsOptions.cs` ### 3c. MIME Header Parsing New `NatsHeaderParser` static class in `Protocol/`. Parses `NATS/1.0 \r\n` status line + `Key: Value\r\n` pairs. Returns `NatsHeaders` readonly struct with `Status` (int), `Description` (string), and key-value `Dictionary` lookup. Used in `ProcessMessage()` for header inspection (no-responders status, future message tracing). **Files:** New `Protocol/NatsHeaderParser.cs`, `NatsServer.cs` ### 3d. MSG/HMSG Construction Optimization Pre-allocate buffers for MSG/HMSG prefix using `Span` and `Utf8Formatter` instead of string interpolation + `Encoding.UTF8.GetBytes()`. Reduces per-message allocations. **Files:** `NatsClient.cs` --- ## Section 4 — Subscriptions & Subject Matching ### 4a. Atomic Generation ID for Cache Invalidation Add `long _generation` to `SubList`. Increment via `Interlocked.Increment` on every `Insert()` and `Remove()`. Cache entries store generation at computation time. On `Match()`, stale generation = cache miss. Replaces current explicit per-key cache removal. O(1) invalidation. **Files:** `SubList.cs` ### 4b. Async Background Cache Sweep Replace inline sweep (runs under write lock) with `PeriodicTimer`-based background task. Acquires write lock briefly to snapshot + evict stale entries. Triggered when cache count > 1024, sweeps to 256. **Files:** `SubList.cs` ### 4c. `plist` Optimization for High-Fanout Nodes On `TrieNode`, when `PlainSubs.Count > 256`, convert `HashSet` to `Subscription[]` flat array in `PList` field. `Match()` iterates `PList` when present. On count < 128, convert back to HashSet. **Files:** `SubList.cs` ### 4d. SubList Utility Methods | Method | Description | |--------|-------------| | `Stats()` | Returns `SubListStats` record with NumSubs, NumCache, NumInserts, NumRemoves, NumMatches, CacheHitRate, MaxFanout. Track via `Interlocked` counters. | | `HasInterest(string)` | Walk trie without building result, return true on first hit. | | `NumInterest(string)` | Walk trie, count without allocating result arrays. | | `ReverseMatch(string)` | Walk trie with literal tokens, collect all subscription patterns matching the literal. | | `RemoveBatch(IEnumerable)` | Single write-lock, batch removes, single generation bump. | | `All()` | Depth-first trie walk, yield all subscriptions. Returns `IReadOnlyList`. | | `MatchBytes(ReadOnlySpan)` | Zero-copy match using byte-based `TokenEnumerator`. | **Files:** `SubList.cs`, new `SubListStats.cs` ### 4e. SubjectMatch Utilities | Method | Description | |--------|-------------| | `SubjectsCollide(string, string)` | Token-by-token comparison handling `*` and `>`. Two patterns collide if any literal could match both. | | `TokenAt(string, int)` | Return nth dot-delimited token as `ReadOnlySpan`. | | `NumTokens(string)` | Count dots + 1. | | UTF-8/null validation | Add `checkRunes` parameter to `IsValidSubject()`. When true, scan for `\0` bytes and validate UTF-8. | **Files:** `SubjectMatch.cs` ### 4f. Per-Account Subscription Limits Add `MaxSubscriptions` to `Account`. Track `SubscriptionCount` via `Interlocked`. Enforce in `ProcessSub()`. Close with `ClientClosedReason.MaxSubscriptionsExceeded`. **Files:** `Account.cs`, `NatsClient.cs` --- ## Section 5 — Authentication & Authorization ### 5a. Deny List Enforcement at Delivery Time In `NatsServer.DeliverMessage()`, before sending MSG, check `subscriber.Client.Permissions?.IsDeliveryAllowed(subject)`. New method checks publish deny list for the receiving client ("msg delivery filter"). Cache results in pub cache. **Files:** `NatsServer.cs`, `ClientPermissions.cs` ### 5b. Permission Caching with 128-Entry LRU Replace `ConcurrentDictionary` with custom `PermissionLruCache` (128 entries). `Dictionary` + `LinkedList` for LRU ordering. Lock-protected (per-client, low contention). **Files:** `ClientPermissions.cs`, new `Auth/PermissionLruCache.cs` ### 5c. Subscribe Deny Queue-Group Checking `IsSubscribeAllowed(subject, queue)` checks queue group against subscribe deny list (currently ignores queue parameter). **Files:** `ClientPermissions.cs` ### 5d. Response Permissions (Reply Tracking) New `ResponseTracker` class on `NatsClient`. Created when `Permissions.Response` is non-null. Tracks reply subjects with TTL (`ResponsePermission.Expires`) and max count (`ResponsePermission.MaxMsgs`). `IsPublishAllowed()` consults tracker for reply subjects not in static allow list. Expired entries cleaned lazily + in ping timer. **Files:** New `Auth/ResponseTracker.cs`, `ClientPermissions.cs`, `NatsClient.cs` ### 5e. Per-Account Connection Limits Add `MaxConnections` to `Account`. Enforce in `ProcessConnectAsync()` after account assignment. Reject with `-ERR maximum connections for account exceeded`. **Files:** `Account.cs`, `NatsClient.cs` ### 5f. Multi-Account User Resolution Add `NatsOptions.Accounts` as `Dictionary` with per-account MaxConnections, MaxSubscriptions, DefaultPermissions. `AuthService` resolves account name to configured `Account` with limits. **Files:** `NatsOptions.cs`, new `Auth/AccountConfig.cs`, `AuthService.cs`, `NatsServer.cs` ### 5g. Auth Expiry Enforcement In `ProcessConnectAsync()`, if `AuthResult.Expiry` is set, start `CancellationTokenSource.CancelAfter(expiry - now)`. Link to client lifetime. On fire, close with `ClientClosedReason.AuthenticationExpired`. **Files:** `NatsClient.cs` ### 5h. Auto-Unsub Cleanup In `DeliverMessage()`, when `sub.MessageCount >= sub.MaxMessages`, call `sub.Client.RemoveSubscription(sub.Sid)` and `subList.Remove(sub)` to clean up both tracking dict and trie. Currently only skips delivery. **Files:** `NatsServer.cs`, `NatsClient.cs` --- ## Section 6 — Configuration ### 6a. Debug/Trace CLI Flags Add `-D`/`--debug`, `-V`/`--trace`, `-DV` to `Program.cs`. Set `NatsOptions.Debug` and `NatsOptions.Trace`. Wire into Serilog minimum level. **Files:** `Program.cs` ### 6b. New NatsOptions Fields | Field | Type | Default | Purpose | |-------|------|---------|---------| | `MaxSubs` | int | 0 (unlimited) | Per-connection subscription limit | | `MaxSubTokens` | int | 0 (unlimited) | Max tokens in a subject | | `Debug` | bool | false | Enable debug-level logging | | `Trace` | bool | false | Enable trace-level protocol logging | | `LogFile` | string? | null | Log to file instead of console | | `LogSizeLimit` | long | 0 | Max log file size before rotation | | `Tags` | Dictionary? | null | Server metadata tags | **Files:** `NatsOptions.cs` ### 6c. Logging Options Wiring In `Program.cs`, if `LogFile` is set, add Serilog `File` sink with `LogSizeLimit`. If `Debug`/`Trace`, override Serilog minimum level. **Files:** `Program.cs` --- ## Implementation Strategy Execute in a git worktree. Parallelize where files don't overlap: - **Parallel batch 1:** SubjectMatch utilities (4e) | NatsOptions + CLI flags (6a, 6b) | NatsHeaderParser (3c) | PermissionLruCache (5b) | SubListStats (4d stats class) - **Parallel batch 2:** SubList overhaul (4a, 4b, 4c, 4d methods) | Account limits + config (4f, 5e, 5f, 5g) | Response tracker (5d) - **Parallel batch 3:** Protocol tracing (3b) | INFO caching (3a) | MSG optimization (3d) - **Sequential:** Delivery-time enforcement (5a, 5c, 5h) — touches NatsServer.cs + ClientPermissions.cs, must be coordinated - **Final:** Logging wiring (6c) | differences.md update Tests added alongside each feature in the appropriate test file.