- Fix pull consumer fetch: send original stream subject in HMSG (not inbox) so NATS client distinguishes data messages from control messages - Fix MaxAge expiry: add background timer in StreamManager for periodic pruning - Fix JetStream wire format: Go-compatible anonymous objects with string enums, proper offset-based pagination for stream/consumer list APIs - Add 42 E2E black-box tests (core messaging, auth, TLS, accounts, JetStream) - Add ~1000 parity tests across all subsystems (gaps closure) - Update gap inventory docs to reflect implementation status
451 lines
48 KiB
Markdown
451 lines
48 KiB
Markdown
# Utilities & Other — Gap Analysis
|
|
|
|
> This file tracks what has and hasn't been ported from Go to .NET for the **Utilities & Other** module.
|
|
> See [stillmissing.md](stillmissing.md) for the full LOC comparison across all modules.
|
|
|
|
## LLM Instructions: How to Analyze This Category
|
|
|
|
### Step 1: Read the Go Reference Files
|
|
|
|
Read each Go source file listed below. For every file:
|
|
|
|
1. Extract all **exported types** (structs, interfaces, type aliases)
|
|
2. Extract all **exported methods** on those types (receiver functions)
|
|
3. Extract all **exported standalone functions**
|
|
4. Note **key constants, enums, and protocol states**
|
|
5. Note **important unexported helpers** that implement core logic (functions >20 lines)
|
|
6. Pay attention to **concurrency patterns** (goroutines, mutexes, channels) — these map to different .NET patterns
|
|
|
|
### Step 2: Read the .NET Implementation Files
|
|
|
|
Read all `.cs` files in the .NET directories listed below. For each Go symbol found in Step 1:
|
|
|
|
1. Search for a matching type, method, or function in .NET
|
|
2. If found, compare the behavior: does it handle the same edge cases? Same error paths?
|
|
3. If partially implemented, note what's missing
|
|
4. If not found, note it as MISSING
|
|
|
|
### Step 3: Cross-Reference Tests
|
|
|
|
Compare Go test functions against .NET test methods:
|
|
|
|
1. For each Go `Test*` function, check if a corresponding .NET `[Fact]` or `[Theory]` exists
|
|
2. Note which test scenarios are covered and which are missing
|
|
3. Check the parity DB (`docs/test_parity.db`) for existing mappings:
|
|
```bash
|
|
sqlite3 docs/test_parity.db "SELECT go_test, dotnet_test, confidence FROM test_mappings tm JOIN go_tests gt ON tm.go_test_id=gt.rowid JOIN dotnet_tests dt ON tm.dotnet_test_id=dt.rowid WHERE gt.go_file LIKE '%PATTERN%'"
|
|
```
|
|
|
|
### Step 4: Classify Each Item
|
|
|
|
Use these status values:
|
|
|
|
| Status | Meaning |
|
|
|--------|---------|
|
|
| **PORTED** | Equivalent exists in .NET with matching behavior |
|
|
| **PARTIAL** | .NET implementation exists but is incomplete (missing edge cases, error handling, or features) |
|
|
| **MISSING** | No .NET equivalent found — needs to be ported |
|
|
| **NOT_APPLICABLE** | Go-specific pattern that doesn't apply to .NET (build tags, platform-specific goroutine tricks, etc.) |
|
|
| **DEFERRED** | Intentionally skipped for now (document why) |
|
|
|
|
### Step 5: Fill In the Gap Inventory
|
|
|
|
Add rows to the Gap Inventory table below. Group by Go source file. Include the Go file and line number so a porting LLM can jump directly to the reference implementation.
|
|
|
|
### Key Porting Notes for Utilities & Other
|
|
|
|
- This category is at **7% LOC parity** — significant gap, but many items may be NOT_APPLICABLE:
|
|
- `sendq.go` / `ipqueue.go` — Go channel-based patterns; .NET uses `Channel<T>` or different buffering
|
|
- `ring.go` — May be replaced by .NET collections
|
|
- `ats/` — Address translation for NAT environments
|
|
- `elastic/` — Elasticsearch metric export (may be deferred)
|
|
- `tpm/` — Trusted Platform Module integration (platform-specific, likely DEFERRED)
|
|
- `internal/fastrand` — Go's fast random; .NET has `Random.Shared`
|
|
- `internal/ldap` — LDAP DN parsing for LDAP auth
|
|
- `internal/antithesis` — Chaos testing assertions (NOT_APPLICABLE unless using Antithesis)
|
|
- Focus on: `util.go` (byte parsing helpers), `errors.go` (error definitions), `rate_counter.go`, `scheduler.go`.
|
|
|
|
---
|
|
|
|
## Go Reference Files (Source)
|
|
|
|
- `golang/nats-server/server/util.go` — General utilities (string helpers, byte parsing, etc.)
|
|
- `golang/nats-server/server/ring.go` — Ring buffer implementation
|
|
- `golang/nats-server/server/rate_counter.go` — Rate limiting / counting
|
|
- `golang/nats-server/server/sendq.go` — Send queue for outbound messages
|
|
- `golang/nats-server/server/ipqueue.go` — IP-based queue
|
|
- `golang/nats-server/server/errors.go` — Error type definitions
|
|
- `golang/nats-server/server/errors_gen.go` — Generated error codes
|
|
- `golang/nats-server/server/sdm.go` — Server dynamic management
|
|
- `golang/nats-server/server/scheduler.go` — Internal task scheduler
|
|
- `golang/nats-server/server/ats/ats.go` — Address translation service
|
|
- `golang/nats-server/server/elastic/elastic.go` — Elasticsearch integration
|
|
- `golang/nats-server/server/tpm/js_ek_tpm_windows.go` — TPM key management (Windows)
|
|
- `golang/nats-server/server/tpm/js_ek_tpm_other.go` — TPM key management (non-Windows)
|
|
- `golang/nats-server/internal/` — Internal utility packages (fastrand, ldap, ocsp, testhelper, antithesis)
|
|
|
|
## Go Reference Files (Tests)
|
|
|
|
- `golang/nats-server/server/util_test.go`
|
|
- `golang/nats-server/server/ring_test.go`
|
|
- `golang/nats-server/server/rate_counter_test.go`
|
|
- `golang/nats-server/server/ipqueue_test.go`
|
|
- `golang/nats-server/server/errors_test.go`
|
|
|
|
## .NET Implementation Files (Source)
|
|
|
|
- `src/NATS.Server/IO/OutboundBufferPool.cs`
|
|
- `src/NATS.Server/IO/AdaptiveReadBuffer.cs`
|
|
- `src/NATS.Server/Server/AcceptLoopErrorHandler.cs`
|
|
|
|
## .NET Implementation Files (Tests)
|
|
|
|
- `tests/NATS.Server.Tests/IO/`
|
|
|
|
---
|
|
|
|
## Gap Inventory
|
|
|
|
### `golang/nats-server/server/util.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `refCountedUrlSet` (type alias) | golang/nats-server/server/util.go:34 | NOT_APPLICABLE | — | Internal clustering gossip helper; no equivalent needed in .NET port yet (clustering/gateway not fully ported) |
|
|
| `refCountedUrlSet.addUrl` | golang/nats-server/server/util.go:203 | NOT_APPLICABLE | — | Part of gossip URL ref-counting; used only in route/gateway code not yet ported |
|
|
| `refCountedUrlSet.removeUrl` | golang/nats-server/server/util.go:212 | NOT_APPLICABLE | — | Same as above |
|
|
| `refCountedUrlSet.getAsStringSlice` | golang/nats-server/server/util.go:226 | NOT_APPLICABLE | — | Same as above |
|
|
| `versionComponents` (unexported) | golang/nats-server/server/util.go:42 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:992 | Inlined as `VersionAtLeast` helper in test file; production equivalent used in server |
|
|
| `versionAtLeastCheckError` (unexported) | golang/nats-server/server/util.go:62 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:992 | Logic folded into `VersionAtLeast` test helper |
|
|
| `versionAtLeast` (unexported) | golang/nats-server/server/util.go:75 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:992 | Ported as `VersionAtLeast` in InfrastructureGoParityTests; production uses `System.Version` comparisons |
|
|
| `parseSize` (unexported) | golang/nats-server/server/util.go:82 | PORTED | src/NATS.Server/Protocol/NatsParser.cs:434 | `NatsParser.ParseSize(Span<byte>)` — exact behavioral match including -1 on error; tested in InfrastructureGoParityTests |
|
|
| `parseInt64` (unexported) | golang/nats-server/server/util.go:113 | PORTED | src/NATS.Server/Protocol/NatsParser.cs:434 | Folded into `ParseSize` / inline parser logic; behavior covered by parser tests |
|
|
| `secondsToDuration` (unexported) | golang/nats-server/server/util.go:127 | NOT_APPLICABLE | — | Go-specific `time.Duration` helper; .NET uses `TimeSpan.FromSeconds(double)` directly |
|
|
| `parseHostPort` (unexported) | golang/nats-server/server/util.go:134 | PORTED | src/NATS.Server/Server/ServerUtilities.cs:19 | Added `ParseHostPort(string, int)` with default-port fallback and 0/-1 port normalization |
|
|
| `urlsAreEqual` (unexported) | golang/nats-server/server/util.go:158 | NOT_APPLICABLE | — | Uses `reflect.DeepEqual` on `*url.URL`; not needed in .NET port (no equivalent URL gossip pattern yet) |
|
|
| `comma` (unexported) | golang/nats-server/server/util.go:169 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:960 | Ported as `CommaFormat` helper in InfrastructureGoParityTests (test-side only); monitoring output uses `string.Format("{0:N0}")` in production |
|
|
| `natsListenConfig` | golang/nats-server/server/util.go:246 | PORTED | src/NATS.Server/NatsServer.cs | .NET `TcpListener` / `Socket` used without OS TCP keepalives; keepalive is disabled by default in .NET socket setup matching Go behavior |
|
|
| `natsListen` (unexported) | golang/nats-server/server/util.go:252 | PORTED | src/NATS.Server/NatsServer.cs | Equivalent accept loop uses `TcpListener.AcceptTcpClientAsync` without system keepalives |
|
|
| `natsDialTimeout` (unexported) | golang/nats-server/server/util.go:258 | PORTED | src/NATS.Server/Routes/RouteManager.cs:547 | Added `CreateRouteDialSocket()` to explicitly disable TCP keepalive on outbound route dials before connect |
|
|
| `redactURLList` (unexported) | golang/nats-server/server/util.go:270 | PORTED | src/NATS.Server/Server/ServerUtilities.cs:79 | Added production `RedactUrlList(IEnumerable<string>)` that redacts per-URL user-info passwords |
|
|
| `redactURLString` (unexported) | golang/nats-server/server/util.go:296 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:979 | `RedactUrl` in InfrastructureGoParityTests matches behavior; also used in log redaction |
|
|
| `getURLsAsString` (unexported) | golang/nats-server/server/util.go:308 | NOT_APPLICABLE | — | Internal URL slice utility for clustering; not needed in current .NET scope |
|
|
| `copyBytes` (unexported) | golang/nats-server/server/util.go:317 | PORTED | (inline) | .NET uses `ReadOnlySpan<byte>.ToArray()`, `Array.Copy`, or `Buffer.BlockCopy` equivalently throughout the codebase |
|
|
| `copyStrings` (unexported) | golang/nats-server/server/util.go:328 | NOT_APPLICABLE | — | Go slice copying idiom; .NET uses LINQ `.ToArray()` or list copy directly |
|
|
| `generateInfoJSON` (unexported) | golang/nats-server/server/util.go:339 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs | `NatsProtocol.WriteInfo()` writes the `INFO …\r\n` frame directly to the write buffer |
|
|
| `parallelTaskQueue` (unexported) | golang/nats-server/server/util.go:350 | NOT_APPLICABLE | — | Go goroutine pool pattern; .NET uses `Parallel.ForEach`, `Task.WhenAll`, or `Channel<T>` for equivalent parallelism |
|
|
|
|
### `golang/nats-server/server/ring.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `closedClient` (type) | golang/nats-server/server/ring.go:17 | PORTED | src/NATS.Server/Monitoring/ClosedClient.cs | `ClosedClient` C# record mirrors the Go struct; includes connection info, subscription details |
|
|
| `closedRingBuffer` (type) | golang/nats-server/server/ring.go:25 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs | `ClosedConnectionRingBuffer` — full ring buffer with capacity, count, totalClosed, thread-safe via `Lock` |
|
|
| `newClosedRingBuffer` | golang/nats-server/server/ring.go:31 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:16 | Constructor with capacity parameter |
|
|
| `closedRingBuffer.append` | golang/nats-server/server/ring.go:39 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:37 | `Add(ClosedClient)` — overwrites oldest on overflow |
|
|
| `closedRingBuffer.next` (unexported) | golang/nats-server/server/ring.go:44 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs | Inlined into `Add` — `_head = (_head + 1) % _buffer.Length` |
|
|
| `closedRingBuffer.len` (unexported) | golang/nats-server/server/ring.go:48 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:24 | `Count` property |
|
|
| `closedRingBuffer.totalConns` (unexported) | golang/nats-server/server/ring.go:55 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:29 | `TotalClosed` property |
|
|
| `closedRingBuffer.closedClients` (unexported) | golang/nats-server/server/ring.go:65 | PORTED | src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:52 | `GetAll()` and `GetRecent(int)` — returns sorted copy; .NET returns newest-first (monitoring convention) |
|
|
|
|
### `golang/nats-server/server/rate_counter.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `rateCounter` (type) | golang/nats-server/server/rate_counter.go:21 | PORTED | src/NATS.Server/Tls/TlsRateLimiter.cs | `TlsRateLimiter` provides equivalent token-bucket rate limiting for TLS handshakes; also `ApiRateLimiter` for JetStream API |
|
|
| `newRateCounter` | golang/nats-server/server/rate_counter.go:30 | PORTED | src/NATS.Server/Tls/TlsRateLimiter.cs:9 | `TlsRateLimiter(long tokensPerSecond)` constructor |
|
|
| `rateCounter.allow` (unexported) | golang/nats-server/server/rate_counter.go:37 | PORTED | src/NATS.Server/Server/RateCounter.cs:21 | Added non-blocking `Allow()` with 1-second window and blocked-counter increment semantics |
|
|
| `rateCounter.countBlocked` (unexported) | golang/nats-server/server/rate_counter.go:58 | PORTED | src/NATS.Server/Server/RateCounter.cs:42 | Added `CountBlocked()` that returns and resets blocked count |
|
|
|
|
### `golang/nats-server/server/sendq.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `outMsg` (type) | golang/nats-server/server/sendq.go:21 | NOT_APPLICABLE | — | Internal message envelope for Go goroutine-to-goroutine delivery; .NET internal system events use `Channel<T>` with typed event objects directly |
|
|
| `sendq` (type) | golang/nats-server/server/sendq.go:28 | NOT_APPLICABLE | — | Go-specific goroutine-based internal send queue for system account messages; .NET equivalent is `Channel<T>` or `InternalEventSystem` dispatch |
|
|
| `Server.newSendQ` | golang/nats-server/server/sendq.go:35 | NOT_APPLICABLE | — | Factory for goroutine-based queue; not applicable to .NET async model |
|
|
| `sendq.internalLoop` (unexported) | golang/nats-server/server/sendq.go:41 | NOT_APPLICABLE | — | Go goroutine event loop; .NET uses `await foreach` on `Channel<T>` reader |
|
|
| `outMsgPool` | golang/nats-server/server/sendq.go:103 | NOT_APPLICABLE | — | `sync.Pool` for `outMsg` structs; .NET uses `ArrayPool<byte>` or object pools via `System.Buffers` |
|
|
| `sendq.send` | golang/nats-server/server/sendq.go:109 | NOT_APPLICABLE | — | Public entry point for internal system message dispatch; .NET internal event dispatch uses `InternalEventSystem.PublishAsync` |
|
|
|
|
### `golang/nats-server/server/ipqueue.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `ipQueue[T]` (generic type) | golang/nats-server/server/ipqueue.go:25 | NOT_APPLICABLE | — | Go generics-based intra-process queue using goroutine channels; .NET uses `System.Threading.Channels.Channel<T>` which provides the same producer-consumer semantics natively |
|
|
| `ipQueueOpts[T]` | golang/nats-server/server/ipqueue.go:38 | NOT_APPLICABLE | — | Options struct for ipQueue; .NET `Channel.CreateBounded/CreateUnbounded` options cover equivalent functionality |
|
|
| `ipQueueOpt[T]` (function type) | golang/nats-server/server/ipqueue.go:45 | NOT_APPLICABLE | — | Functional options pattern; .NET uses `BoundedChannelOptions` |
|
|
| `ipqMaxRecycleSize[T]` | golang/nats-server/server/ipqueue.go:49 | NOT_APPLICABLE | — | Pool recycling threshold; not needed with .NET GC |
|
|
| `ipqSizeCalculation[T]` | golang/nats-server/server/ipqueue.go:57 | NOT_APPLICABLE | — | Size tracking callback; .NET channels track count natively |
|
|
| `ipqLimitBySize[T]` | golang/nats-server/server/ipqueue.go:68 | NOT_APPLICABLE | — | Capacity limiting by byte size; .NET `BoundedChannelOptions.Capacity` limits by count; byte-size limiting is MISSING but not critical for current port scope |
|
|
| `ipqLimitByLen[T]` | golang/nats-server/server/ipqueue.go:77 | NOT_APPLICABLE | — | Capacity limiting by count; maps to `BoundedChannelOptions.Capacity` |
|
|
| `errIPQLenLimitReached` | golang/nats-server/server/ipqueue.go:83 | NOT_APPLICABLE | — | Error sentinel for capacity; .NET channels return `false` from `TryWrite` when full |
|
|
| `errIPQSizeLimitReached` | golang/nats-server/server/ipqueue.go:84 | NOT_APPLICABLE | — | Same as above for size-based limit |
|
|
| `newIPQueue[T]` | golang/nats-server/server/ipqueue.go:86 | NOT_APPLICABLE | — | Factory; equivalent is `Channel.CreateBounded<T>` or `Channel.CreateUnbounded<T>` |
|
|
| `ipQueue[T].push` | golang/nats-server/server/ipqueue.go:113 | NOT_APPLICABLE | — | Maps to `ChannelWriter<T>.TryWrite` |
|
|
| `ipQueue[T].pop` | golang/nats-server/server/ipqueue.go:152 | NOT_APPLICABLE | — | Maps to `ChannelReader<T>.ReadAllAsync` |
|
|
| `ipQueue[T].popOne` | golang/nats-server/server/ipqueue.go:178 | NOT_APPLICABLE | — | Maps to `ChannelReader<T>.TryRead` |
|
|
| `ipQueue[T].recycle` | golang/nats-server/server/ipqueue.go:215 | NOT_APPLICABLE | — | Slice pool return; not needed with .NET GC |
|
|
| `ipQueue[T].len` | golang/nats-server/server/ipqueue.go:234 | NOT_APPLICABLE | — | Maps to `ChannelReader<T>.Count` |
|
|
| `ipQueue[T].size` | golang/nats-server/server/ipqueue.go:242 | NOT_APPLICABLE | — | Byte-size tracking; no direct .NET equivalent but not needed |
|
|
| `ipQueue[T].drain` | golang/nats-server/server/ipqueue.go:253 | NOT_APPLICABLE | — | Flush/clear; .NET channels are drained by completing the writer and reading remaining items |
|
|
| `ipQueue[T].inProgress` | golang/nats-server/server/ipqueue.go:275 | NOT_APPLICABLE | — | In-flight count tracking; not needed in .NET model |
|
|
| `ipQueue[T].unregister` | golang/nats-server/server/ipqueue.go:281 | NOT_APPLICABLE | — | Remove from server map; .NET uses `ConcurrentDictionary.TryRemove` |
|
|
|
|
### `golang/nats-server/server/errors.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `ErrConnectionClosed` | golang/nats-server/server/errors.go:23 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs | Protocol-level error strings defined as constants in `NatsProtocol`; connection close reason tracked via `ClientClosedReason` enum |
|
|
| `ErrAuthentication` | golang/nats-server/server/errors.go:26 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs:30 | `ErrAuthorizationViolation` constant |
|
|
| `ErrAuthTimeout` | golang/nats-server/server/errors.go:29 | PORTED | src/NATS.Server/NatsClient.cs | Auth timeout enforced; close reason `AuthTimeout` in `ClientClosedReason` |
|
|
| `ErrAuthExpired` | golang/nats-server/server/errors.go:32 | PORTED | src/NATS.Server/NatsClient.cs | Auth expiry enforced via connection deadline |
|
|
| `ErrAuthProxyNotTrusted` | golang/nats-server/server/errors.go:35 | PORTED | src/NATS.Server/Auth/ | Proxy trust handled in auth layer |
|
|
| `ErrAuthProxyRequired` | golang/nats-server/server/errors.go:39 | PORTED | src/NATS.Server/Auth/ | Proxy requirement enforced |
|
|
| `ErrMaxPayload` | golang/nats-server/server/errors.go:43 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs:27 | `ErrMaxPayloadViolation` constant |
|
|
| `ErrMaxControlLine` | golang/nats-server/server/errors.go:46 | PORTED | src/NATS.Server/Protocol/NatsParser.cs | Parser throws when control line exceeds `MaxControlLineSize` |
|
|
| `ErrReservedPublishSubject` | golang/nats-server/server/errors.go:49 | PORTED | src/NATS.Server/NatsClient.cs | Reserved subject check on publish |
|
|
| `ErrBadPublishSubject` | golang/nats-server/server/errors.go:52 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs:28 | `ErrInvalidPublishSubject` constant |
|
|
| `ErrBadSubject` | golang/nats-server/server/errors.go:55 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs:29 | `ErrInvalidSubject` constant |
|
|
| `ErrBadQualifier` | golang/nats-server/server/errors.go:58 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:10 | Added parity literal constant for bad transform qualifier error |
|
|
| `ErrBadClientProtocol` | golang/nats-server/server/errors.go:61 | PORTED | src/NATS.Server/NatsClient.cs | Protocol version validation on CONNECT |
|
|
| `ErrTooManyConnections` | golang/nats-server/server/errors.go:64 | PORTED | src/NATS.Server/Protocol/NatsProtocol.cs:25 | `ErrMaxConnectionsExceeded` constant |
|
|
| `ErrTooManyAccountConnections` | golang/nats-server/server/errors.go:68 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:11 | Added parity error literal constant; enforcement work remains tracked separately in account-limit behavior gaps |
|
|
| `ErrLeafNodeLoop` | golang/nats-server/server/errors.go:72 | PORTED | src/NATS.Server/LeafNode/ | Leaf node loop detection implemented |
|
|
| `ErrTooManySubs` | golang/nats-server/server/errors.go:76 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:12 | Added parity error literal constant |
|
|
| `ErrTooManySubTokens` | golang/nats-server/server/errors.go:79 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:13 | Added parity error literal constant |
|
|
| `ErrClientConnectedToRoutePort` | golang/nats-server/server/errors.go:83 | PORTED | src/NATS.Server/Routes/ | Wrong port detection on route listener |
|
|
| `ErrClientConnectedToLeafNodePort` | golang/nats-server/server/errors.go:87 | PORTED | src/NATS.Server/LeafNode/ | Wrong port detection on leaf node listener |
|
|
| `ErrLeafNodeHasSameClusterName` | golang/nats-server/server/errors.go:91 | PORTED | src/NATS.Server/LeafNode/ | Same-cluster-name rejection |
|
|
| `ErrLeafNodeDisabled` | golang/nats-server/server/errors.go:94 | PORTED | src/NATS.Server/LeafNode/ | Leaf node disabled check |
|
|
| `ErrConnectedToWrongPort` | golang/nats-server/server/errors.go:98 | PORTED | src/NATS.Server/NatsServer.cs | Port sniffing / wrong-port close |
|
|
| `ErrAccountExists` | golang/nats-server/server/errors.go:102 | PORTED | src/NATS.Server/Auth/Account.cs | Duplicate account registration check |
|
|
| `ErrBadAccount` | golang/nats-server/server/errors.go:105 | PORTED | src/NATS.Server/Auth/ | Bad/malformed account |
|
|
| `ErrReservedAccount` | golang/nats-server/server/errors.go:108 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:14 | Added parity error literal constant |
|
|
| `ErrMissingAccount` | golang/nats-server/server/errors.go:111 | PORTED | src/NATS.Server/Auth/ | Missing account lookup |
|
|
| `ErrMissingService` | golang/nats-server/server/errors.go:114 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:15 | Added parity error literal constant |
|
|
| `ErrBadServiceType` | golang/nats-server/server/errors.go:117 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:16 | Added parity error literal constant |
|
|
| `ErrBadSampling` | golang/nats-server/server/errors.go:120 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:17 | Added parity error literal constant |
|
|
| `ErrAccountValidation` | golang/nats-server/server/errors.go:123 | PORTED | src/NATS.Server/Auth/ | Account validation logic |
|
|
| `ErrAccountExpired` | golang/nats-server/server/errors.go:126 | PORTED | src/NATS.Server/Auth/ | Account expiry check |
|
|
| `ErrNoAccountResolver` | golang/nats-server/server/errors.go:129 | PORTED | src/NATS.Server/Auth/ | No resolver configured check |
|
|
| `ErrAccountResolverUpdateTooSoon` | golang/nats-server/server/errors.go:132 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:18 | Added parity error literal constant |
|
|
| `ErrAccountResolverSameClaims` | golang/nats-server/server/errors.go:135 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:19 | Added parity error literal constant |
|
|
| `ErrStreamImportAuthorization` | golang/nats-server/server/errors.go:138 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:20 | Added parity error literal constant |
|
|
| `ErrStreamImportBadPrefix` | golang/nats-server/server/errors.go:141 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:21 | Added parity error literal constant |
|
|
| `ErrStreamImportDuplicate` | golang/nats-server/server/errors.go:144 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:22 | Added parity error literal constant |
|
|
| `ErrServiceImportAuthorization` | golang/nats-server/server/errors.go:147 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:23 | Added parity error literal constant |
|
|
| `ErrImportFormsCycle` | golang/nats-server/server/errors.go:150 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:24 | Added parity error literal constant |
|
|
| `ErrCycleSearchDepth` | golang/nats-server/server/errors.go:153 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:25 | Added parity error literal constant |
|
|
| `ErrClientOrRouteConnectedToGatewayPort` | golang/nats-server/server/errors.go:157 | PORTED | src/NATS.Server/Gateways/ | Wrong port detection on gateway listener |
|
|
| `ErrWrongGateway` | golang/nats-server/server/errors.go:161 | PORTED | src/NATS.Server/Gateways/ | Wrong gateway name on connect |
|
|
| `ErrGatewayNameHasSpaces` | golang/nats-server/server/errors.go:165 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs | Config validation rejects spaces in gateway name |
|
|
| `ErrNoSysAccount` | golang/nats-server/server/errors.go:169 | PORTED | src/NATS.Server/NatsServer.cs | System account presence check |
|
|
| `ErrRevocation` | golang/nats-server/server/errors.go:172 | PORTED | src/NATS.Server/Auth/ | Credential revocation check |
|
|
| `ErrServerNotRunning` | golang/nats-server/server/errors.go:175 | PORTED | src/NATS.Server/NatsServer.cs | Server running state check |
|
|
| `ErrServerNameHasSpaces` | golang/nats-server/server/errors.go:178 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1434 | Config validation; `ConfigProcessorException` thrown |
|
|
| `ErrBadMsgHeader` | golang/nats-server/server/errors.go:181 | PORTED | src/NATS.Server/Protocol/NatsParser.cs | Header parsing validation |
|
|
| `ErrMsgHeadersNotSupported` | golang/nats-server/server/errors.go:185 | PORTED | src/NATS.Server/NatsClient.cs | Headers-not-supported check |
|
|
| `ErrNoRespondersRequiresHeaders` | golang/nats-server/server/errors.go:189 | PORTED | src/NATS.Server/NatsClient.cs | No-responders validation |
|
|
| `ErrClusterNameConfigConflict` | golang/nats-server/server/errors.go:193 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs | Cluster/gateway name conflict validation |
|
|
| `ErrClusterNameRemoteConflict` | golang/nats-server/server/errors.go:196 | PORTED | src/NATS.Server/Routes/ | Remote cluster name mismatch |
|
|
| `ErrClusterNameHasSpaces` | golang/nats-server/server/errors.go:199 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs | Config validation |
|
|
| `ErrMalformedSubject` | golang/nats-server/server/errors.go:202 | PORTED | src/NATS.Server/Subscriptions/SubjectMatch.cs | Subject validation rejects malformed subjects |
|
|
| `ErrSubscribePermissionViolation` | golang/nats-server/server/errors.go:205 | PORTED | src/NATS.Server/NatsClient.cs | Subscribe permission check |
|
|
| `ErrNoTransforms` | golang/nats-server/server/errors.go:208 | PORTED | src/NATS.Server/Server/ServerErrorConstants.cs:26 | Added parity error literal constant |
|
|
| `ErrCertNotPinned` | golang/nats-server/server/errors.go:211 | PORTED | src/NATS.Server/Tls/TlsHelper.cs | Pinned cert validation |
|
|
| `ErrDuplicateServerName` | golang/nats-server/server/errors.go:215 | PORTED | src/NATS.Server/Routes/ | Duplicate server name on cluster connect |
|
|
| `ErrMinimumVersionRequired` | golang/nats-server/server/errors.go:218 | PORTED | src/NATS.Server/Routes/ | Minimum version enforcement on cluster |
|
|
| `ErrInvalidMappingDestination` | golang/nats-server/server/errors.go:221 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Transform destination validation |
|
|
| `ErrInvalidMappingDestinationSubject` | golang/nats-server/server/errors.go:223 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Invalid destination subject |
|
|
| `ErrMappingDestinationNotUsingAllWildcards` | golang/nats-server/server/errors.go:226 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Wildcard coverage check |
|
|
| `ErrUnknownMappingDestinationFunction` | golang/nats-server/server/errors.go:229 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Unknown function error |
|
|
| `ErrMappingDestinationIndexOutOfRange` | golang/nats-server/server/errors.go:232 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Index out of range |
|
|
| `ErrMappingDestinationNotEnoughArgs` | golang/nats-server/server/errors.go:235 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Not enough args error |
|
|
| `ErrMappingDestinationInvalidArg` | golang/nats-server/server/errors.go:238 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Invalid arg error |
|
|
| `ErrMappingDestinationTooManyArgs` | golang/nats-server/server/errors.go:241 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Too many args error |
|
|
| `ErrMappingDestinationNotSupportedForImport` | golang/nats-server/server/errors.go:244 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Import-only wildcard restriction |
|
|
| `mappingDestinationErr` (type) | golang/nats-server/server/errors.go:248 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Equivalent validation exceptions in transform code |
|
|
| `mappingDestinationErr.Error` | golang/nats-server/server/errors.go:253 | PORTED | src/NATS.Server/Subscriptions/SubjectTransform.cs | Exception message formatting |
|
|
| `mappingDestinationErr.Is` | golang/nats-server/server/errors.go:257 | NOT_APPLICABLE | — | Go `errors.Is` interface; .NET uses `is` and `catch (SpecificException)` instead |
|
|
| `configErr` (type) | golang/nats-server/server/errors.go:261 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1434 | `ConfigProcessorException` with error list |
|
|
| `configErr.Source` | golang/nats-server/server/errors.go:267 | PARTIAL | src/NATS.Server/Configuration/ConfigProcessor.cs | Source file/line tracking in errors is partial; exception message includes context but not file:line:col |
|
|
| `configErr.Error` | golang/nats-server/server/errors.go:272 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs | Exception `Message` property |
|
|
| `unknownConfigFieldErr` (type) | golang/nats-server/server/errors.go:280 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1597 | Added `UnknownConfigFieldWarning` type with field/source metadata and Go-style warning message (`unknown field <name>`). |
|
|
| `configWarningErr` (type) | golang/nats-server/server/errors.go:292 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1588 | Added `ConfigWarningException` base warning type to distinguish warning payloads from hard errors. |
|
|
| `processConfigErr` (type) | golang/nats-server/server/errors.go:303 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1434 | `ConfigProcessorException` accumulates all errors |
|
|
| `processConfigErr.Error` | golang/nats-server/server/errors.go:310 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs | `Message` + `Errors` list |
|
|
| `processConfigErr.Warnings` | golang/nats-server/server/errors.go:322 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1581 | Added `ConfigProcessorException.Warnings` list and wired unknown top-level field warnings into thrown config errors when validation errors are present. |
|
|
| `processConfigErr.Errors` | golang/nats-server/server/errors.go:327 | PORTED | src/NATS.Server/Configuration/ConfigProcessor.cs:1437 | `ConfigProcessorException.Errors` property |
|
|
| `errCtx` (type) | golang/nats-server/server/errors.go:332 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1069 | `WrappedNatsException` (test-file-scoped) mirrors the error context wrapping; production code uses standard .NET exception chaining |
|
|
| `NewErrorCtx` | golang/nats-server/server/errors.go:338 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1069 | Equivalent via `new WrappedNatsException(inner, ctx)` in tests; production uses `new Exception(msg, inner)` |
|
|
| `errCtx.Unwrap` | golang/nats-server/server/errors.go:343 | NOT_APPLICABLE | — | Go `errors.Unwrap` interface; .NET uses `Exception.InnerException` |
|
|
| `errCtx.Context` | golang/nats-server/server/errors.go:350 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1069 | `WrappedNatsException.FullTrace()` extracts and returns context |
|
|
| `UnpackIfErrorCtx` | golang/nats-server/server/errors.go:358 | PORTED | tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1075 | `WrappedNatsException.FullTrace()` — recursive trace assembly matches Go's `UnpackIfErrorCtx` logic |
|
|
| `errorsUnwrap` (unexported) | golang/nats-server/server/errors.go:371 | NOT_APPLICABLE | — | Go 1.13 compatibility shim; .NET uses `Exception.InnerException` directly |
|
|
| `ErrorIs` | golang/nats-server/server/errors.go:382 | NOT_APPLICABLE | — | Go 1.13 compatibility shim for `errors.Is`; .NET uses `is`, `catch`, or `Exception.GetType()` |
|
|
|
|
### `golang/nats-server/server/errors_gen.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| (entire file — code generator) | golang/nats-server/server/errors_gen.go:1 | NOT_APPLICABLE | — | This is a `//go:build ignore` code generator that produces `jetstream_errors_generated.go`. The generated JetStream API error codes are ported directly as `JetStreamApiError` and integer error code constants in `src/NATS.Server/JetStream/Api/`. No need to port the generator itself. |
|
|
|
|
### `golang/nats-server/server/sdm.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `SDMMeta` (type) | golang/nats-server/server/sdm.go:22 | MISSING | — | Subject Delete Marker metadata tracker; used inside `stream.go` for SDM/KV purge tracking. MsgScheduling not yet ported so SDMMeta is also absent. |
|
|
| `SDMBySeq` (type) | golang/nats-server/server/sdm.go:27 | MISSING | — | Per-sequence SDM state (last flag + timestamp); needed by `SDMMeta` |
|
|
| `newSDMMeta` | golang/nats-server/server/sdm.go:33 | MISSING | — | Constructor for `SDMMeta` |
|
|
| `isSubjectDeleteMarker` (unexported) | golang/nats-server/server/sdm.go:42 | MISSING | — | Header inspection to detect SDM or KV purge markers; needed for FileStore tombstone handling |
|
|
| `SDMMeta.empty` | golang/nats-server/server/sdm.go:47 | MISSING | — | Clear all tracking state |
|
|
| `SDMMeta.trackPending` | golang/nats-server/server/sdm.go:56 | MISSING | — | Cache a pending SDM sequence |
|
|
| `SDMMeta.removeSeqAndSubject` | golang/nats-server/server/sdm.go:66 | MISSING | — | Remove a confirmed SDM from tracking |
|
|
|
|
### `golang/nats-server/server/scheduler.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `ErrMsgScheduleInvalidVersion` | golang/nats-server/server/scheduler.go:29 | MISSING | — | Error for unknown schedule snapshot version; needed when decoding binary schedule state |
|
|
| `MsgScheduling` (type) | golang/nats-server/server/scheduler.go:35 | MISSING | — | Core message scheduler type — manages per-subject schedules, timer, THW integration; tests in FileStoreTombstoneTests.cs note this is not yet ported |
|
|
| `MsgSchedule` (type) | golang/nats-server/server/scheduler.go:46 | MISSING | — | Per-subject schedule entry (seq + timestamp) |
|
|
| `newMsgScheduling` | golang/nats-server/server/scheduler.go:51 | MISSING | — | Constructor with run callback |
|
|
| `MsgScheduling.add` | golang/nats-server/server/scheduler.go:61 | MISSING | — | Add/replace a schedule entry |
|
|
| `MsgScheduling.init` (unexported) | golang/nats-server/server/scheduler.go:66 | MISSING | — | Internal init with THW integration |
|
|
| `MsgScheduling.update` | golang/nats-server/server/scheduler.go:81 | MISSING | — | Update timestamp of existing schedule |
|
|
| `MsgScheduling.markInflight` | golang/nats-server/server/scheduler.go:93 | MISSING | — | Mark subject as currently being delivered |
|
|
| `MsgScheduling.isInflight` | golang/nats-server/server/scheduler.go:99 | MISSING | — | Check if subject is in-flight |
|
|
| `MsgScheduling.remove` | golang/nats-server/server/scheduler.go:104 | MISSING | — | Remove by sequence number |
|
|
| `MsgScheduling.removeSubject` | golang/nats-server/server/scheduler.go:111 | MISSING | — | Remove by subject |
|
|
| `MsgScheduling.clearInflight` | golang/nats-server/server/scheduler.go:119 | MISSING | — | Reset all in-flight tracking |
|
|
| `MsgScheduling.resetTimer` (unexported) | golang/nats-server/server/scheduler.go:123 | MISSING | — | Recalculate next fire time from THW |
|
|
| `MsgScheduling.getScheduledMessages` (unexported) | golang/nats-server/server/scheduler.go:158 | MISSING | — | Evaluate expired schedules; complex — includes pattern parsing, header manipulation |
|
|
| `MsgScheduling.encode` | golang/nats-server/server/scheduler.go:249 | MISSING | — | Binary snapshot serialization |
|
|
| `MsgScheduling.decode` | golang/nats-server/server/scheduler.go:267 | MISSING | — | Binary snapshot deserialization |
|
|
| `parseMsgSchedule` (unexported) | golang/nats-server/server/scheduler.go:302 | MISSING | — | Parse `@at ...` / `@every ...` schedule patterns |
|
|
|
|
### `golang/nats-server/server/ats/ats.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `TickInterval` (const) | golang/nats-server/server/ats/ats.go:25 | MISSING | — | 100ms tick interval constant for access-time service |
|
|
| `Register` | golang/nats-server/server/ats/ats.go:42 | MISSING | — | Start the access-time goroutine (ref-counted). Used by FileStore on creation to get efficient nanosecond timestamps without calling `time.Now()` on every access. |
|
|
| `Unregister` | golang/nats-server/server/ats/ats.go:64 | MISSING | — | Stop the access-time goroutine when last user unregisters |
|
|
| `AccessTime` | golang/nats-server/server/ats/ats.go:76 | MISSING | — | Return cached Unix nanosecond timestamp (atomic load). .NET equivalent could use `Interlocked`-cached `DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()` but no such service exists yet |
|
|
|
|
### `golang/nats-server/server/elastic/elastic.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `Pointer[T]` (generic type) | golang/nats-server/server/elastic/elastic.go:26 | MISSING | — | Elastic (weak/strong) reference wrapper using Go 1.24 `weak.Pointer`. Used for FileStore block caching to allow GC to reclaim blocks while keeping a strong ref when needed. No .NET equivalent ported. |
|
|
| `Make[T]` | golang/nats-server/server/elastic/elastic.go:20 | MISSING | — | Factory for `Pointer[T]` from a strong pointer |
|
|
| `Pointer[T].Set` | golang/nats-server/server/elastic/elastic.go:31 | MISSING | — | Update the weak/strong pointer |
|
|
| `Pointer[T].Strengthen` | golang/nats-server/server/elastic/elastic.go:38 | MISSING | — | Promote weak ref to strong |
|
|
| `Pointer[T].Weaken` | golang/nats-server/server/elastic/elastic.go:45 | MISSING | — | Demote strong ref to weak (allow GC) |
|
|
| `Pointer[T].Value` | golang/nats-server/server/elastic/elastic.go:52 | MISSING | — | Get current value (strong if available, else weak) |
|
|
|
|
### `golang/nats-server/server/tpm/js_ek_tpm_windows.go` and `js_ek_tpm_other.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `JsKeyTPMVersion` | golang/nats-server/server/tpm/js_ek_tpm_windows.go:34 | DEFERRED | — | TPM version constant; entire TPM subsystem deferred |
|
|
| `regenerateSRK` (unexported) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:51 | DEFERRED | — | Windows-only TPM2 SRK creation |
|
|
| `natsTPMPersistedKeys` (type) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:77 | DEFERRED | — | JSON-serializable key blob struct |
|
|
| `writeTPMKeysToFile` (unexported) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:85 | DEFERRED | — | Persist TPM key blobs to disk |
|
|
| `readTPMKeysFromFile` (unexported) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:115 | DEFERRED | — | Read TPM key blobs from disk |
|
|
| `createAndSealJsEncryptionKey` (unexported) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:146 | DEFERRED | — | Create NKey-based JetStream encryption key and seal to TPM |
|
|
| `unsealJsEncrpytionKey` (unexported) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:178 | DEFERRED | — | Unseal JetStream key from TPM |
|
|
| `policyPCRPasswordSession` (unexported) | golang/nats-server/server/tpm/js_ek_tpm_windows.go:203 | DEFERRED | — | TPM2 policy session with PCR + password |
|
|
| `LoadJetStreamEncryptionKeyFromTPM` | golang/nats-server/server/tpm/js_ek_tpm_windows.go:245 | DEFERRED | — | Main entry point; Windows only. Non-Windows stub returns error. Deferred: requires `Microsoft.TPM` or `Tss.Net` NuGet and Windows-only API surface. |
|
|
| `LoadJetStreamEncryptionKeyFromTPM` (stub) | golang/nats-server/server/tpm/js_ek_tpm_other.go:21 | NOT_APPLICABLE | — | Non-Windows stub; .NET would use `PlatformNotSupportedException` equivalently |
|
|
|
|
### `golang/nats-server/internal/fastrand/fastrand.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `Uint32` | golang/nats-server/internal/fastrand/fastrand.go:12 | NOT_APPLICABLE | — | Links to `runtime.fastrand` via `go:linkname` — a Go runtime internal. .NET uses `Random.Shared.Next()` or `RandomNumberGenerator` equivalently. No need to port this internal. |
|
|
| `Uint32n` | golang/nats-server/internal/fastrand/fastrand.go:17 | NOT_APPLICABLE | — | Same as above; maps to `Random.Shared.Next(0, n)` |
|
|
| `Uint64` | golang/nats-server/internal/fastrand/fastrand.go:20 | NOT_APPLICABLE | — | Same as above; maps to `Random.Shared.NextInt64()` |
|
|
|
|
### `golang/nats-server/internal/ldap/dn.go`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `AttributeTypeAndValue` (type) | golang/nats-server/internal/ldap/dn.go:30 | PARTIAL | src/NATS.Server/Auth/TlsMapAuthenticator.cs | .NET `X500DistinguishedName` used directly; no standalone `AttributeTypeAndValue` type |
|
|
| `RelativeDN` (type) | golang/nats-server/internal/ldap/dn.go:37 | PARTIAL | src/NATS.Server/Auth/TlsMapAuthenticator.cs | `X500DistinguishedName.EnumerateRelativeDistinguishedNames()` provides equivalent; no custom `RelativeDN` type |
|
|
| `DN` (type) | golang/nats-server/internal/ldap/dn.go:43 | PARTIAL | src/NATS.Server/Auth/TlsMapAuthenticator.cs | `X500DistinguishedName` (.NET BCL) used instead; no custom `DN` type |
|
|
| `FromCertSubject` | golang/nats-server/internal/ldap/dn.go:48 | PARTIAL | src/NATS.Server/Auth/TlsMapAuthenticator.cs:31 | Certificate subject extracted via `X509Certificate2.SubjectName`; does not support multi-value RDNs or full RFC 4514 ordering |
|
|
| `FromRawCertSubject` | golang/nats-server/internal/ldap/dn.go:80 | MISSING | — | Raw ASN.1 subject parsing preserving original order; not implemented |
|
|
| `ParseDN` | golang/nats-server/internal/ldap/dn.go:126 | MISSING | — | RFC 4514 DN string parser; not implemented. .NET uses `X500DistinguishedName` which parses RFC 2253 format but lacks the Go implementation's special-case handling |
|
|
| `DN.Equal` | golang/nats-server/internal/ldap/dn.go:220 | MISSING | — | RFC 4517 distinguishedNameMatch comparison |
|
|
| `DN.RDNsMatch` | golang/nats-server/internal/ldap/dn.go:234 | MISSING | — | Order-independent RDN matching |
|
|
| `DN.AncestorOf` | golang/nats-server/internal/ldap/dn.go:258 | MISSING | — | DN ancestry check |
|
|
| `RelativeDN.Equal` | golang/nats-server/internal/ldap/dn.go:278 | MISSING | — | RFC 4517 RDN equivalence |
|
|
| `RelativeDN.hasAllAttributes` (unexported) | golang/nats-server/internal/ldap/dn.go:285 | MISSING | — | Attribute superset check |
|
|
| `AttributeTypeAndValue.Equal` | golang/nats-server/internal/ldap/dn.go:302 | MISSING | — | Case-insensitive type + value comparison |
|
|
|
|
### `golang/nats-server/internal/antithesis/`
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `AssertUnreachable` (noop build) | golang/nats-server/internal/antithesis/noop.go:24 | NOT_APPLICABLE | — | Chaos testing assertion (noop when Antithesis SDK not active); .NET has no Antithesis SDK. xUnit's `Assert.Fail()` covers the reachability assertion pattern in tests. |
|
|
| `Assert` (noop build) | golang/nats-server/internal/antithesis/noop.go:27 | NOT_APPLICABLE | — | Same as above; .NET uses Shouldly `condition.ShouldBeTrue()` in tests |
|
|
| `AssertUnreachable` (SDK build) | golang/nats-server/internal/antithesis/test_assert.go:49 | NOT_APPLICABLE | — | Antithesis SDK wrapper; no .NET Antithesis SDK exists |
|
|
| `Assert` (SDK build) | golang/nats-server/internal/antithesis/test_assert.go:83 | NOT_APPLICABLE | — | Same as above |
|
|
|
|
### `golang/nats-server/internal/testhelper/` (ocsp.go / logging.go)
|
|
|
|
| Go Symbol | Go File:Line | Status | .NET Equivalent | Notes |
|
|
|-----------|:-------------|--------|:----------------|-------|
|
|
| `NewOCSPResponder` | golang/nats-server/internal/testhelper/ocsp.go (ocsp.go):45 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | .NET OCSP test helper implemented inline in test files using ASP.NET Core minimal APIs |
|
|
| `NewOCSPResponderCustomAddress` | golang/nats-server/internal/testhelper/ocsp.go:40 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | Equivalent test helper |
|
|
| `NewOCSPResponderDesignatedCustomAddress` | golang/nats-server/internal/testhelper/ocsp.go:50 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | Designated responder variant |
|
|
| `NewOCSPResponderPreferringHTTPMethod` | golang/nats-server/internal/testhelper/ocsp.go:55 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | HTTP method preference variant |
|
|
| `NewOCSPResponderCustomTimeout` | golang/nats-server/internal/testhelper/ocsp.go:60 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | Custom TTL variant |
|
|
| `NewOCSPResponderBase` | golang/nats-server/internal/testhelper/ocsp.go:65 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | Base factory; all OCSP responder variants collapse to this |
|
|
| `GetOCSPStatus` | golang/nats-server/internal/testhelper/ocsp.go:230 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | OCSP status extraction from TLS connection state |
|
|
| `SetOCSPStatus` | golang/nats-server/internal/testhelper/ocsp.go:251 | PORTED | tests/NATS.Server.Tests/OcspStaplingTests.cs | HTTP POST to set cert status on mock OCSP responder |
|
|
|
|
---
|
|
|
|
## .NET-Only Implementations (No Direct Go Equivalent)
|
|
|
|
The following .NET types were added to support the porting but have no exact Go counterpart:
|
|
|
|
| .NET Type | File | Notes |
|
|
|-----------|------|-------|
|
|
| `OutboundBufferPool` | `src/NATS.Server/IO/OutboundBufferPool.cs` | Tiered byte-array pool (512/4096/65536) replacing Go's `sync.Pool` + `[]byte` dynamic sizing |
|
|
| `AdaptiveReadBuffer` | `src/NATS.Server/IO/AdaptiveReadBuffer.cs` | Buffer sizing state machine; mirrors `client.go` readLoop buffer growth/shrink logic |
|
|
| `AcceptLoopErrorHandler` | `src/NATS.Server/Server/AcceptLoopErrorHandler.cs` | Callback-based accept error delegation (no Go equivalent; Go logs inline) |
|
|
| `TlsRateLimiter` | `src/NATS.Server/Tls/TlsRateLimiter.cs` | Async token-bucket rate limiter for TLS handshakes |
|
|
|
|
---
|
|
|
|
## Keeping This File Updated
|
|
|
|
After porting work is completed:
|
|
|
|
1. **Update status**: Change `MISSING → PORTED` or `PARTIAL → PORTED` for each item completed
|
|
2. **Add .NET path**: Fill in the ".NET Equivalent" column with the actual file:line
|
|
3. **Re-count LOC**: Update the LOC numbers in `stillmissing.md`:
|
|
```bash
|
|
# Re-count .NET source LOC for this module
|
|
find src/NATS.Server/IO/ src/NATS.Server/Server/ -name '*.cs' -type f -exec cat {} + | wc -l
|
|
# Re-count .NET test LOC for this module
|
|
find tests/NATS.Server.Tests/IO/ -name '*.cs' -type f -exec cat {} + | wc -l
|
|
```
|
|
4. **Add a changelog entry** below with date and summary of what was ported
|
|
5. **Update the parity DB** if new test mappings were created:
|
|
```bash
|
|
sqlite3 docs/test_parity.db "INSERT INTO test_mappings (go_test_id, dotnet_test_id, confidence, notes) VALUES (?, ?, 'manual', 'ported in YYYY-MM-DD session')"
|
|
```
|
|
|
|
## Change Log
|
|
|
|
| Date | Change | By |
|
|
|------|--------|----|
|
|
| 2026-02-26 | Ported config warning parity slice: added `ConfigWarningException`, `UnknownConfigFieldWarning`, and `ConfigProcessorException.Warnings`; wired unknown top-level fields as warning entries and added focused configuration parity tests. | codex |
|
|
| 2026-02-25 | File created with LLM analysis instructions | auto |
|
|
| 2026-02-25 | Full gap inventory populated — all Go source files analyzed, 131 symbols classified | auto |
|
|
| 2026-02-25 | Ported missing `errors.go` parity literals into `ServerErrorConstants` and added targeted parity tests for the newly added constants | codex |
|