Files
natsnet/docs/plans/2026-02-27-batch-3-sendq-service-client-proxyproto-plan.md
Joseph Doherty b928be4f2f Add batch plans for batches 1-5 and 8 (rounds 1-3)
Generated design docs and implementation plans via Codex for:
- Batch 1: Proto, Const, CipherSuites, NKey, JWT
- Batch 2: Parser, Sublist, MemStore remainders
- Batch 3: SendQ, Service, Client ProxyProto
- Batch 4: Logging
- Batch 5: JetStream Errors
- Batch 8: Store Interfaces

All plans include mandatory verification protocol and anti-stub guardrails.
Updated batches.md with file paths and planned status.
2026-02-27 14:11:29 -05:00

17 KiB
Raw Blame History

Batch 3 (SendQ, Service, Client ProxyProto) Implementation Plan

For Codex: REQUIRED SUB-SKILL: Use executeplan to implement this plan task-by-task.

Goal: Implement and verify Batch 3s 18 features and 1 tracked test with Go-parity behavior, zero stub leakage, and evidence-backed PortTracker status updates.

Architecture: Execute Batch 3 in three feature groups (ProxyProto, SendQueue, Service) plus one tracked-test group. Reuse existing .NET proxy/service behavior where valid, add compatibility surfaces for mapped Batch 3 methods, and run strict per-feature verification loops before any status promotion.

Tech Stack: .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (porting.db)

Design doc: docs/plans/2026-02-27-batch-3-sendq-service-client-proxyproto-design.md


Batch 3 Working Set

Feature groups (max group size <= 20 features):

  • Group A - ProxyProto (8): 574, 575, 576, 577, 578, 579, 580, 581
  • Group B - SendQueue (3): 2971, 2972, 2973
  • Group C - Service (7): 3148, 3149, 3150, 3151, 3152, 3153, 3154
  • Tracked test (1): 2832

Batch facts:

  • Total features: 18
  • Total tracked tests: 1
  • Dependency: Batch 1
  • Go files: server/client_proxyproto.go, server/sendq.go, server/service.go, server/service_windows.go

dotnet is not on PATH in this environment. Use /usr/local/share/dotnet/dotnet in all commands.


MANDATORY VERIFICATION PROTOCOL

NON-NEGOTIABLE: Every feature and test in this plan must follow this protocol. Skipping steps is a plan violation.

What Counts as Real Verification

A feature or test can be marked verified only if all are true:

  1. Go source was reviewed for the mapped ID (feature show or test show + source lines).
  2. C# implementation/test contains real behavior (no placeholders/fake pass assertions).
  3. Related tests execute with non-zero discovery and pass.
  4. Group build gate is green.
  5. Stub detection checks are clean for touched files.

Per-Feature Verification Loop (REQUIRED for every feature ID)

  1. Read mapped Go source and intent:
    /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show <id> --db porting.db
    
  2. Write/adjust C# implementation in mapped target area.
  3. Build immediately after feature-level change:
    /usr/local/share/dotnet/dotnet build dotnet/
    
  4. Run related tests for that feature area.
  5. Confirm Passed > 0 and Failed = 0 before adding ID to verified candidates.

Per-Test Verification Loop (REQUIRED for test 2832)

  1. Read Go test source and dependent feature behavior:
    /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- test show 2832 --db porting.db
    
  2. Write the C# test first (real Arrange/Act/Assert, no placeholder asserts).
  3. Run the specific test filter and confirm it is discovered and passing.
  4. Run containing class filter and confirm cumulative pass summary.

Stub Detection Check (REQUIRED after each feature group and test group)

Run on touched files before any status updates:

# Forbidden markers in changed source/test files
git diff -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests | \
  grep -nE "^\+.*(NotImplementedException|TODO|PLACEHOLDER|Assert\.True\(true\)|Assert\.Pass\(|ShouldBe\(true\);)"

# Empty method bodies introduced in touched files
for f in $(git diff --name-only -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests | grep -E "\.cs$"); do
  grep -nE "(public|private|internal|protected).*\)\s*\{\s*\}" "$f";
done

Any match blocks status promotion until fixed or reclassified (deferred/n_a) with reason.

Build Gate (REQUIRED after each feature group)

/usr/local/share/dotnet/dotnet build dotnet/

Required: 0 errors.

Test Gate (REQUIRED before marking features verified)

