# Batch 23 Routes Implementation Plan

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

**Goal:** Port and verify Batch 23 (`Routes`) by implementing 52 deferred route features from `server/route.go` and replacing/verifying the 5 mapped route tests with real behavioral coverage.

**Architecture:** Implement route behavior in focused partials for `ClientConnection` and `NatsServer`, plus a small `RouteHandler` helper surface for batch-mapped helper methods. Execute in three feature groups (18/14/20 IDs), each with strict per-feature verification loops and group gates, then run the mapped test wave and only promote features `complete -> verified` after all related route regression tests are green.

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

**Design doc:** `docs/plans/2026-02-27-batch-23-routes-design.md`

---

## Batch 23 Scope

- Batch ID: `23`
- Name: `Routes`
- Dependencies: `16`, `18`
- Go source: `golang/nats-server/server/route.go`
- Features: `52`
- Tests: `5`

Reference commands:

```bash
dotnet run --project tools/NatsNet.PortTracker -- batch show 23 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- batch list --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
```

Primary production files:

- Create: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs`
- Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.InfoAndPerms.cs`
- Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Subscriptions.cs`
- Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Connections.cs`
- Create: `dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs`
- Modify (as needed): `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Lifecycle.cs`
- Modify (as needed): `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/IProtocolHandler.cs`
- Modify (as needed): `dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProtocolParser.cs`
- Modify (as needed): `dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteTypes.cs`

Mapped test file:

- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs`

Related regression test files:

- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProtocolParserTests.cs`
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ServerTests.cs`
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/ServerLifecycleStubFeaturesTests.cs`

---

## MANDATORY VERIFICATION PROTOCOL

> **NON-NEGOTIABLE:** Every Batch 23 feature/test update must follow this protocol.

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

1. Read the tracked feature metadata and Go source before coding:

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature show <feature_id> --db porting.db
# then open golang/nats-server/server/route.go at go_line_number..(go_line_number + go_line_count)
```

2. Implement the mapped C# behavior in the planned file(s) without placeholders.
3. Build immediately after each feature (or tightly coupled pair):

```bash
dotnet build dotnet/
```

4. Run the smallest related tests immediately:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ProtocolParserTests|FullyQualifiedName~ServerTests|FullyQualifiedName~ServerLifecycleStubFeaturesTests|FullyQualifiedName~RouteHandlerTests"
```

5. Record evidence (feature ID, build result, test result) before moving on.
6. If red, fix first. Do not stack unresolved failures.

### Stub Detection Check (REQUIRED after every feature group and test wave)

Run these checks before any status promotion:

```bash
# 1) Forbidden stub markers
grep -R -n -E "(NotImplementedException|TODO|PLACEHOLDER)" \
  dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.InfoAndPerms.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Subscriptions.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Connections.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs

# 2) Empty method bodies in mapped feature files
grep -R -n -E "^[[:space:]]*(public|internal|private|protected)[^{;=]*\)[[:space:]]*\{[[:space:]]*\}$" \
  dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.InfoAndPerms.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Subscriptions.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Connections.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs

# 3) Fake ImplBacklog placeholders
grep -n -E "(var goFile = \"server/|ShouldContain\(\"Should\"\)|ShouldNotBeNullOrWhiteSpace\(\))" \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
```

Any hit must be removed or explicitly deferred. No exceptions.

### Build Gate (REQUIRED after each feature group)

```bash
dotnet build dotnet/
```

`Build succeeded` is required before moving any group features to `complete`.

### Test Gate (REQUIRED before any `complete -> verified` promotion)

All related route tests must pass:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Protocol.ProtocolParserTests"
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ServerTests"
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.Server.ServerLifecycleStubFeaturesTests"
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.RouteHandlerTests"
```

All 5 Batch 23 mapped tests must pass before any Batch 23 feature is marked `verified`.

### Status Update Protocol (REQUIRED)

- Max `15` IDs per `feature batch-update` or `test batch-update` command.
- Required progression:
  - `deferred -> stub` when active work begins.
  - `stub -> complete` only after clean stub checks + build gate.
  - `complete -> verified` only after global route test gate passes.
- Evidence required for each update chunk:
  - successful build output,
  - successful related test output,
  - clean stub scan output,
  - explicit ID list and reason.

Status command templates:

```bash
# features (<=15 IDs)
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<comma-separated up to 15 IDs>" --set-status <stub|complete|verified> --db porting.db --execute

# tests (<=15 IDs)
dotnet run --project tools/NatsNet.PortTracker -- \
  test batch-update --ids "<comma-separated up to 15 IDs>" --set-status <stub|complete|verified> --db porting.db --execute
```

### Checkpoint Protocol (REQUIRED between tasks)

After each task (every feature group and the test wave):

```bash
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/

