# Batch 1 (Proto, Const, CipherSuites, NKey, JWT) Implementation Plan

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

**Goal:** Implement and verify all 10 Batch 1 feature mappings with audit-aligned method names and behavior-faithful .NET parity.

**Architecture:** Use a hybrid compatibility approach: add/align mapped methods required by PortTracker (`Init`, `WipeSlice`, `NonceRequiredInternal`, `Proto*`) while preserving existing callers via wrappers where needed. Execute in four feature groups with strict per-feature red/green loops, then close the batch via evidence-backed status updates.

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

**Design doc:** `docs/plans/2026-02-27-batch-1-proto-const-ciphersuites-nkey-jwt-design.md`

---

## Batch 1 Working Set

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

- **Group A (2 features):** `384`, `583`
- **Group B (2 features):** `1975`, `2441`
- **Group C (5 features):** `2593`, `2594`, `2595`, `2596`, `2597`
- **Group D (1 feature):** `2598`

Batch facts:

- Total features: `10`
- Total tracked tests: `0`
- Dependency batches: none

---

## MANDATORY VERIFICATION PROTOCOL

> **NON-NEGOTIABLE:** every feature in this batch must pass this loop before status advancement.

### What Counts as a Real Feature Verification

A feature is eligible for `verified` only when all are true:

1. Mapped .NET method exists on mapped class (`dotnet_class`.`dotnet_method`).
2. Behavior matches Go intent for the mapped function.
3. Related tests execute and pass (not merely discovered as zero tests).
4. No stub markers remain in touched feature/test files.
5. Build is green after the feature group.

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

1. Read exact Go source range from tracker mapping.
2. Write or adjust C# implementation in mapped class/method.
3. Write or update a focused test that exercises the behavior.
4. Run focused test(s):
   ```bash
   dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
     --filter "FullyQualifiedName~<ClassName>.<MethodOrScenario>" --verbosity normal
   ```
5. Verify summary shows at least 1 executed test and 0 failures.
6. Run build gate (`dotnet build dotnet/`) before promoting group statuses.

### Stub Detection Check (REQUIRED after each feature group)

Run against touched source and tests:

```bash
rg -n "NotImplementedException|throw new NotSupportedException\(" dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests
rg -n "TODO|PLACEHOLDER|Assert\.True\(true\)|Assert\.Pass\(|ShouldBe\(true\);$|^\s*\{\s*\}$" dotnet/tests/ZB.MOM.NatsNet.Server.Tests
```

Any hit in edited files blocks status updates until fixed or explicitly deferred.

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

```bash
dotnet build dotnet/
```

Required: build succeeds with 0 errors.

### Test Gate (REQUIRED before marking any feature `verified`)

- Run all related test classes for the group (existing + newly added).
- For this batch, related classes include at minimum:
  - `ZB.MOM.NatsNet.Server.Tests.Auth.CipherSuitesTests`
  - `ZB.MOM.NatsNet.Server.Tests.Auth.JwtProcessorTests`
  - `ZB.MOM.NatsNet.Server.Tests.Auth.JwtProcessorOperatorTests`
  - `ZB.MOM.NatsNet.Server.Tests.ServerTests` (or dedicated nonce test class)
  - `ZB.MOM.NatsNet.Server.Tests.Internal.ProtoWireTests` (new)

Run pattern:

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~<ClassName>" --verbosity normal
```

Required: all related class runs pass with `Failed: 0`.

### Status Update Protocol

- Use max 15 IDs per `feature batch-update` command.
- Never set `verified` without captured build + test evidence.
- Status flow per feature: `deferred/not_started -> stub -> complete -> verified`.
- Record evidence per update chunk (command + pass summary + files touched).

Commands (chunk size max 15):

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<ids>" --set-status complete --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "<ids>" --set-status verified --db porting.db --execute
```