All related tests for the active group must pass:

  • Group A (ProxyProto):
    /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
      --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol.ProxyProtocolTests" --verbosity normal
    
  • Group B (SendQueue):
    /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
      --filter "FullyQualifiedName~SendQueueTests" --verbosity normal
    
  • Group C (Service):
    /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
      --filter "FullyQualifiedName~SignalHandlerTests|FullyQualifiedName~ServiceManagerTests" --verbosity normal
    
  • Group D (tracked test):
    /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
      --filter "FullyQualifiedName~RoutePoolRouteStoredSameIndexBothSides_ShouldSucceed" --verbosity normal
    

Status Update Protocol

  • Maximum 15 IDs per batch-update call (hard cap).
  • Do not mark verified without evidence bundle (Go source reference, build output, related test output, stub-scan output).
  • Apply status in order: deferred/not_started -> stub -> complete -> verified.
  • Use n_a only with explicit technical justification.

Examples:

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status stub --db porting.db --execute

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status complete --db porting.db --execute

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status verified --db porting.db --execute

For blocked items:

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature update <id> --status deferred --db porting.db --override "blocked: <specific reason>"

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature update <id> --status n_a --db porting.db --override "n/a: <specific reason>"

Checkpoint Protocol Between Tasks (REQUIRED)

After each task group and before starting the next:

  1. Full build:
    /usr/local/share/dotnet/dotnet build dotnet/
    
  2. Full unit tests:
    /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
    
  3. Confirm no regressions introduced.
  4. Commit task-scoped changes (including porting.db) before proceeding.

ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)

Forbidden Patterns

These are forbidden in feature or test changes for Batch 3:

  • throw new NotImplementedException()
  • TODO / PLACEHOLDER markers in newly added code
  • Empty method body placeholders ({ }) for mapped features
  • Fake pass assertions (Assert.True(true), Assert.Pass(), meaningless sentinel assertions)
  • Default/null return used only to satisfy compiler with no Go-equivalent behavior
  • Test methods with no production call + no meaningful assertion

Hard Limits

  • Max 15 IDs per status update command.
  • Max 1 feature group promoted per verification cycle.
  • Mandatory build + related test gate before verified.
  • Mandatory stub scan before every status promotion.
  • Mandatory checkpoint commit between groups.

If You Get Stuck (REQUIRED behavior)

Do not stub and do not fake-pass.

  1. Keep item as deferred (or n_a only if genuinely non-applicable).
  2. Add explicit reason with --override in PortTracker.
  3. Commit only proven work.
  4. Continue with next unblocked ID.

Task 1: Group A - Proxy Protocol Features (574-581)

Files:

  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs
  • Create: dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.ProxyProto.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProxyProtocol.cs
  • Modify/Test: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProxyProtocolTests.cs

Step 1: Mark Group A features as stub

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status stub --db porting.db --execute

Step 2: Write/adjust failing tests first

Add coverage for any missing mapped behavior:

  • RemoteAddr mapped semantics
  • version detect wrappers
  • v1/v2 parser wrapper entry points
  • IPv4/IPv6 parse wrappers

Step 3: Run focused ProxyProto tests (expect fail first, then pass)

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~ProxyProtocolTests" --verbosity normal

Step 4: Implement minimal production parity

  • Add ClientConnection mapped method shims to existing parser core.
  • Keep parsing logic centralized in Protocol/ProxyProtocol.cs.

Step 5: Re-run focused tests until green

Use Step 3 command.

Step 6: Run stub detection + build gate

Run protocol checks.

Step 7: Promote statuses (complete, then verified)

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status complete --db porting.db --execute

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "574,575,576,577,578,579,580,581" --set-status verified --db porting.db --execute

Step 8: Checkpoint protocol + commit

git add dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.ProxyProto.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProxyProtocol.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProxyProtocolTests.cs \
        porting.db

git commit -m "feat(batch3): verify client proxy protocol feature group"

Task 2: Group B - SendQueue Features (2971-2973)

Files:

  • Create: dotnet/src/ZB.MOM.NatsNet.Server/SendQueue.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Accounts.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs
  • Create/Test: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SendQueueTests.cs

Step 1: Mark Group B features as stub

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "2971,2972,2973" --set-status stub --db porting.db --execute

Step 2: Write failing tests first

Cover at minimum:

  • NewSendQ creates queue and starts loop entry path
  • Send no-ops when queue is null/disposed
  • queued messages are copied and passed to internal client path

Step 3: Run focused SendQueue tests (expect fail first, then pass)

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~SendQueueTests" --verbosity normal