git add dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog porting.db
git commit -m "<batch23 checkpoint message>"
```

Do not start the next task until this checkpoint is complete.

### If You Get Stuck (REQUIRED)

1. Stop on the blocked ID.
2. Remove partial placeholder code (do not leave stubs).
3. Mark blocked item deferred with explicit reason:

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature update <id> --status deferred --override "blocked: <specific reason>" --db porting.db
# or
dotnet run --project tools/NatsNet.PortTracker -- test update <id> --status deferred --override "blocked: <specific reason>" --db porting.db
```

4. Continue to the next unblocked ID.
5. Never write fake-pass code or tests to bypass blockers.

---

## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)

### Forbidden Patterns

These patterns are forbidden in Batch 23 feature and test work:

- `throw new NotImplementedException()` in mapped methods
- Empty method bodies for mapped route features
- `// TODO` or `// PLACEHOLDER` in mapped route code paths
- Trivial default-return placeholders for non-trivial route logic (`return null`, `return false`, `return 0`, `return string.Empty`)
- ImplBacklog placeholder tests that only assert string literals (for example `"...".ShouldContain("Should")`)
- Test bodies that do not exercise route production code

### Hard Limits

- Maximum `20` features per feature group
- Maximum `15` IDs per status update command
- One feature group active at a time
- Zero unresolved stub-scan hits in touched Batch 23 files
- Mandatory checkpoint (full build + full test + commit) between tasks

---

## Feature Groups (<=20 IDs each)

### Group 1 (18 IDs): Route protocol and info/perms foundation

IDs:

`2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2908,2909,2910,2911,2912,2913`

Focus:

- Account SUB/UNSUB handling and reply-sub cleanup
- Routed args parsing and inbound routed message setup
- Route CONNECT and route INFO processing
- Route compression negotiation and remote permission update
- Implicit route filtering/forwarding and import/export permission checks

Target files:

- `ClientConnection.Routes.cs`
- `NatsServer.Routes.InfoAndPerms.cs`
- `Routes/RouteHandler.cs`

### Group 2 (14 IDs): Remote route subs and sub-proto fanout

IDs:

`2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927`

Focus:

- Routed-sub key/account extraction
- Remote sub/unsub parsing and state mutation
- Route SUB/UNSUB protocol buffer generation
- Sending full subscription interest to a route
- Route object creation and delayed-info decision helper

Target files:

- `ClientConnection.Routes.cs`
- `NatsServer.Routes.Subscriptions.cs`
- `Routes/RouteHandler.cs`

### Group 3 (20 IDs): Route lifecycle, solicitation, dedupe, iteration

IDs:

`2928,2929,2930,2931,2932,2933,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2947,2948,2950`

Focus:

- Initial route INFO JSON and `addRoute`
- Solicited/duplicate route detection and upgrade path
- Route import filters
- Route accept loop, start routing, connect/reconnect/validate
- Route connect processing, remove-all-except behavior
- Duplicate server-name check and route iterators by pool index

Target files:

- `ClientConnection.Routes.cs`
- `NatsServer.Routes.Connections.cs`
- `NatsServer.Lifecycle.cs` (for harmonization of remove/iterate paths)
- `Routes/RouteHandler.cs`

---

## Mapped Test Wave (5 IDs)

IDs:

`2798,2822,2823,2844,2850`

Target file:

- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs`

Required behavior focus:

- Cluster advertise startup error behavior
- TLS route certificate implicit allow pass/fail behavior
- Origin cluster route msg arg parsing behavior
- Route compression behavior

---

## Task 1: Preflight and Batch Start

**Files:**

- Read: `docs/standards/dotnet-standards.md`
- Read: `docs/plans/2026-02-27-batch-23-routes-design.md`
- Read: `golang/nats-server/server/route.go`

**Step 1: Confirm batch context**

```bash
dotnet run --project tools/NatsNet.PortTracker -- batch show 23 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- batch list --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
```

**Step 2: Start batch**

```bash
dotnet run --project tools/NatsNet.PortTracker -- batch start 23 --db porting.db
```

**Step 3: Baseline gate**

```bash
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
```

**Step 4: Checkpoint commit**

```bash
git add porting.db
git commit -m "chore(batch23): start routes batch"
```

---

## Task 2: Implement Feature Group 1 (18 IDs)

**Files:**

- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs`
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.InfoAndPerms.cs`
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs`

**Step 1: Move Group 1 to `stub` in chunks <=15**

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2908,2909,2910" --set-status stub --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2911,2912,2913" --set-status stub --db porting.db --execute
```

**Step 2: Execute Per-Feature Verification Loop for all 18 IDs**

**Step 3: Run Stub Detection Check + Build Gate + Group-related tests**

```bash
# mandatory stub checks (see protocol)
# then:
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ProtocolParserTests|FullyQualifiedName~RouteHandlerTests"
```

**Step 4: Move Group 1 IDs to `complete` in chunks <=15**

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2908,2909,2910" --set-status complete --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2911,2912,2913" --set-status complete --db porting.db --execute
```

**Step 5: Run Checkpoint Protocol and commit**

```bash
git commit -m "feat(batch23): implement route protocol and info/perms foundation"
```