If audit rejects a valid status, re-run with explicit reason:

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature update <id> --status verified --db porting.db --override "manual verification evidence: <short reason>"
```

### Checkpoint Protocol Between Tasks (REQUIRED)

After each task group (A/B/C/D), before starting the next:

1. Full build:
   ```bash
   dotnet build dotnet/
   ```
2. Full unit test suite:
   ```bash
   dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal
   ```
3. Confirm total summary is stable and no new failures introduced.
4. Commit the group before moving on.

---

## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)

### Forbidden Patterns

The following are forbidden in touched feature or test code:

- `throw new NotImplementedException()`
- Empty method bodies used as placeholders
- `TODO`, `PLACEHOLDER`, or similar deferred markers without status deferral
- Fake-pass tests (`Assert.True(true)`, `Assert.Pass()`, meaningless single assert)
- Dummy return values used to bypass behavior (`return default`, `return null`) without Go-equivalent logic

### Hard Limits

- Max `15` IDs per status update command.
- Max `1` feature group promoted per verification cycle.
- Mandatory build + related test evidence before `verified`.
- Mandatory checkpoint commit after each group.

### If You Get Stuck

Do **not** stub.

1. Leave/return feature status as `deferred`.
2. Add explicit tracker override reason describing the concrete blocker.
3. Commit only proven work.
4. Continue with next unblocked feature in the current group.

Example:

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature update <id> --status deferred --db porting.db --override "blocked: <specific runtime or API gap>"
```

---

### Task 1: Group A - Init Parity (Features 384, 583)

**Files:**

- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/CipherSuites.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ServerConstants.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/CipherSuitesTests.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ServerTests.cs` (or add focused constants test file)

**Step 1: Mark feature IDs as in-progress (`stub`)**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "384,583" --set-status stub --db porting.db --execute
```

**Step 2: Write failing tests for explicit init hooks**

Add tests asserting `CipherSuites.Init()` and `ServerConstants.Init()` are callable and idempotent.

**Step 3: Run focused tests and confirm FAIL**

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~CipherSuitesTests" --verbosity normal
```

**Step 4: Implement minimal production code to pass**

Add explicit mapped methods:

- `CipherSuites.Init()`
- `ServerConstants.Init()`

Both must be idempotent and preserve existing behavior.

**Step 5: Re-run focused tests and confirm PASS**

Run both related classes and confirm zero failures.

**Step 6: Run mandatory stub scan + build gate**

Use the protocol commands above.

**Step 7: Promote statuses with evidence**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "384,583" --set-status complete --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "384,583" --set-status verified --db porting.db --execute
```

**Step 8: Checkpoint (full build + full unit tests + commit)**

```bash
git add dotnet/src/ZB.MOM.NatsNet.Server/Auth/CipherSuites.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/ServerConstants.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/CipherSuitesTests.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ServerTests.cs \
        porting.db

git commit -m "feat(batch1): add init parity hooks for ciphers and constants"
```

---

### Task 2: Group B - JWT + NKey Nonce Helpers (Features 1975, 2441)

**Files:**

- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/JwtProcessor.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Listeners.cs`
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/AuthHandler.cs` (only if retaining compatibility wrapper)
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/JwtProcessorTests.cs`
- Modify/Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/NonceRequiredTests.cs` (or equivalent in `ServerTests.cs`)

**Step 1: Mark IDs as `stub`**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "1975,2441" --set-status stub --db porting.db --execute
```

**Step 2: Write failing tests**

- `JwtProcessor.WipeSlice` fills buffer with `'x'`.
- `NonceRequiredInternal` returns true for each Go condition and false otherwise.

**Step 3: Run focused tests and confirm FAIL**

Run `JwtProcessorTests` and nonce-focused tests.

**Step 4: Implement minimal code**

- Add `JwtProcessor.WipeSlice(Span<byte>)` and route existing call sites as needed.
- Implement `NatsServer.NonceRequiredInternal()` using:
  - `GetOpts().AlwaysEnableNonce`
  - `_nkeys?.Count > 0`
  - `_trustedKeys != null`
  - `_proxiesKeyPairs.Count > 0`

**Step 5: Re-run focused tests and confirm PASS**

**Step 6: Stub scan + build gate**

**Step 7: Promote statuses**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "1975,2441" --set-status complete --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "1975,2441" --set-status verified --db porting.db --execute
```

**Step 8: Checkpoint + commit**

```bash
git add dotnet/src/ZB.MOM.NatsNet.Server/Auth/JwtProcessor.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Listeners.cs \
        dotnet/src/ZB.MOM.NatsNet.Server/Auth/AuthHandler.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/JwtProcessorTests.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/NonceRequiredTests.cs \
        porting.db

git commit -m "feat(batch1): implement jwt wipe and nonce-required internal logic"
```

---

### Task 3: Group C - Proto Scan Helpers (Features 2593-2597)

**Files:**

- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Internal/ProtoWire.cs`
- Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ProtoWireTests.cs`

**Step 1: Mark IDs as `stub`**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "2593,2594,2595,2596,2597" --set-status stub --db porting.db --execute
```

**Step 2: Write failing tests for mapped scan methods**

Cover:

- valid/invalid tag decode
- unsupported wire type error
- insufficient data behavior
- overflow behavior in varint decode
- length-delimited size behavior

**Step 3: Run focused tests and confirm FAIL**

```bash
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ProtoWireTests" --verbosity normal
```

**Step 4: Implement minimal mapped methods**

Add mapped methods:

- `ProtoScanField`
- `ProtoScanTag`
- `ProtoScanFieldValue`
- `ProtoScanVarint`
- `ProtoScanBytes`

Use existing logic or direct forwards without changing behavior.

**Step 5: Re-run ProtoWire tests and confirm PASS**

**Step 6: Stub scan + build gate**

**Step 7: Promote statuses**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "2593,2594,2595,2596,2597" --set-status complete --db porting.db --execute

dotnet run --project tools/NatsNet.PortTracker -- \
  feature batch-update --ids "2593,2594,2595,2596,2597" --set-status verified --db porting.db --execute
```

**Step 8: Checkpoint + commit**

```bash
git add dotnet/src/ZB.MOM.NatsNet.Server/Internal/ProtoWire.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ProtoWireTests.cs \
        porting.db

git commit -m "feat(batch1): add mapped proto scan helpers with boundary tests"
```

---

### Task 4: Group D - Proto Varint Encode (Feature 2598)

**Files:**

- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Internal/ProtoWire.cs`
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ProtoWireTests.cs`

**Step 1: Mark ID as `stub`**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature update 2598 --status stub --db porting.db
```

**Step 2: Write failing tests for `ProtoEncodeVarint` boundaries**

Cover `1<<7`, `1<<14`, ..., `1<<63` edges and encode/decode round-trip with `ProtoScanVarint`.

**Step 3: Run focused tests and confirm FAIL**

**Step 4: Implement minimal code**

Add `ProtoEncodeVarint` mapped method (forward or primary implementation) with 10-byte max semantics matching Go.

**Step 5: Re-run focused tests and confirm PASS**

**Step 6: Stub scan + build gate**

**Step 7: Promote status**

```bash
dotnet run --project tools/NatsNet.PortTracker -- \
  feature update 2598 --status complete --db porting.db

dotnet run --project tools/NatsNet.PortTracker -- \
  feature update 2598 --status verified --db porting.db
```

**Step 8: Checkpoint + commit**

```bash
git add dotnet/src/ZB.MOM.NatsNet.Server/Internal/ProtoWire.cs \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ProtoWireTests.cs \
        porting.db

git commit -m "feat(batch1): implement proto varint encoder parity"
```

---

### Task 5: Batch 1 Final Verification and Closure

**Files:**

- Modify: `porting.db`
- Generate: `reports/current.md` (optional at end of batch)

**Step 1: Full regression gates**

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

Required: `Failed: 0`.

**Step 2: Final stub audit on touched files**

```bash
rg -n "NotImplementedException|TODO|PLACEHOLDER|Assert\.True\(true\)|Assert\.Pass\(" \
  dotnet/src/ZB.MOM.NatsNet.Server/Auth/CipherSuites.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/ServerConstants.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/Auth/JwtProcessor.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Listeners.cs \
  dotnet/src/ZB.MOM.NatsNet.Server/Internal/ProtoWire.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/CipherSuitesTests.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/JwtProcessorTests.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Server/NonceRequiredTests.cs \
  dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Internal/ProtoWireTests.cs
```

Required: no matches.

**Step 3: Audit feature mapping resolution**

```bash
dotnet run --project tools/NatsNet.PortTracker -- audit --type features --db porting.db
```

If dry-run is clean, apply:

```bash
dotnet run --project tools/NatsNet.PortTracker -- audit --type features --db porting.db --execute
```

**Step 4: Close batch**

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

**Step 5: Report + final commit**

```bash
./reports/generate-report.sh

git add dotnet/src/ZB.MOM.NatsNet.Server \
        dotnet/tests/ZB.MOM.NatsNet.Server.Tests \
        porting.db reports/current.md

git commit -m "feat(batch1): complete proto/const/ciphers/nkey/jwt feature set"
```
