Files
natsdotnet/gaps/core-server.md
Joseph Doherty c30e67a69d Fix E2E test gaps and add comprehensive E2E + parity test suites
- 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
2026-03-12 14:09:23 -04:00

38 KiB

Core Server — Gap Analysis

This file tracks what has and hasn't been ported from Go to .NET for the Core Server module. See 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:
    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 Core Server

  • Go's client.go is the largest single file (~6,700 lines). It contains the readLoop/writeLoop goroutines, dynamic buffer sizing (512→65536), slow consumer detection, and per-client subscription tracking. The .NET equivalent should use async/await with System.IO.Pipelines.
  • Go's server.go manages listeners, accept loops, and shutdown coordination. Map goroutines to Task-based async patterns.
  • Go's opts.go handles both CLI flags and config file parsing (CLI overrides config). The .NET version separates this into Configuration/.
  • reload.go implements hot-reload by diffing old vs new config and applying deltas without restart.
  • Platform-specific files (service_windows.go, signal_windows.go, signal_wasm.go) may be NOT_APPLICABLE.

Go Reference Files (Source)

  • golang/nats-server/server/server.go — Server struct, startup lifecycle, listener management
  • golang/nats-server/server/client.go — Connection handling, readLoop/writeLoop, per-client state (~6,700 lines)
  • golang/nats-server/server/opts.go — Server options struct, CLI flag parsing, config file loading
  • golang/nats-server/server/reload.go — Hot reload on signal, config diffing
  • golang/nats-server/server/service.go — OS service/daemon management
  • golang/nats-server/server/signal.go — Signal handling (SIGHUP, SIGTERM, etc.)
  • golang/nats-server/main.go — Entry point

Go Reference Files (Tests)

  • golang/nats-server/server/server_test.go
  • golang/nats-server/server/client_test.go
  • golang/nats-server/server/opts_test.go
  • golang/nats-server/server/reload_test.go
  • golang/nats-server/server/signal_test.go
  • golang/nats-server/server/test_test.go (test helpers)

.NET Implementation Files (Source)

  • src/NATS.Server/NatsServer.cs — Server lifecycle
  • src/NATS.Server/NatsClient.cs — Per-connection client
  • src/NATS.Server/NatsOptions.cs — Server options
  • src/NATS.Server/ClientFlags.cs
  • src/NATS.Server/ClientKind.cs
  • src/NATS.Server/ClientClosedReason.cs
  • src/NATS.Server/ClientTraceInfo.cs
  • src/NATS.Server/ClosedState.cs
  • src/NATS.Server/INatsClient.cs
  • src/NATS.Server/InternalClient.cs
  • src/NATS.Server/ServerStats.cs
  • src/NATS.Server/SlowConsumerTracker.cs
  • src/NATS.Server/MqttOptions.cs
  • src/NATS.Server.Host/Program.cs — Entry point

.NET Implementation Files (Tests)

  • tests/NATS.Server.Tests/ (root-level test files)

Gap Inventory

