Files
natsnet/docs/plans/2026-02-27-batch-1-proto-const-ciphersuites-nkey-jwt-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

485 lines
15 KiB
Markdown

# 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"
```