---

## Task 3: Implement Feature Group 2 (14 IDs)

**Files:**

- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs`
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Subscriptions.cs`
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs`

**Step 1: Move Group 2 to `stub`**

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927" --set-status stub --db porting.db --execute
```

**Step 2: Execute Per-Feature Verification Loop for all 14 IDs**

**Step 3: Run Stub Detection Check + Build Gate + Group-related tests**

```bash
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ProtocolParserTests|FullyQualifiedName~ServerTests|FullyQualifiedName~RouteHandlerTests"
```

**Step 4: Move Group 2 IDs to `complete`**

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927" --set-status complete --db porting.db --execute
```

**Step 5: Run Checkpoint Protocol and commit**

```bash
git commit -m "feat(batch23): implement route subscription propagation and creation helpers"
```

---

## Task 4: Implement Feature Group 3 (20 IDs)

**Files:**

- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs`
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Connections.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Lifecycle.cs`
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs`

**Step 1: Move Group 3 to `stub` in chunks <=15**

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2928,2929,2930,2931,2932,2933,2935,2936,2937,2938,2939,2940,2941,2942,2943" --set-status stub --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2944,2945,2947,2948,2950" --set-status stub --db porting.db --execute
```

**Step 2: Execute Per-Feature Verification Loop for all 20 IDs**

**Step 3: Run Stub Detection Check + Build Gate + Group-related tests**

```bash
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ServerTests|FullyQualifiedName~ServerLifecycleStubFeaturesTests|FullyQualifiedName~RouteHandlerTests"
```

**Step 4: Move Group 3 IDs to `complete` in chunks <=15**

```bash
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2928,2929,2930,2931,2932,2933,2935,2936,2937,2938,2939,2940,2941,2942,2943" --set-status complete --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2944,2945,2947,2948,2950" --set-status complete --db porting.db --execute
```

**Step 5: Run Checkpoint Protocol and commit**

```bash
git commit -m "feat(batch23): implement route lifecycle, solicitation, dedupe, and iteration"
```

---

## Task 5: Implement and Verify Mapped Tests (5 IDs)

**Files:**

- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs`

**Step 1: Move mapped tests to `stub`**

```bash
dotnet run --project tools/NatsNet.PortTracker -- test batch-update --ids "2798,2822,2823,2844,2850" --set-status stub --db porting.db --execute
```

**Step 2: For each test ID (2798, 2822, 2823, 2844, 2850), run per-test loop**

```bash
dotnet run --project tools/NatsNet.PortTracker -- test show <test_id> --db porting.db
# port behavior from routes_test.go line range
# run single test:
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~<dotnet_method_name>"
```

**Step 3: Run Stub Detection Check on test file + class-level gate**

```bash
grep -n -E "(NotImplementedException|Assert\.True\(true\)|TODO|PLACEHOLDER|ShouldContain\(\"Should\"\))" \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs

dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.ImplBacklog.RouteHandlerTests"
```

**Step 4: Move mapped tests to `complete`, then `verified` only after full Test Gate**

```bash
dotnet run --project tools/NatsNet.PortTracker -- test batch-update --ids "2798,2822,2823,2844,2850" --set-status complete --db porting.db --execute
```

**Step 5: Run full Route Test Gate from protocol section and promote statuses**

```bash
# tests verified
dotnet run --project tools/NatsNet.PortTracker -- test batch-update --ids "2798,2822,2823,2844,2850" --set-status verified --db porting.db --execute

# features verified in chunks <=15
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2908,2909,2910" --set-status verified --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925" --set-status verified --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2926,2927,2928,2929,2930,2931,2932,2933,2935,2936,2937,2938,2939,2940,2941" --set-status verified --db porting.db --execute
dotnet run --project tools/NatsNet.PortTracker -- feature batch-update --ids "2942,2943,2944,2945,2947,2948,2950" --set-status verified --db porting.db --execute
```

**Step 6: Run Checkpoint Protocol and commit**

```bash
git commit -m "test(batch23): port and verify mapped route tests"
```

---

## Task 6: Batch Closure and Reporting

**Files:**

- Modify: `porting.db`
- Generate: `reports/current.md`

**Step 1: Final build + full unit test sweep**

```bash
dotnet build dotnet/
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
```

**Step 2: Final Batch 23 stub audit**

```bash
grep -R -n -E "(NotImplementedException|TODO|PLACEHOLDER)" \
  dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.Routes.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.InfoAndPerms.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Subscriptions.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Routes.Connections.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/Routes/RouteHandler.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
```

**Step 3: Verify batch status and complete batch**

```bash
dotnet run --project tools/NatsNet.PortTracker -- batch show 23 --db porting.db
dotnet run --project tools/NatsNet.PortTracker -- batch complete 23 --db porting.db
```

**Step 4: Generate report and final commit**

```bash
./reports/generate-report.sh
git add dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog porting.db reports/
git commit -m "feat(batch23): complete routes implementation and verification"
```