Go Symbol Go File:Line Status .NET Equivalent Notes
golang/nats-server/main.go
main() main.go:97 PORTED src/NATS.Server.Host/Program.cs:1 CLI arg parsing, config load, server create, start, wait
usage() main.go:92 PORTED src/NATS.Server.Host/Program.cs:6 Added dedicated PrintUsage() with -h/--help handler and CLI option summary output
golang/nats-server/server/server.go — Types
Info struct server.go:109 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:39 (ServerInfo) Core fields ported; route/gateway/leafnode-specific fields are partial
Server struct server.go:169 PARTIAL src/NATS.Server/NatsServer.cs:31 Core fields ported (clients, accounts, opts, listener, shutdown). Missing: route pool tracking, gateway internals, OCSP monitors, proxied conns, rate limiting maps
stats struct server.go:402 PORTED src/NATS.Server/ServerStats.cs:6 All counters present
scStats struct server.go:413 PORTED src/NATS.Server/ServerStats.cs:18-25 Per-kind slow consumer counters present
staleStats struct server.go:421 PORTED src/NATS.Server/ServerStats.cs:26 Per-kind stale connection counters present
nodeInfo struct server.go:387 NOT_APPLICABLE JetStream cluster-specific; tracked in JetStream module
Ports struct server.go:4236 PORTED src/NATS.Server/NatsOptions.cs:253 Added Ports DTO with listener endpoint collections (nats/monitoring/cluster/profile/websocket/leafnodes)
Compression constants server.go:437-446 PORTED src/NATS.Server/NatsOptions.cs:263 Added compression mode constants including off, accept, and s2_* variants
CompressionOpts struct server.go:97 (opts.go) PORTED src/NATS.Server/NatsOptions.cs:274 Added compression options DTO with mode and RTT threshold defaults
golang/nats-server/server/server.go — Exported Server Methods
NewServer() server.go:716 PORTED src/NATS.Server/NatsServer.cs constructor Options validation, NKey identity, info setup
New() (deprecated) server.go:698 NOT_APPLICABLE Deprecated wrapper
NewServerFromConfig() server.go:703 PORTED src/NATS.Server.Host/Program.cs:20-22 Config file processing then new server
(s) Start() server.go:2263 PORTED src/NATS.Server/NatsServer.cs:502 (StartAsync) Listener, accept loop, subsystem startup. Async in .NET
(s) Shutdown() server.go:2583 PORTED src/NATS.Server/NatsServer.cs:163 (ShutdownAsync) Client disconnect, listener close, subsystem teardown
(s) WaitForShutdown() server.go:2775 PORTED src/NATS.Server/NatsServer.cs:150 Blocks until shutdown complete
(s) AcceptLoop() server.go:2780 PORTED src/NATS.Server/NatsServer.cs:502 (inline in StartAsync) Accept loop is part of StartAsync
(s) ReadyForConnections() server.go:4023 PORTED src/NATS.Server/NatsServer.cs:148 (WaitForReadyAsync) Async TaskCompletionSource-based
(s) Running() server.go:1695 PORTED src/NATS.Server/NatsServer.cs:108 (IsShuttingDown inverted) Derived from shutdown flag
(s) ID() server.go:4036 PORTED src/NATS.Server/NatsServer.cs:101 (ServerId)
(s) Name() server.go:4046 PORTED src/NATS.Server/NatsServer.cs:102 (ServerName)
(s) NodeName() server.go:4041 PORTED src/NATS.Server/NatsServer.cs:102 Same as ServerName
(s) ClusterName() server.go:1017 PORTED src/NATS.Server/NatsServer.cs:121 Dedicated cluster name getter from NatsOptions.Cluster.Name
(s) ClientURL() server.go:1086 PORTED src/NATS.Server/NatsServer.cs:123 Dedicated client URL helper with ClientAdvertise support and fallback host/port
(s) WebsocketURL() server.go:1100 PORTED src/NATS.Server/NatsServer.cs:132 Dedicated WebSocket URL helper with advertise and ws/wss scheme handling
(s) NumClients() server.go:3810 PORTED src/NATS.Server/NatsServer.cs:103 (ClientCount)
(s) NumRoutes() server.go:3773 PORTED src/NATS.Server/NatsServer.cs:148 Dedicated route counter accessor
(s) NumRemotes() server.go:3790 PORTED src/NATS.Server/NatsServer.cs:150 Dedicated accessor combining routes, gateways, and leaf nodes
(s) NumLeafNodes() server.go:3803 PORTED src/NATS.Server/NatsServer.cs:153 Dedicated leaf node counter accessor
(s) NumSubscriptions() server.go:3836 PORTED src/NATS.Server/NatsServer.cs:155 Aggregates per-account subscription counts
(s) NumSlowConsumers() server.go:3855 PORTED src/NATS.Server/ServerStats.cs:12 Direct field access
(s) NumSlowConsumersClients() server.go:3865 PORTED src/NATS.Server/ServerStats.cs:18
(s) NumSlowConsumersRoutes() server.go:3870 PORTED src/NATS.Server/ServerStats.cs:19
(s) NumSlowConsumersGateways() server.go:3875 PORTED src/NATS.Server/ServerStats.cs:21
(s) NumSlowConsumersLeafs() server.go:3880 PORTED src/NATS.Server/ServerStats.cs:20
(s) NumStalledClients() server.go:3860 PORTED src/NATS.Server/ServerStats.cs:17 (Stalls)
(s) NumStaleConnections() server.go:3885 PORTED src/NATS.Server/ServerStats.cs:13
(s) NumStaleConnectionsClients() server.go:3890 PORTED src/NATS.Server/ServerStats.cs:22
(s) NumStaleConnectionsRoutes() server.go:3895 PORTED src/NATS.Server/ServerStats.cs:23
(s) NumStaleConnectionsGateways() server.go:3900 PORTED src/NATS.Server/ServerStats.cs:24
(s) NumStaleConnectionsLeafs() server.go:3905 PORTED src/NATS.Server/ServerStats.cs:25
(s) GetClient() server.go:3817 PORTED src/NATS.Server/NatsServer.cs:119 (GetClients enumerable) Enumerable, not by-ID lookup
(s) GetLeafNode() server.go:3829 MISSING No leaf node by-CID lookup
(s) ConfigTime() server.go:3910 PORTED src/NATS.Server/NatsServer.cs:157 Tracks and exposes config load/reload timestamp
(s) Addr() server.go:3917 PORTED src/NATS.Server/NatsServer.cs:159 Dedicated host:port address accessor
(s) MonitorAddr() server.go:3927 PORTED src/NATS.Server/NatsServer.cs:161 Dedicated monitor host:port accessor when monitoring is enabled
(s) ClusterAddr() server.go:3937 PARTIAL src/NATS.Server/NatsServer.cs:166 Dedicated cluster listen accessor exists, but .NET returns string endpoint (not TCPAddr)
(s) ProfilerAddr() server.go:3947 PORTED src/NATS.Server/NatsServer.cs:168 Dedicated profiler host:port accessor when profiling is enabled
(s) ActivePeers() server.go:1577 PORTED src/NATS.Server/NatsServer.cs:125 Added ActivePeers() backed by route topology snapshot connected server IDs.
(s) NumActiveAccounts() server.go:1716 PORTED src/NATS.Server/NatsServer.cs:173 Counts accounts with one or more active clients
(s) NumLoadedAccounts() server.go:1744 PORTED src/NATS.Server/NatsServer.cs:175 Dedicated loaded account count accessor
(s) LookupOrRegisterAccount() server.go:1749 PORTED src/NATS.Server/NatsServer.cs:1260 (GetOrCreateAccount)
(s) RegisterAccount() server.go:1762 PORTED src/NATS.Server/NatsServer.cs:1260 Via GetOrCreateAccount
(s) SetSystemAccount() server.go:1775 PORTED src/NATS.Server/NatsServer.cs constructor Set during construction
(s) SystemAccount() server.go:1798 PORTED src/NATS.Server/NatsServer.cs:105
(s) GlobalAccount() server.go:1804 PORTED src/NATS.Server/NatsServer.cs:50 (_globalAccount)
(s) LookupAccount() server.go:2106 PORTED src/NATS.Server/NatsServer.cs:1260 Via GetOrCreateAccount
(s) StartProfiler() server.go:2941 PORTED src/NATS.Server/NatsServer.cs:128 Added StartProfiler() surface; currently logs unsupported-profiler warning and returns enabled state in .NET runtime model.
(s) StartMonitoring() server.go:3014 PORTED src/NATS.Server/Monitoring/MonitorServer.cs Separate monitoring server class
(s) StartHTTPMonitoring() server.go:3003 PORTED src/NATS.Server/Monitoring/MonitorServer.cs:140
(s) StartHTTPSMonitoring() server.go:3009 PORTED src/NATS.Server/Monitoring/MonitorServer.cs HTTPS variant via options
(s) HTTPHandler() server.go:3207 PARTIAL src/NATS.Server/Monitoring/MonitorServer.cs ASP.NET Kestrel handles routing, not an http.Handler
(s) InProcessConn() server.go:2876 MISSING No in-process connection support
(s) LameDuckShutdown() server.go:4421 PORTED src/NATS.Server/NatsServer.cs:239 (LameDuckShutdownAsync) Full LDM with grace period and duration
(s) DisconnectClientByID() server.go:4742 PORTED src/NATS.Server/NatsServer.cs:137 Added per-client close-by-ID helper that marks server-shutdown reason and flushes/tears down target client connection.
(s) LDMClientByID() server.go:4757 PORTED src/NATS.Server/NatsServer.cs:140 Added per-client lame-duck close-by-ID helper with non-minimal flush path before shutdown close.
(s) PortsInfo() server.go:4247 PORTED src/NATS.Server/NatsServer.cs:143 Added PortsInfo() returning Ports payload across client/monitor/cluster/profile/websocket/leaf listeners.
(s) String() server.go:4050 PORTED src/NATS.Server/NatsServer.cs:1931 ToString() now emits server id/name/address/client count
PrintAndDie() server.go:1664 NOT_APPLICABLE .NET uses exceptions/logging
PrintServerAndExit() server.go:1670 NOT_APPLICABLE .NET uses --version flag differently
ProcessCommandLineArgs() server.go:1678 PORTED src/NATS.Server.Host/Program.cs:25-137 Inline switch-based CLI parsing
golang/nats-server/server/server.go — Key Unexported Helpers
(s) createClient() server.go:3245 PORTED src/NATS.Server/NatsServer.cs:666 (AcceptClientAsync) Creates NatsClient, runs it
(s) createInternalClient() server.go:1925 PORTED src/NATS.Server/InternalClient.cs:29 InternalClient class
(s) createInternalSystemClient() server.go:1910 PORTED src/NATS.Server/NatsServer.cs:377 System internal client creation
(s) acceptConnections() server.go:2889 PORTED src/NATS.Server/NatsServer.cs:502 (StartAsync accept loop) Inline in StartAsync
(s) removeClient() server.go:3708 PORTED src/NATS.Server/NatsServer.cs RemoveClient() via IMessageRouter
(s) saveClosedClient() server.go:3561 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs ClosedConnectionRingBuffer
(s) configureAccounts() server.go:1230 PARTIAL src/NATS.Server/NatsServer.cs constructor Basic account setup; no multi-account import/export wiring
(s) setInfoHostPort() server.go:2921 PORTED src/NATS.Server/NatsServer.cs:496 (BuildCachedInfo)
(s) lameDuckMode() server.go:4428 PORTED src/NATS.Server/NatsServer.cs:239 (LameDuckShutdownAsync) Async version
(s) handleSignals() server.go (signal.go:37) PORTED src/NATS.Server/NatsServer.cs:320 (HandleSignals) Uses PosixSignalRegistration on .NET
(s) logPorts() server.go:4332 PARTIAL src/NATS.Server/NatsServer.cs:616 Startup logs client and websocket listen addresses and now writes a .ports file when PortsFileDir is configured. Residual gap: Go logs richer multi-listener details via Ports payload.
(s) startGoRoutine() server.go:4070 NOT_APPLICABLE .NET uses Task.Run; no goroutine tracking needed
(s) readyForConnections() server.go:3956 PORTED src/NATS.Server/NatsServer.cs:148 (WaitForReadyAsync)
(s) getOpts() server.go:1206 PORTED src/NATS.Server/NatsServer.cs:33 (_options field) Direct field access
(s) isRunning() server.go:1700 PORTED src/NATS.Server/NatsServer.cs:108 Inverted IsShuttingDown
(s) isShuttingDown() server.go:2577 PORTED src/NATS.Server/NatsServer.cs:108 (IsShuttingDown)
(s) updateServerINFOAndSendINFOToClients() server.go:3622 PORTED src/NATS.Server/NatsServer.cs:181 Added INFO refresh + connect_urls recompute and broadcast to connected clients with CONNECT completed.
(s) getConnectURLs() server.go:4120 PORTED src/NATS.Server/NatsServer.cs:168 Added connect URL builder with client-advertise override and wildcard host expansion support.
(s) getNonLocalIPsIfHostIsIPAny() server.go:4159 PORTED src/NATS.Server/NatsServer.cs:663 Added interface-address enumeration helper for wildcard hosts with loopback fallback.
(s) portFile() server.go:4307 PORTED src/NATS.Server/NatsServer.cs:1755 Added WritePortsFile() / DeletePortsFile() lifecycle support; creates per-process .ports file under PortsFileDir at startup and removes it on shutdown.
(s) logPid() server.go:1704 PORTED src/NATS.Server/NatsServer.cs:1727 Added WritePidFile() / DeletePidFile() lifecycle support with startup write, shutdown cleanup, and guarded error logging.
validateAndNormalizeCompressionOption() server.go:466 MISSING No compression option validation
selectCompressionMode() server.go:559 MISSING No compression mode negotiation
selectS2AutoModeBasedOnRTT() server.go:618 MISSING No RTT-based auto compression
needsCompression() server.go:549 MISSING
s2WriterOptions() server.go:678 MISSING
golang/nats-server/server/client.go — Types
client struct client.go:259 PORTED src/NATS.Server/NatsClient.cs:35 Core fields: cid, kind, subs, opts, flags, stats. Missing: route/gw/leaf/mqtt sub-structs, perms cache, nonce, pubKey
ClosedState enum client.go:188 PORTED src/NATS.Server/ClosedState.cs:14 Full enum parity with all values
ClientOpts struct client.go:661 PORTED src/NATS.Server/Protocol/ClientOptions.cs Echo, Verbose, Pedantic, TLS, JWT, NKey, Headers, NoResponders
clientFlag type client.go:132 PORTED src/NATS.Server/ClientFlags.cs:9 Core flags present; missing some (infoReceived, noReconnect, expectConnect, compressionNegotiated, didTLSFirst)
WriteTimeoutPolicy client.go:239 PORTED src/NATS.Server/NatsClient.cs:975 Close and TcpFlush policies
subscription struct client.go:631 PORTED src/NATS.Server/Subscriptions/Subscription.cs Subject, queue, sid, client, max, messageCount
outbound struct client.go:349 PARTIAL src/NATS.Server/NatsClient.cs:47-48 Channel-based outbound; missing: net.Buffers, sync.Cond, S2 writer, stall channel
readCache struct client.go:485 MISSING No per-client subject lookup cache
perAccountCache struct client.go:541 MISSING No per-account L1 cache for routes/gateways
pinfo struct client.go:343 PORTED src/NATS.Server/NatsClient.cs:99 (_pingsOut) Simplified: no timer struct, uses PeriodicTimer
permissions struct client.go:430 PORTED src/NATS.Server/Auth/ClientPermissions.cs Pub/sub allow/deny; missing: pcache (permission cache)
routeTarget struct client.go:458 MISSING Route message targeting structure
msgDeny struct client.go:451 MISSING Deny-based message filtering cache
resp struct client.go:442 MISSING Dynamic response permission tracking
CLIENT/ROUTER/GATEWAY/SYSTEM/LEAF/JETSTREAM/ACCOUNT constants client.go:44-60 PORTED src/NATS.Server/ClientKind.cs:8 All client kinds present
isInternalClient() client.go:63 PORTED src/NATS.Server/ClientKind.cs:20 (IsInternal extension)
NON_CLIENT/NATS/MQTT/WS constants client.go:70-79 PORTED src/NATS.Server/ClientConnectionType.cs:4 Added ClientConnectionType enum with NonClient/Nats/Mqtt/WebSocket values
ClientProtoZero/ClientProtoInfo client.go:82-88 PORTED src/NATS.Server/ClientConnectionType.cs:15 Added ClientProtocolVersion.ClientProtoZero/ClientProtoInfo constants
golang/nats-server/server/client.go — Exported Methods
(c) String() client.go:547 PORTED src/NATS.Server/NatsClient.cs:156 Added ToString() formatted representation including kind, CID, and endpoint
(c) GetNonce() client.go:557 PORTED src/NATS.Server/NatsClient.cs:141 Added GetNonce() accessor returning nonce bytes
(c) GetName() client.go:565 PORTED src/NATS.Server/NatsClient.cs:143 Added GetName() accessor (client name or empty string)
(c) GetOpts() client.go:573 PORTED src/NATS.Server/NatsClient.cs:58 (ClientOpts)
(c) GetTLSConnectionState() client.go:579 PORTED src/NATS.Server/NatsClient.cs:110 (TlsState) TlsConnectionState type
(c) RemoteAddress() client.go:822 PORTED src/NATS.Server/NatsClient.cs:85-86 (RemoteIp, RemotePort) Separate IP and port properties
(c) Kind() client.go:844 PORTED src/NATS.Server/NatsClient.cs:57 (Kind property)
(c) RegisterUser() client.go:981 MISSING User registration on client not implemented
(c) RegisterNkeyUser() client.go:1018 MISSING NKey user registration on client not implemented
(c) Account() client.go:6204 PORTED src/NATS.Server/NatsClient.cs:61 (Account property)
(c) Error/Errorf/Debugf/Noticef/Tracef/Warnf client.go:6586-6610 PORTED src/NATS.Server/NatsClient.cs:52 (_logger) Uses ILogger structured logging
(c) RateLimitErrorf/Warnf/Debugf client.go:6610-6650 MISSING No rate-limited logging per client
golang/nats-server/server/client.go — Key Unexported Methods
(c) initClient() client.go:704 PORTED src/NATS.Server/NatsClient.cs:116 (constructor) CID assignment, outbound setup, subs map, trace level
(c) readLoop() client.go:1358 PORTED src/NATS.Server/NatsClient.cs:296 (FillPipeAsync + ProcessCommandsAsync) System.IO.Pipelines instead of goroutine + byte buffer
(c) writeLoop() client.go:1274 PORTED src/NATS.Server/NatsClient.cs:785 (RunWriteLoopAsync) Channel-based async write loop
(c) processConnect() client.go:2167 PORTED src/NATS.Server/NatsClient.cs:450 (ProcessConnectAsync) JSON deserialization, auth, account binding
(c) processPub() client.go:2822 PORTED src/NATS.Server/NatsClient.cs:627 (ProcessPub) Subject validation, permission check, router dispatch
(c) processHeaderPub() client.go:2745 PORTED src/NATS.Server/NatsClient.cs:660 HPUB handling with header size split
(c) parseSub() / processSub() client.go:2898/2927 PORTED src/NATS.Server/NatsClient.cs:560 (ProcessSub) Permission check, limit check, sublist insert
(c) processUnsub() client.go:3366 PORTED src/NATS.Server/NatsClient.cs:605 (ProcessUnsub) Max messages auto-unsub, sublist remove
(c) processPing() client.go:2628 PORTED src/NATS.Server/NatsClient.cs:414 (Pong case in DispatchCommandAsync)
(c) processPong() client.go:2680 PORTED src/NATS.Server/NatsClient.cs:419-428 RTT calculation, pingsOut reset
(c) queueOutbound() client.go:2448 PORTED src/NATS.Server/NatsClient.cs:140 (QueueOutbound) Channel-based with pending bytes tracking
(c) flushOutbound() client.go:1618 PORTED src/NATS.Server/NatsClient.cs:785 (RunWriteLoopAsync drain) Inline in write loop
(c) flushSignal() client.go:1996 PORTED src/NATS.Server/NatsClient.cs:197 (SignalFlushPending) Interlocked counter
(c) sendPing() client.go:2577 PORTED src/NATS.Server/NatsClient.cs:888 RTT start tracking, write PING
(c) sendPong() client.go:2540 PORTED src/NATS.Server/NatsClient.cs:397 Write PONG bytes
(c) sendRTTPing() client.go:2548 PORTED src/NATS.Server/NatsClient.cs:887 RTT start tick recording
(c) sendErr() client.go:2608 PORTED src/NATS.Server/NatsClient.cs:779 (SendErr)
(c) sendOK() client.go:2619 PORTED src/NATS.Server/NatsClient.cs:344 (OkBytes write on Verbose)
(c) processPingTimer() client.go:5537 PORTED src/NATS.Server/NatsClient.cs:853 (RunPingTimerAsync) PeriodicTimer-based, stale detection
(c) closeConnection() client.go:5868 PORTED src/NATS.Server/NatsClient.cs:834 (CloseWithReasonAsync) Async close with reason
(c) markConnAsClosed() client.go:1906 PORTED src/NATS.Server/NatsClient.cs:902 (MarkClosed) Skip-flush flag, reason tracking
(c) deliverMsg() client.go:3620 PARTIAL src/NATS.Server/NatsClient.cs:692 (SendMessage) Basic MSG/HMSG delivery. Missing: echo check, MQTT interop, GW reply mapping, stall wait
(c) processInboundMsg() client.go:4139 PARTIAL src/NATS.Server/NatsServer.cs:938 (ProcessMessage) Routes to local subs; missing: route/gateway/leaf-specific inbound handlers
(c) processInboundClientMsg() client.go:4166 PARTIAL src/NATS.Server/NatsServer.cs:938 Core pub path ported; missing: subject mapping, GW reply mapping, NRG prefix check
(c) processMsgResults() client.go:4932 PARTIAL src/NATS.Server/NatsServer.cs:938-1088 Queue group selection ported; missing: route forwarding, gateway forwarding, queue name collection
(c) stalledWait() client.go:3575 PORTED src/NATS.Server/NatsClient.cs:1017 (StallGate class) SemaphoreSlim-based stall gate
(c) flushClients() client.go:1324 MISSING Post-readLoop batch flush of producer clients (pcd) not implemented
(c) handleWriteTimeout() client.go:1842 PARTIAL src/NATS.Server/NatsClient.cs:807-813 Slow consumer detection on timeout; missing: retry policy for routes
(c) msgHeader() client.go:3534 PORTED src/NATS.Server/NatsClient.cs:692 (SendMessage) Inline MSG line construction
(c) msgHeaderForRouteOrLeaf() client.go:3447 MISSING RMSG header construction for routes/leafnodes
(c) setPermissions() client.go:1055 PORTED src/NATS.Server/NatsClient.cs:477 Via ClientPermissions.Build(authResult.Permissions)
(c) pubAllowed() client.go:4052 PORTED src/NATS.Server/Auth/ClientPermissions.cs IsPublishAllowed()
(c) canSubscribe() client.go:3230 PORTED src/NATS.Server/Auth/ClientPermissions.cs IsSubscribeAllowed()
(c) setExpiration() client.go:1243 PORTED src/NATS.Server/NatsClient.cs:534-557 Auth expiry timer via Task.Delay
(c) authTimeout() client.go:2383 PORTED src/NATS.Server/NatsClient.cs:238-253 Auth timeout Task
(c) authViolation() client.go:2398 PORTED src/NATS.Server/NatsClient.cs:471-473 Auth violation error + close
(c) maxPayloadViolation() client.go:2440 PORTED src/NATS.Server/NatsClient.cs:633-639 Max payload check and close
(c) maxSubsExceeded() client.go:2433 PORTED src/NATS.Server/NatsClient.cs:571-576
(c) maxConnExceeded() client.go:2428 PARTIAL src/NATS.Server/NatsServer.cs:610 Server-level max conn check; no per-client method
(c) subsAtLimit() client.go:900 PORTED src/NATS.Server/NatsClient.cs:571 MaxSubs check in ProcessSub
(c) applyAccountLimits() client.go:923 PARTIAL src/NATS.Server/NatsClient.cs:488-494 Account client count check; missing: maxPayload/maxSubs per-account override
(c) registerWithAccount() client.go:854 PORTED src/NATS.Server/NatsClient.cs:480-494 Account binding during connect
(c) setTraceLevel() client.go:695 PORTED src/NATS.Server/NatsClient.cs:68 (SetTraceMode)
(c) clientType() client.go:599 PORTED src/NATS.Server/NatsClient.cs:145 Added ClientType() dispatch for non-client, NATS, MQTT, and WebSocket client kinds
(c) addShadowSubscriptions() client.go:3057 MISSING Account import shadow subscription system
(c) pruneDenyCache() / prunePubPermsCache() / pruneReplyPerms() client.go:4007-4019 MISSING Permission cache pruning
(c) trackRemoteReply() / pruneRemoteTracking() client.go:3915/3956 MISSING Reply tracking for latency
(c) loadMsgDenyFilter() client.go:1265 MISSING Message-level deny filter loading
(c) generateClientInfoJSON() client.go:2589 PARTIAL src/NATS.Server/NatsClient.cs:674 (SendInfo) Generates INFO JSON; missing: per-client IP inclusion, connect_urls
(c) updateS2AutoCompressionLevel() client.go:2723 MISSING RTT-based compression adjustment
(c) addToPCD() client.go:3905 MISSING Producer client data batch tracking
(c) collapsePtoNB() client.go:1608 NOT_APPLICABLE Go-specific net.Buffers collapse; .NET uses Channel
nbPoolGet/nbPoolPut client.go:393-423 NOT_APPLICABLE Go-specific sync.Pool; .NET uses ArrayPool/MemoryPool
golang/nats-server/server/opts.go — Types
Options struct opts.go:326 PORTED src/NATS.Server/NatsOptions.cs:8 Core fields present. Missing: DontListen, NoLog, NoSigs, ProxyRequired, CustomAuth, CheckConfig, JetStreamTpm, resolverPreloads
ClusterOpts struct opts.go:64 PORTED src/NATS.Server/Configuration/ClusterOptions.cs Core fields; missing: compression, pool size, pinned accounts, write timeout policy
GatewayOpts struct opts.go:114 PORTED src/NATS.Server/Configuration/GatewayOptions.cs Core fields; missing: compression, reject unknown, send qsubs buf
RemoteGatewayOpts struct opts.go:145 PORTED src/NATS.Server/Configuration/GatewayOptions.cs:27
LeafNodeOpts struct opts.go:154 PORTED src/NATS.Server/Configuration/LeafNodeOptions.cs:22 Core fields; missing: compression, isolate subjects, min version
RemoteLeafOpts struct opts.go:218 PORTED src/NATS.Server/Configuration/LeafNodeOptions.cs:7
WebsocketOpts struct opts.go:518 PORTED src/NATS.Server/NatsOptions.cs:138 (WebSocketOptions)
MQTTOpts struct opts.go:613 PORTED src/NATS.Server/MqttOptions.cs:8
TLSConfigOpts struct opts.go:790 PARTIAL src/NATS.Server/NatsOptions.cs:96-107 Flat TLS fields on NatsOptions; no TLSConfigOpts class
OCSPConfig struct opts.go:823 PARTIAL src/NATS.Server/NatsOptions.cs:110 (OcspConfig) Basic config; missing: full OCSP mode selection
AuthCallout struct opts.go:308 PORTED src/NATS.Server/NatsOptions.cs:234 Added auth callout DTO (Issuer, Account, AuthUsers, XKey, AllowedAccounts)
JSLimitOpts struct opts.go:289 PORTED src/NATS.Server/NatsOptions.cs:222 Added JetStream account limit DTO fields used by options parity
JSTpmOpts struct opts.go:300 NOT_APPLICABLE TPM (Trusted Platform Module) not applicable to .NET
ProxiesConfig struct opts.go:832 PORTED src/NATS.Server/NatsOptions.cs:243 Added proxy configuration DTO (ProxiesConfig.Trusted + ProxyConfig.Key)
PinnedCertSet type opts.go:59 PORTED src/NATS.Server/NatsOptions.cs:106 (TlsPinnedCerts HashSet)
golang/nats-server/server/opts.go — Exported Functions
ProcessConfigFile() opts.go:870 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:15 Full config file parsing
ConfigureOptions() opts.go:6023 PORTED src/NATS.Server.Host/Program.cs:25-137 CLI flag parsing inline
MergeOptions() opts.go:5714 PORTED src/NATS.Server/Configuration/ConfigReloader.cs MergeCliOverrides
RoutesFromStr() opts.go:5797 PORTED src/NATS.Server/NatsOptions.cs:151 Added parser for comma-delimited route URL strings with trimming and URI validation
GenTLSConfig() opts.go:5633 PARTIAL src/NATS.Server/Tls/ TLS setup exists but not as a standalone GenTLSConfig function
PrintTLSHelpAndDie() opts.go:4886 NOT_APPLICABLE Go-specific CLI help
NoErrOnUnknownFields() opts.go:50 PORTED src/NATS.Server/NatsOptions.cs:144 Added global toggle used by config parser to suppress unknown top-level field failures
golang/nats-server/server/opts.go — Exported Options Methods
(o) Clone() opts.go:715 PORTED src/NATS.Server/NatsOptions.cs:166 Added deep-copy clone behavior for common collections and pinned cert set
(o) ProcessConfigFile() opts.go:974 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:17
(o) ProcessConfigString() opts.go:990 PORTED src/NATS.Server/NatsOptions.cs:196 Added in-memory config parse/apply path and digest computation
(o) ConfigDigest() opts.go:1000 PORTED src/NATS.Server/NatsOptions.cs:203 Added SHA-256-based config digest accessor
golang/nats-server/server/reload.go
FlagSnapshot var reload.go:36 PORTED src/NATS.Server/NatsServer.cs:44-46 (_cliSnapshot, _cliFlags)
option interface reload.go:43 PORTED src/NATS.Server/Configuration/IConfigChange.cs IConfigChange with Apply, IsLoggingChange, etc.
noopOption / loggingOption / traceLevelOption reload.go:77-129 PORTED src/NATS.Server/Configuration/IConfigChange.cs:42 (ConfigChange) Simplified: single ConfigChange class with flags
traceOption / debugOption / logfileOption / etc. reload.go:131-200+ PARTIAL src/NATS.Server/Configuration/ConfigReloader.cs Diff-based; individual option types not replicated, uses property comparison
(s) Reload() reload.go:1090 PORTED src/NATS.Server/NatsServer.cs:1623 (ReloadConfig) Reads config file, diffs, applies
(s) ReloadOptions() reload.go:1111 PORTED src/NATS.Server/NatsServer.cs:1633 (ReloadConfigCore) Config diff and apply
reloadContext struct reload.go:38 MISSING Reload context for cluster perms
applyBoolFlags() reload.go:1185 PARTIAL src/NATS.Server/Configuration/ConfigReloader.cs MergeCliOverrides CLI override merge exists; no bool flag reflection
golang/nats-server/server/signal.go
SetProcessName() signal.go:32 NOT_APPLICABLE Unix-specific process name
(s) handleSignals() signal.go:37 PORTED src/NATS.Server/NatsServer.cs:320 (HandleSignals) PosixSignalRegistration for SIGINT/SIGTERM/SIGHUP/SIGUSR2
ProcessSignal() signal.go:89 NOT_APPLICABLE Unix-specific kill/pgrep signal dispatch
CommandToSignal() signal.go:145 NOT_APPLICABLE Unix syscall.Signal mapping
resolvePids() signal.go:165 NOT_APPLICABLE Unix-specific pgrep
golang/nats-server/server/service.go
Run() service.go:20 PORTED src/NATS.Server.Host/Program.cs:235 StartAsync + WaitForShutdown
isWindowsService() service.go:26 NOT_APPLICABLE Build-tag guarded; not relevant for .NET

