Files
natsnet/docs/plans/2026-02-26-phase-6-porting.md
Joseph Doherty b335230498 chore: scaffold .NET solution structure for Phase 6
Creates the four-project .NET 10 solution (ZB.MOM.NatsNet.slnx):
- ZB.MOM.NatsNet.Server: main library with MEL, BCrypt.Net-Next, IronSnappy
- ZB.MOM.NatsNet.Server.Host: console host with Serilog + Microsoft.Extensions.Hosting
- ZB.MOM.NatsNet.Server.Tests: xUnit 2.9 / Shouldly / NSubstitute / BenchmarkDotNet
- ZB.MOM.NatsNet.Server.IntegrationTests: same test stack, separate project

Also adds Phase 6 porting plan and task-tracking JSON.
2026-02-26 08:03:21 -05:00

742 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Phase 6: Initial Porting Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:executing-plans to implement this plan task-by-task.
**Goal:** Port all 3632 Go features and 3257 tests across 12 modules from the Go NATS server to idiomatic .NET 10 C#, working bottom-up through the dependency graph.
**Architecture:** Port leaf modules (11 small modules, 279 features total) in parallel first, then tackle the server module (3394 features) in functional batches. The `dependency ready` command drives porting order. Every feature gets a stub before implementation; tests are ported alongside.
**Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, Microsoft.Extensions.Logging, Serilog, System.IO.Pipelines, BCrypt.Net-Next, IronSnappy, Tpm2Lib
---
## Dependency Graph Summary
```
Leaf modules (all unblocked — port in parallel):
ats module 1 4 features, 3 tests → AccessTimeService
avl module 2 36 features, 16 tests → SequenceSet (AVL tree)
certidp module 3 14 features, 2 tests → CertificateIdentityProvider
certstore module 4 36 features, 0 tests → CertificateStore
elastic module 5 5 features, 0 tests → ElasticEncoding
gsl module 6 26 features, 21 tests → GenericSubjectList
pse module 7 28 features, 3 tests → ProcessStatsProvider
stree module 9 101 features, 59 tests → SubjectTree
sysmem module 10 9 features, 0 tests → SystemMemory
thw module 11 12 features, 14 tests → TimeHashWheel
tpm module 12 8 features, 2 tests → TpmKeyProvider
Server module (blocked on all leaf modules):
server module 8 3394 features, ~3137 tests → NatsServer (347K Go LOC)
```
---
## TDD Porting Pattern (repeat for every feature)
1. `dotnet run --project tools/NatsNet.PortTracker -- feature update <id> --status stub --db porting.db`
2. Write failing test (translate Go test, Shouldly assertions, xUnit `[Fact]`/`[Theory]`)
3. Run test: confirm FAIL
4. Implement feature: idiomatic C# from Go source (coordinates in `feature show <id>`)
5. Run test: confirm PASS
6. `dotnet run --project tools/NatsNet.PortTracker -- feature update <id> --status complete --db porting.db`
After all features in a module: `dotnet run --project tools/NatsNet.PortTracker -- module update <id> --status complete --db porting.db`
---
## Go→.NET Translation Reference
| Go pattern | .NET equivalent |
|-----------|-----------------|
| `goroutine` + `channel` | `Task` + `Channel<T>` or `async/await` |
| `sync.Mutex` | `lock` or `SemaphoreSlim` |
| `sync.RWMutex` | `ReaderWriterLockSlim` |
| `sync.WaitGroup` | `Task.WhenAll` or `CountdownEvent` |
| `defer` | `try/finally` or `using` |
| `interface{}` / `any` | `object` or generics |
| `[]byte` | `byte[]`, `ReadOnlySpan<byte>`, or `ReadOnlyMemory<byte>` |
| `map[K]V` | `Dictionary<K,V>` or `ConcurrentDictionary<K,V>` |
| `error` return | Exceptions or `Result<T>` |
| `panic/recover` | Exceptions |
| `select` on channels | `Task.WhenAny` or `Channel<T>` reader |
| `context.Context` | `CancellationToken` |
| `io.Reader/Writer` | `Stream`, `PipeReader/PipeWriter` |
| `init()` | Static constructor or DI registration |
---
## Task 0: Create .NET Solution Structure
**Files to create:**
- `dotnet/ZB.MOM.NatsNet.sln`
- `dotnet/src/ZB.MOM.NatsNet.Server/ZB.MOM.NatsNet.Server.csproj`
- `dotnet/src/ZB.MOM.NatsNet.Server.Host/ZB.MOM.NatsNet.Server.Host.csproj`
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ZB.MOM.NatsNet.Server.Tests.csproj`
- `dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ZB.MOM.NatsNet.Server.IntegrationTests.csproj`
**Step 1: Scaffold projects**
```bash
cd /Users/dohertj2/Desktop/natsnet/dotnet
dotnet new sln -n ZB.MOM.NatsNet
dotnet new classlib -n ZB.MOM.NatsNet.Server -o src/ZB.MOM.NatsNet.Server --framework net10.0
dotnet new console -n ZB.MOM.NatsNet.Server.Host -o src/ZB.MOM.NatsNet.Server.Host --framework net10.0
dotnet new xunit -n ZB.MOM.NatsNet.Server.Tests -o tests/ZB.MOM.NatsNet.Server.Tests --framework net10.0
dotnet new xunit -n ZB.MOM.NatsNet.Server.IntegrationTests -o tests/ZB.MOM.NatsNet.Server.IntegrationTests --framework net10.0
dotnet sln add src/ZB.MOM.NatsNet.Server/ZB.MOM.NatsNet.Server.csproj
dotnet sln add src/ZB.MOM.NatsNet.Server.Host/ZB.MOM.NatsNet.Server.Host.csproj
dotnet sln add tests/ZB.MOM.NatsNet.Server.Tests/ZB.MOM.NatsNet.Server.Tests.csproj
dotnet sln add tests/ZB.MOM.NatsNet.Server.IntegrationTests/ZB.MOM.NatsNet.Server.IntegrationTests.csproj
```
**Step 2: Configure server library .csproj**
Replace contents of `dotnet/src/ZB.MOM.NatsNet.Server/ZB.MOM.NatsNet.Server.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="*" />
<PackageReference Include="Microsoft.Extensions.Options" Version="*" />
<PackageReference Include="System.IO.Pipelines" Version="*" />
<PackageReference Include="BCrypt.Net-Next" Version="*" />
<PackageReference Include="IronSnappy" Version="*" />
</ItemGroup>
</Project>
```
Note: Tpm2Lib is Windows-only; add it in Task 11 for the tpm module with a conditional reference.
**Step 3: Configure Host .csproj**
Replace contents of `dotnet/src/ZB.MOM.NatsNet.Server.Host/ZB.MOM.NatsNet.Server.Host.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../ZB.MOM.NatsNet.Server/ZB.MOM.NatsNet.Server.csproj" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="*" />
<PackageReference Include="Serilog" Version="*" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="*" />
<PackageReference Include="Serilog.Sinks.Console" Version="*" />
</ItemGroup>
</Project>
```
**Step 4: Configure Tests .csproj**
Replace contents of `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ZB.MOM.NatsNet.Server.Tests.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../src/ZB.MOM.NatsNet.Server/ZB.MOM.NatsNet.Server.csproj" />
<PackageReference Include="xunit" Version="3.*" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />
<PackageReference Include="Shouldly" Version="*" />
<PackageReference Include="NSubstitute" Version="*" />
<PackageReference Include="BenchmarkDotNet" Version="*" />
</ItemGroup>
</Project>
```
Apply the same to `dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ZB.MOM.NatsNet.Server.IntegrationTests.csproj`.
**Step 5: Clean boilerplate, add placeholder Program.cs, verify build**
```bash
rm -f dotnet/src/ZB.MOM.NatsNet.Server/Class1.cs
# Program.cs for Host (placeholder)
# Write: Console.WriteLine("ZB.MOM.NatsNet.Server"); to Program.cs
dotnet build /Users/dohertj2/Desktop/natsnet/dotnet/ZB.MOM.NatsNet.sln
dotnet test /Users/dohertj2/Desktop/natsnet/dotnet/ZB.MOM.NatsNet.sln
```
Expected: build succeeds, 0 tests (or default xUnit tests pass).
**Step 6: Commit**
```bash
git add dotnet/
git commit -m "chore: scaffold .NET solution structure for Phase 6"
```
---
## Task 1: Port `avl` Module — SequenceSet
**Go source:** `golang/nats-server/server/avl/seqset.go` (678 LOC)
**Go tests:** `golang/nats-server/server/avl/seqset_test.go`, `norace_test.go`
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Internal/DataStructures/SequenceSet.cs`
**Tests:** `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/DataStructures/SequenceSetTests.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Internal.DataStructures`
**Features:** 36 (IDs 540) | **Tests:** 16 | **Module ID:** 2
**Step 1: Mark all stubs**
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 2 --db porting.db
```
**Step 2: Lookup source coordinates for key features**
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature show 5 --db porting.db # Insert (line 44)
dotnet run --project tools/NatsNet.PortTracker -- feature show 6 --db porting.db # Exists
dotnet run --project tools/NatsNet.PortTracker -- feature show 8 --db porting.db # Delete
dotnet run --project tools/NatsNet.PortTracker -- feature show 22 --db porting.db # Encode
dotnet run --project tools/NatsNet.PortTracker -- feature show 23 --db porting.db # Decode
```
**Step 3: Create the class skeleton**
Create `dotnet/src/ZB.MOM.NatsNet.Server/Internal/DataStructures/SequenceSet.cs`.
Key type mappings:
- `SequenceSet` struct → `public sealed class SequenceSet`
- `node` struct → `private sealed class Node`
- Go `uint64` → C# `ulong`
- Go pointer receivers on `node` → C# methods on `Node`
All methods: `throw new NotImplementedException()` initially.
**Step 4: Write failing tests**
Create `SequenceSetTests.cs` translating from `seqset_test.go`. Example:
```csharp
// Go: TestSeqSetBasics
[Fact]
public void SeqSetBasics_ShouldSucceed()
{
var ss = new SequenceSet();
ss.IsEmpty().ShouldBeTrue();
ss.Insert(1);
ss.Exists(1).ShouldBeTrue();
ss.Exists(2).ShouldBeFalse();
ss.Size().ShouldBe(1);
ss.Delete(1);
ss.IsEmpty().ShouldBeTrue();
}
```
Run: `dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~SequenceSetTests"`
Expected: FAIL with NotImplementedException.
**Step 5: Implement SequenceSet**
Port AVL tree logic from `seqset.go`. Critical Go→.NET:
- `uint64``ulong`
- nil checks → null checks
- `Range(f func(uint64, uint64) bool)``Range(Func<ulong, ulong, bool> f)`
- Encode/Decode using `ReadOnlySpan<byte>` and `BinaryPrimitives`
**Step 6: Run tests**
```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~SequenceSetTests"
```
Expected: all 16 tests pass.
**Step 7: Update DB**
```bash
for id in 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40; do
dotnet run --project tools/NatsNet.PortTracker -- feature update $id --status complete --db porting.db
done
dotnet run --project tools/NatsNet.PortTracker -- test list --module 2 --db porting.db
# mark each test complete
dotnet run --project tools/NatsNet.PortTracker -- module update 2 --status complete --db porting.db
```
**Step 8: Commit**
```bash
git add dotnet/
git commit -m "feat: port avl module - SequenceSet AVL tree"
```
---
## Task 2: Port `ats` Module — AccessTimeService
**Go source:** `golang/nats-server/server/ats/ats.go` (186 LOC)
**Go tests:** `golang/nats-server/server/ats/ats_test.go`
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Internal/AccessTimeService.cs`
**Tests:** `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/AccessTimeServiceTests.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Internal`
**Features:** IDs 14 | **Tests:** IDs 13 | **Module ID:** 1
Tracks access times; `init()` → static initialization. Follow TDD pattern.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 1 --db porting.db
# implement Register, Unregister, AccessTime, Init
for id in 1 2 3 4; do dotnet run --project tools/NatsNet.PortTracker -- feature update $id --status complete --db porting.db; done
dotnet run --project tools/NatsNet.PortTracker -- module update 1 --status complete --db porting.db
git commit -m "feat: port ats module - AccessTimeService"
```
---
## Task 3: Port `elastic` Module — ElasticEncoding
**Go source:** `golang/nats-server/server/elastic/elastic.go` (61 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Internal/ElasticEncoding.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Internal`
**Features:** 5 | **Tests:** 0 | **Module ID:** 5
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 5 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- feature list --module 5 --db porting.db
# implement features; no tests to port
dotnet run --project tools/NatsNet.PortTracker -- module update 5 --status complete --db porting.db
git commit -m "feat: port elastic module - ElasticEncoding"
```
---
## Task 4: Port `sysmem` Module — SystemMemory
**Go source:** `golang/nats-server/server/sysmem/mem_*.go` (platform-specific)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Internal/SystemMemory.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Internal`
**Features:** 9 | **Tests:** 0 | **Module ID:** 10
Use `System.Diagnostics.Process` and `GC.GetTotalMemory` for cross-platform memory. Mark platform-specific Go variants (BSD, Solaris, WASM, z/OS) as N/A with reason.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 10 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- feature list --module 10 --db porting.db
# implement; mark n/a for platform variants
dotnet run --project tools/NatsNet.PortTracker -- module update 10 --status complete --db porting.db
git commit -m "feat: port sysmem module - SystemMemory"
```
---
## Task 5: Port `thw` Module — TimeHashWheel
**Go source:** `golang/nats-server/server/thw/` (656 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Internal/TimeHashWheel.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Internal`
**Features:** 12 | **Tests:** 14 | **Module ID:** 11
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 11 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- test list --module 11 --db porting.db
# TDD: write tests first, then implement hash wheel
dotnet run --project tools/NatsNet.PortTracker -- module update 11 --status complete --db porting.db
git commit -m "feat: port thw module - TimeHashWheel"
```
---
## Task 6: Port `certidp` Module — CertificateIdentityProvider
**Go source:** `golang/nats-server/server/certidp/` (600 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Auth/CertificateIdentityProvider.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Auth`
**Features:** 14 | **Tests:** 2 | **Module ID:** 3
Use `System.Security.Cryptography.X509Certificates`.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 3 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- module update 3 --status complete --db porting.db
git commit -m "feat: port certidp module - CertificateIdentityProvider"
```
---
## Task 7: Port `certstore` Module — CertificateStore
**Go source:** `golang/nats-server/server/certstore/` (1197 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Auth/CertificateStore.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Auth`
**Features:** 36 | **Tests:** 0 | **Module ID:** 4
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 4 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- module update 4 --status complete --db porting.db
git commit -m "feat: port certstore module - CertificateStore"
```
---
## Task 8: Port `gsl` Module — GenericSubjectList
**Go source:** `golang/nats-server/server/gsl/` (936 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Subscriptions/GenericSubjectList.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Subscriptions`
**Features:** 26 | **Tests:** 21 | **Module ID:** 6
Performance-sensitive. Use `ReadOnlySpan<byte>` for subject matching.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 6 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- test list --module 6 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- module update 6 --status complete --db porting.db
git commit -m "feat: port gsl module - GenericSubjectList"
```
---
## Task 9: Port `pse` Module — ProcessStatsProvider
**Go source:** `golang/nats-server/server/pse/` (1150 LOC, platform-specific)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Internal/ProcessStatsProvider.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Internal`
**Features:** 28 | **Tests:** 3 | **Module ID:** 7
Use `System.Diagnostics.Process`. Mark Go-specific syscall wrappers N/A where replaced.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 7 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- module update 7 --status complete --db porting.db
git commit -m "feat: port pse module - ProcessStatsProvider"
```
---
## Task 10: Port `stree` Module — SubjectTree
**Go source:** `golang/nats-server/server/stree/` (3628 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Subscriptions/SubjectTree.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Subscriptions`
**Features:** 101 | **Tests:** 59 | **Module ID:** 9
Largest leaf module. Performance-critical NATS routing trie. Use `ReadOnlySpan<byte>` throughout.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 9 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- test list --module 9 --db porting.db
# write 59 tests first, implement trie, iterate until all pass
dotnet run --project tools/NatsNet.PortTracker -- module update 9 --status complete --db porting.db
git commit -m "feat: port stree module - SubjectTree"
```
---
## Task 11: Port `tpm` Module — TpmKeyProvider
**Go source:** `golang/nats-server/server/tpm/` (387 LOC)
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/Auth/TpmKeyProvider.cs`
**Namespace:** `ZB.MOM.NatsNet.Server.Auth`
**Features:** 8 | **Tests:** 2 | **Module ID:** 12
Add conditional Tpm2Lib reference (Windows-only). If unavailable on current platform, throw `PlatformNotSupportedException`.
```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update 0 --status stub --all-in-module 12 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- module update 12 --status complete --db porting.db
git commit -m "feat: port tpm module - TpmKeyProvider"
```
---
## Task 12: Verify Wave 1 (All Leaf Modules Complete)
```bash
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db | head -5
dotnet build /Users/dohertj2/Desktop/natsnet/dotnet/ZB.MOM.NatsNet.sln
dotnet test /Users/dohertj2/Desktop/natsnet/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
```
Expected: 11 modules complete, server module appears in `dependency ready`, build green.
---
## Task 13: Port Server Module — Batch A: Core Types
**Go sources:** `server/const.go`, `server/errors.go`, `server/errors_gen.go`, `server/proto.go`, `server/util.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Constants.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/NatsErrors.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProtocolConstants.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Internal/Utilities.cs`
```bash
dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db
# identify IDs for const/errors/proto/util features; stub them
dotnet build /Users/dohertj2/Desktop/natsnet/dotnet/ZB.MOM.NatsNet.sln
git commit -m "feat: port server core types (const, errors, proto, util)"
```
---
## Task 14: Port Server Module — Batch B: Options & Config
**Go sources:** `server/opts.go`, `server/reload.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Configuration/NatsServerOptions.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Configuration/NatsServerReload.cs`
```bash
git commit -m "feat: port server options and reload configuration"
```
---
## Task 15: Port Server Module — Batch C: Parser & Protocol
**Go sources:** `server/parser.go`, `server/ring.go`, `server/rate_counter.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/NatsParser.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Internal/RingBuffer.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Internal/RateCounter.cs`
Parser is performance-critical. Use `ReadOnlySpan<byte>` and `System.IO.Pipelines`.
```bash
git commit -m "feat: port server parser, ring buffer, rate counter"
```
---
## Task 16: Port Server Module — Batch D: Client & Connection
**Go sources:** `server/client.go`, `server/client_proxyproto.go`, `server/sendq.go`, `server/ipqueue.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Connections/NatsClient.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Connections/ProxyProtocolHandler.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Connections/SendQueue.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Internal/IpQueue.cs`
Use `Channel<T>` for send queue. All async I/O via `PipeWriter`/`PipeReader`.
```bash
git commit -m "feat: port server client, connection, send queue"
```
---
## Task 17: Port Server Module — Batch E: Auth & Security
**Go sources:** `server/auth.go`, `server/auth_callout.go`, `server/jwt.go`, `server/nkey.go`, `server/ciphersuites.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/AuthHandler.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/AuthCallout.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/JwtValidator.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/NkeyProvider.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/CipherSuiteMapper.cs`
```bash
git commit -m "feat: port server auth, JWT, nkeys, cipher suites"
```
---
## Task 18: Port Server Module — Batch F: Accounts & Events
**Go sources:** `server/accounts.go`, `server/events.go`, `server/dirstore.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/AccountManager.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Events/NatsEventBus.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/DirectoryAccountStore.cs`
```bash
git commit -m "feat: port server accounts, events, directory store"
```
---
## Task 19: Port Server Module — Batch G: Sublist & Subject Transform
**Go sources:** `server/sublist.go`, `server/subject_transform.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Subscriptions/SubList.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Subscriptions/SubjectTransform.cs`
Hot path. Use `ReadOnlySpan<byte>`, avoid allocations in `Match`.
```bash
git commit -m "feat: port server sublist and subject transform"
```
---
## Task 20: Port Server Module — Batch H: Clustering
**Go sources:** `server/route.go`, `server/gateway.go`, `server/leafnode.go`, `server/raft.go`, `server/sdm.go`, `server/scheduler.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Cluster/RouteHandler.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Cluster/GatewayHandler.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Cluster/LeafNodeHandler.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Cluster/RaftConsensus.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Cluster/StreamDomainManager.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Cluster/Scheduler.cs`
```bash
git commit -m "feat: port server clustering (routes, gateway, leaf nodes, raft)"
```
---
## Task 21: Port Server Module — Batch I: JetStream Core
**Go sources:** `server/jetstream.go`, `server/jetstream_api.go`, `server/jetstream_errors.go`, `server/jetstream_errors_generated.go`, `server/jetstream_events.go`, `server/jetstream_versioning.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamEngine.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamApi.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamEvents.cs`
```bash
git commit -m "feat: port JetStream core engine and API"
```
---
## Task 22: Port Server Module — Batch J: JetStream Storage
**Go sources:** `server/store.go`, `server/filestore.go`, `server/memstore.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/Storage/IMessageStore.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/Storage/FileMessageStore.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/Storage/MemoryMessageStore.cs`
Define `IMessageStore` from `store.go` first, then implement.
```bash
git commit -m "feat: port JetStream storage (file store, memory store)"
```
---
## Task 23: Port Server Module — Batch K: JetStream Streams & Consumers
**Go sources:** `server/stream.go`, `server/consumer.go`, `server/jetstream_batching.go`, `server/jetstream_cluster.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamManager.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/ConsumerManager.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/BatchProcessor.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamCluster.cs`
```bash
git commit -m "feat: port JetStream streams, consumers, batching, cluster"
```
---
## Task 24: Port Server Module — Batch L: Monitoring
**Go sources:** `server/monitor.go`, `server/monitor_sort_opts.go`, `server/msgtrace.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Monitoring/NatsMonitor.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Monitoring/MonitorSortOptions.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Monitoring/MessageTracer.cs`
`log.go` features → mark N/A: replaced by `Microsoft.Extensions.Logging` + Serilog.
```bash
git commit -m "feat: port server monitoring, message tracing (log.go → N/A)"
```
---
## Task 25: Port Server Module — Batch M: MQTT & WebSocket
**Go sources:** `server/mqtt.go`, `server/websocket.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/MqttHandler.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/WebSocketHandler.cs`
```bash
git commit -m "feat: port MQTT and WebSocket protocol handlers"
```
---
## Task 26: Port Server Module — Batch N: OCSP & TLS
**Go sources:** `server/ocsp.go`, `server/ocsp_peer.go`, `server/ocsp_responsecache.go`
**Targets:**
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/OcspValidator.cs`
- `dotnet/src/ZB.MOM.NatsNet.Server/Auth/OcspResponseCache.cs`
```bash
git commit -m "feat: port OCSP validation and response cache"
```
---
## Task 27: Port Server Module — Batch O: Platform-Specific & N/A
**Go sources:** `server/disk_avail_*.go`, `server/signal.go`, `server/signal_*.go`, `server/service.go`, `server/service_windows.go`
- Signal handling → mark N/A: replaced by `IHostApplicationLifetime`
- Windows service → port using `System.ServiceProcess`
- Disk availability → port using `System.IO.DriveInfo`; platform variants → N/A
```bash
git commit -m "feat: port platform-specific features, mark N/A where replaced"
```
---
## Task 28: Port Server Module — Batch P: Server Core
**Go source:** `server/server.go`
**Target:** `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.cs`
Main `Server` struct and lifecycle. Final piece of the server module.
```bash
dotnet run --project tools/NatsNet.PortTracker -- module update 8 --status complete --db porting.db
git commit -m "feat: port server core lifecycle - server module complete"
```
---
## Task 29: Final Verification & Close Phase 6
```bash
dotnet build /Users/dohertj2/Desktop/natsnet/dotnet/ZB.MOM.NatsNet.sln
dotnet test /Users/dohertj2/Desktop/natsnet/dotnet/ZB.MOM.NatsNet.sln
dotnet run --project tools/NatsNet.PortTracker -- dependency blocked --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- phase check 6 --db porting.db
# Close Gitea issues 39-44
for issue in 39 40 41 42 43 44; do
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/issues/$issue" \
-H "Content-Type: application/json" \
-H "Authorization: token $GITEA_TOKEN" \
-d '{"state":"closed"}'
done
# Close Phase 6 milestone
curl -s -X PATCH "https://gitea.dohertylan.com/api/v1/repos/dohertj2/natsnet/milestones/6" \
-H "Content-Type: application/json" \
-H "Authorization: token $GITEA_TOKEN" \
-d '{"state":"closed"}'
git commit -m "chore: complete phase 6 - initial porting complete"
```