# Batch 9 (Auth, DirStore, OCSP Foundations) Implementation Plan > **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task. **Goal:** Implement and verify Batch 9 (`36` features + `10` tests) across auth pinned-cert checks, directory-store parity helpers, and OCSP monitor/peer foundations, with evidence-backed status updates. **Architecture:** Execute four bounded feature groups (8/12/7/9 IDs) and one mapped-test group. For every feature: read mapped Go source, implement minimal parity, build, run related tests, then promote status only after gates pass. For mapped auth-callout tests, enforce real behavioral verification; if infrastructure is missing, keep deferred with explicit blocker evidence. **Tech Stack:** .NET 10, C# latest, xUnit + Shouldly + NSubstitute, PortTracker CLI, SQLite (`porting.db`) **Design doc:** `docs/plans/2026-02-27-batch-9-auth-dirstore-ocsp-foundations-design.md` --- I'm using `writeplan` to create the implementation plan. ## Batch 9 Working Set Batch facts: - Batch ID: `9` - Dependencies: `4,6` - Features: `36` - Tests: `10` - Go files: `server/auth.go`, `server/dirstore.go`, `server/ocsp.go`, `server/ocsp_peer.go` Environment note: - `dotnet` is not on PATH in this workspace. Use `/usr/local/share/dotnet/dotnet` for all commands. Feature groups (max ~20 each): - **F1 (8):** `361,793,794,817,818,819,820,821` - **F2 (12):** `2443,2444,2445,2446,2447,2448,2457,2458,2459,2460,2461,2462` - **F3 (7):** `2450,2451,2452,2453,2454,2455,2456` - **F4 (9):** `2463,2464,2465,2466,2467,2468,2469,2470,2471` Test group: - **T1 (10):** `118,119,124,125,128,129,130,131,134,135` --- ## MANDATORY VERIFICATION PROTOCOL > **NON-NEGOTIABLE:** No Batch 9 feature/test may be marked `verified` unless this exact protocol is followed. ### Per-Feature Verification Loop (REQUIRED for every feature ID) 1. Read mapping + Go location: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show --db porting.db ``` 2. Read exact Go behavior in mapped file/line range. 3. Write C# parity in mapped .NET file/class. 4. Build immediately: ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` 5. Run related tests for that feature slice (examples in each task). 6. Only after build + related tests pass, add feature ID to promotion candidates. ### Per-Test Verification Loop (REQUIRED for every test ID) 1. Read mapping + Go test location: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- test show --db porting.db ``` 2. Implement/port real Arrange/Act/Assert behavior in mapped test method. 3. Run single mapped test method: ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~" --verbosity normal ``` 4. Require discovery and pass (`Passed: 1`, `Failed: 0`) before candidate promotion. ### Stub Detection Check (REQUIRED after each feature/test group) Run after each task, before any status promotion: ```bash # Forbidden placeholder markers in touched source/tests rg -n "NotImplementedException|TODO|PLACEHOLDER" \ dotnet/src/ZB.MOM.NatsNet.Server \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests # Empty method bodies in touched C# files for f in $(git diff --name-only -- '*.cs'); do rg -n "^\s*(public|private|internal|protected).*\)\s*\{\s*\}\s*$" "$f" done ``` Any match blocks status updates until fixed or explicitly deferred with reason. ### Build Gate (REQUIRED after each feature group) ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` Required: `0` build errors. ### Test Gate (REQUIRED before marking features verified) All related tests for current group must pass before any `verified` promotion. Baseline command template: ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "" --verbosity normal ``` ### Status Update Protocol (REQUIRED) - Maximum `15` IDs per `feature batch-update` or `test batch-update` command. - Required evidence for each update command: - latest build gate output - related test gate output - stub detection output - Status flow: - Features: `deferred -> stub -> complete -> verified` - Tests: `deferred -> stub -> verified` (or remain `deferred` with override reason) Command templates: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "" --set-status --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "" --set-status --db porting.db --execute ``` If audit disagrees: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update --status --db porting.db \ --override "verification evidence: " ``` ### Checkpoint Protocol Between Tasks (REQUIRED) After each task (F1/F2/F3/F4/T1), before moving on: 1. Full build: ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` 2. Full unit tests: ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` 3. Commit completed slice: ```bash git add porting.db git commit -m "feat(batch9): " ``` --- ## ANTI-STUB GUARDRAILS ### Forbidden Patterns Production code must not include: - `throw new NotImplementedException(...)` for Batch 9 mapped methods - empty mapped method bodies (`{ }`) - TODO placeholders in mapped method bodies - fake default returns (`return null;`, `return default;`, `return true;`) where Go behavior is non-trivial Test code must not include for `verified` status: - `Assert.True(true)` / unconditional pass assertions - tests that only assert method-name strings/constants - empty test bodies - single trivial assertion that does not exercise mapped behavior ### Hard Limits - Max `20` features per implementation task group - Max `15` IDs per status update command - No cross-group bulk verification in one cycle - Build gate required after each feature group - Test gate required before `verified` promotion - Mandatory checkpoint commit between task groups ### If You Get Stuck Do not stub and do not fake-pass. 1. Keep blocked feature/test as `deferred`. 2. Record concrete blocker using `--override`. 3. Capture failing command output as evidence. 4. Continue with next unblocked ID. Commands: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update --status deferred --db porting.db \ --override "blocked: " /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test update --status deferred --db porting.db \ --override "blocked: " ``` --- ### Task 1: Dependency Preflight and Batch Start **Files:** - Modify: `porting.db` **Step 1: Verify dependency batches are complete** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 4 --db porting.db /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 6 --db porting.db ``` **Step 2: Start Batch 9 only if dependencies are complete** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch start 9 --db porting.db ``` **Step 3: Run checkpoint protocol and commit preflight evidence** --- ### Task 2: Implement Feature Group F1 (Auth + DirStore + Expiration Heap Primitives) **IDs:** `361,793,794,817,818,819,820,821` **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Accounts/DirJwtStore.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Accounts/DirectoryStoreTests.cs` - Modify/Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ServerTests.cs` - Modify: `porting.db` **Step 1: Mark F1 as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "361,793,794,817,818,819,820,821" --set-status stub --db porting.db --execute ``` **Step 2: Write/adjust failing tests for pinned-cert and DirStore parity methods** **Step 3: Run focused tests and confirm FAIL first** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~DirectoryStoreTests|FullyQualifiedName~ServerTests" --verbosity normal ``` **Step 4: Implement mapped F1 methods using Per-Feature Verification Loop** **Step 5: Re-run focused tests and require PASS** Use same command as Step 3, require `Failed: 0`. **Step 6: Run Stub Detection + Build Gate + Test Gate** **Step 7: Promote F1 to `complete` then `verified`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "361,793,794,817,818,819,820,821" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "361,793,794,817,818,819,820,821" --set-status verified --db porting.db --execute ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 3: Implement Feature Group F2 (OCSP Monitor Core + Helper Functions) **IDs:** `2443,2444,2445,2446,2447,2448,2457,2458,2459,2460,2461,2462` **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/Ocsp/OcspTypes.cs` - Create: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/Ocsp/OcspHandler.cs` - Modify/Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/OcspResponseCacheTests.cs` - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/OcspFoundationTests.cs` - Modify: `porting.db` **Step 1: Mark F2 as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2443,2444,2445,2446,2447,2448,2457,2458,2459,2460,2461,2462" --set-status stub --db porting.db --execute ``` **Step 2: Add failing OCSP foundation tests (status selection, cert parsing, issuer lookup, status-string, response validity)** **Step 3: Run focused tests and confirm FAIL** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~OcspFoundationTests|FullyQualifiedName~OcspResponseCacheTests|FullyQualifiedName~CertificateIdentityProviderTests" --verbosity normal ``` **Step 4: Implement F2 methods with per-feature loop** **Step 5: Re-run focused tests and require PASS** Use same command as Step 3, require `Failed: 0`. **Step 6: Run Stub Detection + Build Gate + Test Gate** **Step 7: Promote F2 to `complete` then `verified`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2443,2444,2445,2446,2447,2448,2457,2458,2459,2460,2461,2462" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2443,2444,2445,2446,2447,2448,2457,2458,2459,2460,2461,2462" --set-status verified --db porting.db --execute ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 4: Implement Feature Group F3 (NatsServer OCSP Wiring/Lifecycle) **IDs:** `2450,2451,2452,2453,2454,2455,2456` **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Ocsp.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Init.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Lifecycle.cs` - Create/Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/NatsServerOcspTests.cs` - Modify: `porting.db` **Step 1: Mark F3 as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2450,2451,2452,2453,2454,2455,2456" --set-status stub --db porting.db --execute ``` **Step 2: Add failing server OCSP wiring tests (config discovery, monitor creation, store dir, reload/start behavior)** **Step 3: Run focused tests and confirm FAIL** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~NatsServerOcspTests|FullyQualifiedName~OcspFoundationTests" --verbosity normal ``` **Step 4: Implement F3 methods with per-feature loop** **Step 5: Re-run focused tests and require PASS** Use same command as Step 3, require `Failed: 0`. **Step 6: Run Stub Detection + Build Gate + Test Gate** **Step 7: Promote F3 to `complete` then `verified`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2450,2451,2452,2453,2454,2455,2456" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2450,2451,2452,2453,2454,2455,2456" --set-status verified --db porting.db --execute ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 5: Implement Feature Group F4 (OCSP Peer Parsing + TLS Plug/Validation) **IDs:** `2463,2464,2465,2466,2467,2468,2469,2470,2471` **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.OcspPeer.cs` - Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/CertificateIdentityProvider/OcspPeerConfig.cs` - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/OcspPeerValidationTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/CertificateIdentityProvider/CertificateIdentityProviderTests.cs` - Modify: `porting.db` **Step 1: Mark F4 as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2463,2464,2465,2466,2467,2468,2469,2470,2471" --set-status stub --db porting.db --execute ``` **Step 2: Add failing OCSP peer tests (config parse variants, peer chain selection, tls client/server validation hooks)** **Step 3: Run focused tests and confirm FAIL** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~OcspPeerValidationTests|FullyQualifiedName~CertificateIdentityProviderTests" --verbosity normal ``` **Step 4: Implement F4 methods with per-feature loop** **Step 5: Re-run focused tests and require PASS** Use same command as Step 3, require `Failed: 0`. **Step 6: Run Stub Detection + Build Gate + Test Gate** **Step 7: Promote F4 to `complete` then `verified`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2463,2464,2465,2466,2467,2468,2469,2470,2471" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2463,2464,2465,2466,2467,2468,2469,2470,2471" --set-status verified --db porting.db --execute ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 6: Resolve Mapped Test Group T1 (AuthCalloutTests in ImplBacklog) **IDs:** `118,119,124,125,128,129,130,131,134,135` **Files:** - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/AuthCalloutTests.Impltests.cs` - Modify (if needed): `dotnet/src/ZB.MOM.NatsNet.Server/Auth/AuthCallout.cs` - Modify (if needed): `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Auth.cs` - Modify: `porting.db` **Step 1: Mark T1 as `stub` in one chunk (10 <= 15)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "118,119,124,125,128,129,130,131,134,135" --set-status stub --db porting.db --execute ``` **Step 2: For each test ID, attempt real port with Per-Test Verification Loop** **Step 3: If runtime dependencies are missing (internal callout pub/sub/JWT signing pipeline), keep test deferred with reason and no fake assertions** Example defer command: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test update --status deferred --db porting.db \ --override "blocked: requires full auth-callout runtime path (internal request/reply + signed response validation)" ``` **Step 4: Promote only genuinely passing test IDs to `verified` (max 15 IDs/update)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "" --set-status verified --db porting.db --execute ``` **Step 5: Run Stub Detection + Build/Test Gates + checkpoint commit** --- ### Task 7: Batch 9 Final Verification and Closure **Files:** - Modify: `porting.db` - Generate: `reports/current.md` **Step 1: Full build + full unit tests** ```bash /usr/local/share/dotnet/dotnet build dotnet/ /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` **Step 2: Run global Batch 9 stub scan on touched files** ```bash rg -n "NotImplementedException|TODO|PLACEHOLDER|Assert\.True\(true\)" \ dotnet/src/ZB.MOM.NatsNet.Server \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests ``` **Step 3: Validate batch visibility and statuses** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 9 --db porting.db /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db ``` **Step 4: Attempt batch completion** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch complete 9 --db porting.db ``` **Step 5: 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 \ porting.db reports/ git commit -m "feat(batch9): implement auth/dirstore/ocsp foundations" ```