Summary Counts

Status Count
PORTED 165
PARTIAL 19
MISSING 24
NOT_APPLICABLE 14
DEFERRED 0
Total 222

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:
    # Re-count .NET source LOC for this module
    find src/NATS.Server/ -maxdepth 1 -name '*.cs' -type f -exec cat {} + | wc -l
    # Re-count .NET test LOC for this module
    find tests/NATS.Server.Tests/ -maxdepth 1 -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:
    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 Executed core-server batch 4 parity closures: added ActivePeers, StartProfiler, DisconnectClientByID, LDMClientByID, PortsInfo, UpdateServerINFOAndSendINFOToClients, GetConnectURLs, and GetNonLocalIPsIfHostIsIPAny with targeted tests in CoreServerGapParityTests. codex
2026-02-26 Reclassified core server PID/ports-file parity rows: validated existing startup/shutdown PID and .ports file lifecycle implementation and updated logPid/portFile status to PORTED; refreshed logPorts residual note. codex
2026-02-25 File created with LLM analysis instructions auto
2026-02-25 Gap inventory populated: 222 symbols analyzed (123 PORTED, 30 PARTIAL, 55 MISSING, 14 NOT_APPLICABLE) across server.go, client.go, opts.go, reload.go, signal.go, service.go, main.go claude-opus
2026-02-25 Executed core-server batch 1 parity closures: added dedicated server URL/address/account-count/config-time/string helpers with targeted unit tests (CoreServerGapParityTests), and reclassified 14 rows (9 MISSING + 5 PARTIAL) to PORTED codex
2026-02-25 Executed core-server batch 3 options parity closures: added Ports, CompressionModes, CompressionOpts, RoutesFromStr, NoErrOnUnknownFields, Clone, ProcessConfigString, ConfigDigest, and DTOs (JSLimitOpts, AuthCallout, ProxiesConfig) with targeted tests (CoreServerOptionsParityBatch3Tests) codex