Step 4: Implement minimal SendQueue parity

  • Port newSendQ, internalLoop, send intent using IpQueue<T> + existing internal client APIs.
  • Replace Account.SendQueue placeholder with concrete type usage.

Step 5: Re-run focused tests until green

Use Step 3 command.

Step 6: Run stub detection + build gate

Run protocol checks.

Step 7: Promote statuses (complete, then verified)

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "2971,2972,2973" --set-status complete --db porting.db --execute

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "2971,2972,2973" --set-status verified --db porting.db --execute

Step 8: Checkpoint protocol + commit

git add dotnet/src/ZB.MOM.NatsNet.Server/SendQueue.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Accounts.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SendQueueTests.cs \
        porting.db

git commit -m "feat(batch3): implement send queue feature group"

Task 3: Group C - Service Features (3148-3154)

Files:

  • Create: dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.cs
  • Create (if needed): dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.Windows.cs
  • Modify: dotnet/src/ZB.MOM.NatsNet.Server/Internal/SignalHandler.cs
  • Create/Test: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ServiceManagerTests.cs
  • Modify/Test: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SignalHandlerTests.cs

Step 1: Mark Group C features as stub

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "3148,3149,3150,3151,3152,3153,3154" --set-status stub --db porting.db --execute

Step 2: Write failing tests first

Cover:

  • non-Windows Run behavior
  • non-Windows IsWindowsService behavior
  • service-name configuration behavior (if implemented)
  • Windows-only hooks either behaviorally verified or explicitly marked n_a

Step 3: Run focused service tests (expect fail first, then pass)

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~SignalHandlerTests|FullyQualifiedName~ServiceManagerTests" --verbosity normal

Step 4: Implement service parity layer

  • Add ServiceManager mapped surface.
  • For Windows-only features (3150-3154), choose one per-ID outcome based on evidence:
    • implemented wrapper (complete/verified), or
    • n_a with explicit reason tied to host-level WindowsService ownership.

Step 5: Re-run focused tests until green

Use Step 3 command.

Step 6: Run stub detection + build gate

Run protocol checks.

Step 7: Promote statuses with evidence

  • Use complete -> verified for implemented service features.
  • Use n_a for validated non-applicable Windows-host-only entries.
  • Keep max 7 IDs in this task update (below 15 cap).

Step 8: Checkpoint protocol + commit

git add dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/Internal/ServiceManager.Windows.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/Internal/SignalHandler.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ServiceManagerTests.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/SignalHandlerTests.cs \
        porting.db

git commit -m "feat(batch3): implement service feature group"

Task 4: Group D - Tracked Test 2832

Files:

  • Modify/Test: dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
  • Modify (only if required by real behavior): dotnet/src/ZB.MOM.NatsNet.Server/Routes/*

Step 1: Mark test 2832 as stub

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  test update 2832 --status stub --db porting.db

Step 2: Write real failing test first

Implement RoutePoolRouteStoredSameIndexBothSides_ShouldSucceed with actual route index/endpoint assertions mirroring Go intent.

Step 3: Run focused test and class gates

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~RoutePoolRouteStoredSameIndexBothSides_ShouldSucceed" --verbosity normal

/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
  --filter "FullyQualifiedName~RouteHandlerTests" --verbosity normal

Step 4: If infrastructure is missing, defer explicitly (do not stub)

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  test update 2832 --status deferred --db porting.db \
  --override "blocked: requires route-pool runtime topology not yet implemented in current server core"

Step 5: If test is green, promote to verified

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \
  test update 2832 --status verified --db porting.db

Step 6: Checkpoint protocol + commit

git add dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/Routes \
        porting.db

git commit -m "test(batch3): handle route pool same-index test"

Task 5: Batch 3 Closure

Files:

  • Modify: porting.db
  • Generate: reports/current.md (via report script)

Step 1: Verify batch state

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 3 --db porting.db

Required: all 18 features and test 2832 are verified/complete/n_a; unresolved blockers remain explicitly deferred with reason.

Step 2: Full regression gate

/usr/local/share/dotnet/dotnet build dotnet/
/usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal

Required: Failed: 0 for full unit test suite.

Step 3: Complete batch if eligible

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch complete 3 --db porting.db

Step 4: Validate summary + readiness

/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
/usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db

Step 5: Generate report and final commit

./reports/generate-report.sh

git add porting.db reports/current.md
git commit -m "chore(batch3): close sendq-service-proxyproto batch"