# Configuration — Gap Analysis > This file tracks what has and hasn't been ported from Go to .NET for the **Configuration** 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 Configuration - .NET LOC **exceeds** Go LOC (4,559 vs 1,871) because .NET implements a full lexer/parser/token pipeline. - The Go config format is a custom format (not JSON, not YAML). It supports includes, variables, and block structures. - `opts.go` (in Core Server category) also participates in config — it maps CLI flags + config file to the options struct. - Hot reload (`reload.go` in Core Server) depends on config diffing — ensure the .NET config model supports this. --- ## Go Reference Files (Source) - `golang/nats-server/conf/lex.go` — Lexer for NATS config file format - `golang/nats-server/conf/parse.go` — Parser for config files (supports includes, variables) - `golang/nats-server/conf/token.go` — Token types for config lexer ## Go Reference Files (Tests) - `golang/nats-server/conf/lex_test.go` - `golang/nats-server/conf/parse_test.go` - `golang/nats-server/server/config_check_test.go` ## .NET Implementation Files (Source) - `src/NATS.Server/Configuration/NatsConfLexer.cs` - `src/NATS.Server/Configuration/NatsConfParser.cs` - `src/NATS.Server/Configuration/NatsConfToken.cs` - `src/NATS.Server/Configuration/ConfigProcessor.cs` - `src/NATS.Server/Configuration/ConfigReloader.cs` - All other files in `src/NATS.Server/Configuration/` ## .NET Implementation Files (Tests) - `tests/NATS.Server.Tests/Configuration/` --- ## Gap Inventory ### golang/nats-server/conf/lex.go | Go Symbol | Go File:Line | Status | .NET Equivalent | Notes | |-----------|:-------------|--------|:----------------|-------| | `itemType` (type alias `int`) | `conf/lex.go:37` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:5` | Ported as `TokenType` enum | | `itemError` constant | `conf/lex.go:40` | PORTED | `NatsConfToken.cs:7` | `TokenType.Error` | | `itemNIL` constant | `conf/lex.go:41` | NOT_APPLICABLE | — | Go-only sentinel used in parser internal state; .NET uses `Token` default struct instead | | `itemEOF` constant | `conf/lex.go:42` | PORTED | `NatsConfToken.cs:8` | `TokenType.Eof` | | `itemKey` constant | `conf/lex.go:43` | PORTED | `NatsConfToken.cs:9` | `TokenType.Key` | | `itemText` constant | `conf/lex.go:44` | PORTED | `NatsConfToken.cs:10` | Added `TokenType.Text` and emit comment body text tokens in lexer comment state. | | `itemString` constant | `conf/lex.go:45` | PORTED | `NatsConfToken.cs:10` | `TokenType.String` | | `itemBool` constant | `conf/lex.go:46` | PORTED | `NatsConfToken.cs:11` | `TokenType.Bool` | | `itemInteger` constant | `conf/lex.go:47` | PORTED | `NatsConfToken.cs:12` | `TokenType.Integer` | | `itemFloat` constant | `conf/lex.go:48` | PORTED | `NatsConfToken.cs:13` | `TokenType.Float` | | `itemDatetime` constant | `conf/lex.go:49` | PORTED | `NatsConfToken.cs:14` | `TokenType.DateTime` | | `itemArrayStart` constant | `conf/lex.go:50` | PORTED | `NatsConfToken.cs:15` | `TokenType.ArrayStart` | | `itemArrayEnd` constant | `conf/lex.go:51` | PORTED | `NatsConfToken.cs:16` | `TokenType.ArrayEnd` | | `itemMapStart` constant | `conf/lex.go:52` | PORTED | `NatsConfToken.cs:17` | `TokenType.MapStart` | | `itemMapEnd` constant | `conf/lex.go:53` | PORTED | `NatsConfToken.cs:18` | `TokenType.MapEnd` | | `itemCommentStart` constant | `conf/lex.go:54` | PORTED | `NatsConfToken.cs:22` | .NET now emits `TokenType.Comment` followed by `TokenType.Text` for comment body, matching Go token stream semantics. | | `itemVariable` constant | `conf/lex.go:55` | PORTED | `NatsConfToken.cs:19` | `TokenType.Variable` | | `itemInclude` constant | `conf/lex.go:56` | PORTED | `NatsConfToken.cs:20` | `TokenType.Include` | | `stateFn` type | `conf/lex.go:84` | PORTED | `NatsConfLexer.cs:30` | Ported as `delegate LexState? LexState(NatsConfLexer lx)` — identical functional model | | `lexer` struct | `conf/lex.go:86` | PORTED | `NatsConfLexer.cs:6` | All fields: `_input`, `_start`, `_pos`, `_width`, `_line`, `_stack`, `_stringParts`, `_stringStateFn`, `_lstart`, `_ilstart` | | `item` struct | `conf/lex.go:113` | PORTED | `NatsConfToken.cs:24` | Ported as `readonly record struct Token(TokenType Type, string Value, int Line, int Position)` | | `(lx *lexer) nextItem()` | `conf/lex.go:120` | PORTED | `NatsConfLexer.cs:62` | Go uses a goroutine channel; .NET runs state machine eagerly in `Tokenize()` collecting all tokens into a `List` — semantically equivalent | | `lex(input string)` | `conf/lex.go:131` | PORTED | `NatsConfLexer.cs:48` | Ported as private constructor + `Tokenize()` factory | | `(lx *lexer) push()` | `conf/lex.go:143` | PORTED | `NatsConfLexer.cs:75` | `Push()` using `Stack` | | `(lx *lexer) pop()` | `conf/lex.go:147` | PORTED | `NatsConfLexer.cs:77` | `Pop()` | | `(lx *lexer) emit()` | `conf/lex.go:157` | PORTED | `NatsConfLexer.cs:87` | `Emit()` — identical logic for computing position and clearing stringParts | | `(lx *lexer) emitString()` | `conf/lex.go:166` | PORTED | `NatsConfLexer.cs:106` | `EmitString()` | | `(lx *lexer) addCurrentStringPart()` | `conf/lex.go:181` | PORTED | `NatsConfLexer.cs:125` | `AddCurrentStringPart()` | | `(lx *lexer) addStringPart()` | `conf/lex.go:186` | PORTED | `NatsConfLexer.cs:131` | `AddStringPart()` | | `(lx *lexer) hasEscapedParts()` | `conf/lex.go:192` | PORTED | `NatsConfLexer.cs:138` | `HasEscapedParts()` | | `(lx *lexer) next()` | `conf/lex.go:196` | PORTED | `NatsConfLexer.cs:144` | Updated lexer read path to decode UTF-16 runes (`Rune.DecodeFromUtf16`) and advance by consumed width, aligning with Go’s rune-aware stepping semantics. | | `(lx *lexer) ignore()` | `conf/lex.go:215` | PORTED | `NatsConfLexer.cs:160` | `Ignore()` | | `(lx *lexer) backup()` | `conf/lex.go:221` | PORTED | `NatsConfLexer.cs:166` | `Backup()` | | `(lx *lexer) peek()` | `conf/lex.go:229` | PORTED | `NatsConfLexer.cs:175` | `Peek()` | | `(lx *lexer) errorf()` | `conf/lex.go:238` | PORTED | `NatsConfLexer.cs:193` | Added formatted `Errorf(string, params object?[])` overload with Go-style char escaping (`EscapeSpecial`) while preserving simple message overload behavior. | | `lexTop` | `conf/lex.go:257` | PORTED | `NatsConfLexer.cs:202` | `LexTop` static method | | `lexTopValueEnd` | `conf/lex.go:296` | PORTED | `NatsConfLexer.cs:247` | `LexTopValueEnd` static method | | `lexBlockStart` | `conf/lex.go:321` | PORTED | `NatsConfLexer.cs:291` | `LexBlockStart` static method | | `lexBlockValueEnd` | `conf/lex.go:363` | PORTED | `NatsConfLexer.cs:338` | `LexBlockValueEnd` static method | | `lexBlockEnd` | `conf/lex.go:392` | PORTED | `NatsConfLexer.cs:388` | `LexBlockEnd` static method | | `lexKeyStart` | `conf/lex.go:422` | PORTED | `NatsConfLexer.cs:438` | `LexKeyStart` static method | | `lexDubQuotedKey` | `conf/lex.go:443` | PORTED | `NatsConfLexer.cs:469` | `LexDubQuotedKey` static method | | `lexQuotedKey` | `conf/lex.go:460` | PORTED | `NatsConfLexer.cs:494` | `LexQuotedKey` static method | | `(lx *lexer) keyCheckKeyword()` | `conf/lex.go:480` | PORTED | `NatsConfLexer.cs:519` | `KeyCheckKeyword()` — instance method | | `lexIncludeStart` | `conf/lex.go:495` | PORTED | `NatsConfLexer.cs:537` | `LexIncludeStart` static method | | `lexIncludeQuotedString` | `conf/lex.go:507` | PORTED | `NatsConfLexer.cs:549` | `LexIncludeQuotedString` static method | | `lexIncludeDubQuotedString` | `conf/lex.go:525` | PORTED | `NatsConfLexer.cs:569` | `LexIncludeDubQuotedString` static method | | `lexIncludeString` | `conf/lex.go:541` | PORTED | `NatsConfLexer.cs:589` | `LexIncludeString` static method | | `lexInclude` | `conf/lex.go:559` | PORTED | `NatsConfLexer.cs:611` | `LexInclude` static method | | `lexKey` | `conf/lex.go:587` | PORTED | `NatsConfLexer.cs:646` | `LexKey` static method | | `lexKeyEnd` | `conf/lex.go:601` | PORTED | `NatsConfLexer.cs:671` | `LexKeyEnd` static method | | `lexValue` | `conf/lex.go:621` | PORTED | `NatsConfLexer.cs:695` | `LexValue` static method | | `lexArrayValue` | `conf/lex.go:665` | PORTED | `NatsConfLexer.cs:745` | `LexArrayValue` static method | | `lexArrayValueEnd` | `conf/lex.go:696` | PORTED | `NatsConfLexer.cs:788` | `LexArrayValueEnd` static method | | `lexArrayEnd` | `conf/lex.go:723` | PORTED | `NatsConfLexer.cs:832` | `LexArrayEnd` static method | | `lexMapKeyStart` | `conf/lex.go:732` | PORTED | `NatsConfLexer.cs:839` | `LexMapKeyStart` static method | | `lexMapQuotedKey` | `conf/lex.go:772` | PORTED | `NatsConfLexer.cs:906` | `LexMapQuotedKey` static method | | `lexMapDubQuotedKey` | `conf/lex.go:784` | PORTED | `NatsConfLexer.cs:925` | `LexMapDubQuotedKey` static method | | `lexMapKey` | `conf/lex.go:799` | PORTED | `NatsConfLexer.cs:944` | `LexMapKey` static method | | `lexMapKeyEnd` | `conf/lex.go:815` | PORTED | `NatsConfLexer.cs:972` | `LexMapKeyEnd` static method | | `lexMapValue` | `conf/lex.go:833` | PORTED | `NatsConfLexer.cs:990` | `LexMapValue` static method | | `lexMapValueEnd` | `conf/lex.go:850` | PORTED | `NatsConfLexer.cs:1013` | `LexMapValueEnd` static method | | `lexMapEnd` | `conf/lex.go:875` | PORTED | `NatsConfLexer.cs:1059` | `LexMapEnd` static method | | `(lx *lexer) isBool()` | `conf/lex.go:884` | PORTED | `NatsConfLexer.cs:1066` | `IsBool()` instance method | | `(lx *lexer) isVariable()` | `conf/lex.go:892` | PORTED | `NatsConfLexer.cs:1072` | `IsVariable()` instance method | | `lexQuotedString` | `conf/lex.go:906` | PORTED | `NatsConfLexer.cs:1088` | `LexQuotedString` static method | | `lexDubQuotedString` | `conf/lex.go:928` | PORTED | `NatsConfLexer.cs:1114` | `LexDubQuotedString` static method | | `lexString` | `conf/lex.go:951` | PORTED | `NatsConfLexer.cs:1146` | `LexString` static method | | `lexBlock` | `conf/lex.go:986` | PORTED | `NatsConfLexer.cs:1193` | `LexBlock` static method | | `lexStringEscape` | `conf/lex.go:1021` | PORTED | `NatsConfLexer.cs:1235` | `LexStringEscape` static method | | `lexStringBinary` | `conf/lex.go:1043` | PORTED | `NatsConfLexer.cs:1250` | `LexStringBinary` static method — uses `Convert.FromHexString` + `Latin1.GetString` | | `lexNumberOrDateOrStringOrIPStart` | `conf/lex.go:1065` | PORTED | `NatsConfLexer.cs:1276` | `LexNumberOrDateOrStringOrIPStart` static method | | `lexNumberOrDateOrStringOrIP` | `conf/lex.go:1079` | PORTED | `NatsConfLexer.cs:1292` | `LexNumberOrDateOrStringOrIP` static method | | `lexConvenientNumber` | `conf/lex.go:1106` | PORTED | `NatsConfLexer.cs:1333` | `LexConvenientNumber` static method | | `lexDateAfterYear` | `conf/lex.go:1124` | PORTED | `NatsConfLexer.cs:1354` | `LexDateAfterYear` static method | | `lexNegNumberStart` | `conf/lex.go:1152` | PORTED | `NatsConfLexer.cs:1385` | `LexNegNumberStart` static method | | `lexNegNumber` | `conf/lex.go:1165` | PORTED | `NatsConfLexer.cs:1401` | `LexNegNumber` static method | | `lexFloatStart` | `conf/lex.go:1182` | PORTED | `NatsConfLexer.cs:1424` | `LexFloatStart` static method | | `lexFloat` | `conf/lex.go:1193` | PORTED | `NatsConfLexer.cs:1435` | `LexFloat` static method | | `lexIPAddr` | `conf/lex.go:1210` | PORTED | `NatsConfLexer.cs:1454` | `LexIPAddr` static method | | `lexCommentStart` | `conf/lex.go:1222` | PORTED | `NatsConfLexer.cs:1467` | Emits `TokenType.Comment` and transitions into comment-body emission state. | | `lexComment` | `conf/lex.go:1231` | PORTED | `NatsConfLexer.cs:1474` | Emits `TokenType.Text` for comment body at end-of-line/EOF, matching Go lexer semantics. | | `lexSkip` | `conf/lex.go:1242` | PORTED | `NatsConfLexer.cs:1489` | `LexSkip` static method — identical logic | | `isNumberSuffix()` | `conf/lex.go:1250` | PORTED | `NatsConfLexer.cs:197` | `IsNumberSuffix()` static method | | `isKeySeparator()` | `conf/lex.go:1255` | PORTED | `NatsConfLexer.cs:195` | `IsKeySeparator()` static method | | `isWhitespace()` | `conf/lex.go:1261` | PORTED | `NatsConfLexer.cs:191` | `IsWhitespace()` static method | | `isNL()` | `conf/lex.go:1265` | PORTED | `NatsConfLexer.cs:193` | `IsNL()` static method | | `(itemType) String()` | `conf/lex.go:1269` | PORTED | — | Go's stringer is used for debugging; .NET `TokenType` is an enum (has `.ToString()` built in) — functionally equivalent | | `(item) String()` | `conf/lex.go:1309` | PORTED | — | Go debug helper; .NET `Token` is a record struct with auto-generated `ToString()` | | `escapeSpecial()` | `conf/lex.go:1313` | PORTED | `NatsConfLexer.cs:1495` | `EscapeSpecial()` static method — .NET version also handles `\r`, `\t`, and EOF | --- ### golang/nats-server/conf/parse.go | Go Symbol | Go File:Line | Status | .NET Equivalent | Notes | |-----------|:-------------|--------|:----------------|-------| | `_EMPTY_` constant | `conf/parse.go:40` | NOT_APPLICABLE | — | Go-only string constant alias for `""` | | `parser` struct | `conf/parse.go:42` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:115` | Ported as private `ParserState` class inside `NatsConfParser` with context stacks, key stacks, include depth, token stream, and pedantic key-token compatibility stack (`_itemKeys`). | | `Parse()` | `conf/parse.go:71` | PORTED | `NatsConfParser.cs:29` | `NatsConfParser.Parse(string)` — identical signature and semantics | | `ParseWithChecks()` | `conf/parse.go:80` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:42` | Added compatibility entry point that delegates to `Parse(...)` in .NET. | | `ParseFile()` | `conf/parse.go:89` | PORTED | `NatsConfParser.cs:40` | `NatsConfParser.ParseFile(string)` | | `ParseFileWithChecks()` | `conf/parse.go:103` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:54` | Added file-based compatibility entry point that delegates to `ParseFile(...)`. | | `cleanupUsedEnvVars()` | `conf/parse.go:119` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:96` | Added compatibility hook; no-op in .NET because digesting is based on raw bytes, not token-tree mutation. | | `ParseFileWithChecksDigest()` | `conf/parse.go:135` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:88` | Added pedantic parse+digest path that computes SHA-256 from canonical JSON encoding of parsed config tree (sorted object keys), matching Go's token-tree digest intent rather than raw-file bytes. | | `token` struct | `conf/parse.go:155` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:32` (`PedanticToken`) | Added pedantic token wrapper with value/line/position/used-variable/source-file metadata accessors. | | `(t *token) MarshalJSON()` | `conf/parse.go:162` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:47` | Added `PedanticToken.MarshalJson()` using `System.Text.Json`. | | `(t *token) Value()` | `conf/parse.go:166` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:49` | Added `PedanticToken.Value()`. | | `(t *token) Line()` | `conf/parse.go:170` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:51` | Added `PedanticToken.Line()`. | | `(t *token) IsUsedVariable()` | `conf/parse.go:174` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:53` | Added `PedanticToken.IsUsedVariable()`. | | `(t *token) SourceFile()` | `conf/parse.go:178` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:55` | Added `PedanticToken.SourceFile()`. | | `(t *token) Position()` | `conf/parse.go:182` | PORTED | `src/NATS.Server/Configuration/NatsConfToken.cs:57` | Added `PedanticToken.Position()`. | | `newParser()` | `conf/parse.go:186` | PORTED | `NatsConfParser.cs:105` | `ParserState` constructors | | `parse()` | `conf/parse.go:199` | PORTED | `NatsConfParser.cs:118` | `ParserState.Run()` — identical loop structure | | `parseEnv()` | `conf/parse.go:207` | PORTED | `NatsConfParser.cs:75` | `ParseEnvValue()` static method — same synthetic `pk=` trick | | `(p *parser) parse()` | `conf/parse.go:216` | PORTED | `NatsConfParser.cs:118` | `ParserState.Run()` | | `(p *parser) next()` | `conf/parse.go:238` | PORTED | `NatsConfParser.cs:142` | `ParserState.Next()` | | `(p *parser) pushContext()` | `conf/parse.go:242` | PORTED | `NatsConfParser.cs:152` | `PushContext()` | | `(p *parser) popContext()` | `conf/parse.go:247` | PORTED | `NatsConfParser.cs:158` | `PopContext()` | | `(p *parser) pushKey()` | `conf/parse.go:258` | PORTED | `NatsConfParser.cs:171` | `PushKey()` | | `(p *parser) popKey()` | `conf/parse.go:262` | PORTED | `NatsConfParser.cs:173` | `PopKey()` | | `(p *parser) pushItemKey()` | `conf/parse.go:272` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:214` | Added pedantic key-token stack helper in parser state. | | `(p *parser) popItemKey()` | `conf/parse.go:276` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:216` | Added pedantic key-token pop helper; synchronized with map assignments in `SetValue()`. | | `(p *parser) processItem()` | `conf/parse.go:286` | PORTED | `NatsConfParser.cs:205` | `ProcessItem()` — handles all token types including variable, include, map, array | | `(p *parser) lookupVariable()` | `conf/parse.go:462` | PORTED | `NatsConfParser.cs:344` | `ResolveVariable()` — block scoping, env var lookup, cycle detection, bcrypt prefix all ported | | `(p *parser) setValue()` | `conf/parse.go:500` | PORTED | `NatsConfParser.cs:185` | `SetValue()` — array and map context handling | | `pkey` constant | `conf/parse.go:452` | PORTED | `NatsConfParser.cs:77` | Used in `ParseEnvValue` synthetic input (`"pk={value}"`) | | `bcryptPrefix` constant | `conf/parse.go:455` | PORTED | `src/NATS.Server/Configuration/NatsConfParser.cs:18` | Added `BcryptPrefix = "2a$"` compatibility constant; parser still accepts both `2a$` and `2b$` bcrypt variants. | --- ### golang/nats-server/conf/token.go (does not exist) The `token.go` file listed in the gap analysis instructions does not exist in the Go source tree. The `item` and `itemType` declarations live in `lex.go`. The `token` struct (pedantic wrapper) lives in `parse.go`. The .NET `NatsConfToken.cs` consolidates both the token type enum (`TokenType`) and the token value record (`Token`). --- ### .NET-only Configuration Files (no direct Go counterpart in conf/) These .NET files port functionality from `golang/nats-server/server/opts.go` and `golang/nats-server/server/reload.go` which are tracked under the Core Server category, but the implementations live in the Configuration folder: | .NET File | Go Reference | Status | Notes | |-----------|:-------------|--------|-------| | `src/NATS.Server/Configuration/ConfigProcessor.cs` | `server/opts.go` (processConfigFileLine, ~line 1050) | PORTED | Maps parsed dict to `NatsOptions`. Covers: listen, port, host, logging, limits, monitoring, TLS, auth, cluster, gateway, leafnode, JetStream, MQTT config keys | | `src/NATS.Server/Configuration/ConfigReloader.cs` | `server/reload.go` | PORTED | `Diff()`, `Validate()`, `MergeCliOverrides()`, `ApplyDiff()`, `ReloadAsync()`, `ReloadFromOptionsAsync()`, `ApplyClusterConfigChanges()`, `ApplyLoggingChanges()`, `PropagateAuthChanges()`, `ReloadTlsCertificates()`, `ReloadTlsCertificate()`, `ApplyJetStreamConfigChanges()` | | `src/NATS.Server/Configuration/IConfigChange.cs` | `server/reload.go:42–74` | PORTED | `IConfigChange` interface + `ConfigChange` implementation | | `src/NATS.Server/Configuration/ClusterOptions.cs` | `server/opts.go` (ClusterOpts) | PORTED | Cluster options struct | | `src/NATS.Server/Configuration/GatewayOptions.cs` | `server/opts.go` (GatewayOpts, RemoteGatewayOpts) | PORTED | Gateway options + `RemoteGatewayOptions` | | `src/NATS.Server/Configuration/LeafNodeOptions.cs` | `server/opts.go` (LeafNodeOpts, RemoteLeafOpts) | PORTED | LeafNode options + `RemoteLeafOptions` | | `src/NATS.Server/Configuration/JetStreamOptions.cs` | `server/opts.go` (JetStreamConfig) | PORTED | JetStream options struct | | `src/NATS.Server/Configuration/RouteCompression.cs` | `server/opts.go` (Compression enum) | PORTED | `RouteCompression` enum (None, S2) | | `src/NATS.Server/Configuration/SignalHandler.cs` | `server/signal_unix.go` | PORTED | SIGHUP handler via `PosixSignalRegistration` | --- ### conf/fuzz.go | Go Symbol | Go File:Line | Status | .NET Equivalent | Notes | |-----------|:-------------|--------|:----------------|-------| | `Fuzz()` | `conf/fuzz.go:18` | NOT_APPLICABLE | — | Go fuzz test entry point (`//go:build gofuzz` build tag). .NET has its own fuzzing infrastructure (SharpFuzz / libFuzzer) but no equivalent fuzz target exists. Low priority. | --- ## 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/Configuration/ -name '*.cs' -type f -exec cat {} + | wc -l # Re-count .NET test LOC for this module find tests/NATS.Server.Tests/Configuration/ -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 | Executed configuration batch 4: upgraded `ParseFileWithChecksDigest` to compute digest from canonicalized parsed config tree (sorted-key JSON) and added targeted digest behavior assertions in `ConfigPedanticParityBatch1Tests`. Reclassified `ParseFileWithChecksDigest` from PARTIAL to PORTED. | codex | | 2026-02-25 | File created with LLM analysis instructions | auto | | 2026-02-25 | Full gap inventory completed: read all Go source files (lex.go, parse.go) and all .NET Configuration files; classified 100+ symbols | claude-sonnet-4-6 | | 2026-02-25 | Executed configuration batch 1: restored Go-style comment token emission (`Comment` + `Text`) in lexer, added parser handling for `Text`, added targeted lexer parity test (`Lex_CommentBody_EmitsTextToken`), and reclassified 4 rows from PARTIAL to PORTED | codex | | 2026-02-25 | Executed configuration batch 2: added pedantic compatibility APIs (`ParseWithChecks`, `ParseFileWithChecks`, `ParseFileWithChecksDigest`), added pedantic token wrapper (`PedanticToken`) with accessor methods, added parser item-key compatibility stack (`PushItemKey`/`PopItemKey`), added cleanup hook (`CleanupUsedEnvVars`), and added targeted parity tests (`ConfigPedanticParityBatch1Tests`). | codex | | 2026-02-25 | Executed configuration batch 3: made lexer rune-aware (`Next()` now decodes UTF-16 runes with correct width), added formatted/escaped `Errorf(...)` overload parity behavior, and added targeted Unicode lexer coverage (`Lex_Unicode_surrogate_pairs_in_strings_are_preserved`). Reclassified 2 rows from PARTIAL to PORTED. | codex |