# Batch 10 (OCSP Cache + JS Events) Implementation Plan > **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task. **Goal:** Implement and verify Batch 10 (`20` features + `38` tests) for OCSP response-cache behavior and JetStream advisory publishing, while keeping externally blocked tests deferred with explicit evidence. **Architecture:** Implement Batch 10 in three feature groups (1/13/6 IDs) and two test-resolution groups (candidate-verify + blocked-defer). Use strict per-feature verification loops, stub detection, and chunked status updates so every transition to `complete`/`verified` is evidence-backed. **Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (`porting.db`) --- I'm using `writeplan` to create the implementation plan. **Design doc:** `docs/plans/2026-02-27-batch-10-ocsp-cache-js-events-design.md` ## Batch 10 Working Set Batch facts: - Batch ID: `10` - Depends on: `9` - Features: `20` - Tests: `38` - Go files: `server/ocsp_responsecache.go`, `server/jetstream_events.go` Environment note: - In this workspace, use `/usr/local/share/dotnet/dotnet` (not `dotnet`) for CLI commands. Feature groups (all <= 20 IDs): - **F1 (1):** `1959` - **F2 (13):** `2472,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495` - **F3 (6):** `2496,2497,2498,2499,2500,2501` Test groups: - **T1 candidate verify (8):** `1537,1538,1607,1625,1682,2442,2807,2894` - **T2 dependency-blocked (30):** `641,684,1407,1837,1934,1946,1978,2002,2005,2042,2049,2050,2051,2052,2055,2058,2059,2060,2061,2062,2063,2177,2250,2487,2810,2812,2839,2862,3103,3112` --- ## MANDATORY VERIFICATION PROTOCOL > NON-NEGOTIABLE: Every task in this plan must follow this protocol. ### Per-Feature Verification Loop (required for every feature ID) 1. Read mapping + Go source: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- feature show --db porting.db ``` 2. Read exact Go implementation in `golang/nats-server/server/jetstream_events.go` or `golang/nats-server/server/ocsp_responsecache.go`. 3. Write/adjust C# implementation in mapped .NET file. 4. Build immediately: ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` 5. Run related focused tests for that feature group. 6. Only after build + focused tests pass, add ID to promotion candidate list. ### Stub Detection Check (required after every feature/test group) Run all checks before status updates: ```bash # Placeholder/stub markers in touched code rg -n "NotImplementedException|TODO|PLACEHOLDER|throw new NotSupportedException" \ 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|internal|private|protected).+\)\s*\{\s*\}$" "$f" done # Suspicious trivial returns in touched production files for f in $(git diff --name-only dotnet/src/ZB.MOM.NatsNet.Server -- '*.cs'); do rg -n "=>\s*(default|null|true|false);$" "$f" done ``` Any hit blocks promotion to `complete` or `verified` until fixed or explicitly deferred. ### Build Gate (required after each feature group) ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` Required: `0` compile errors. ### Test Gate (required before marking features verified) All tests related to current feature group must pass before moving feature IDs to `verified`. Focused test commands are defined inside each task. If any test fails, do not promote. ### Status Update Protocol (required) - Maximum `15` IDs per `feature batch-update` or `test batch-update` command. - Required evidence per update command: - latest build gate output - latest focused test gate output - latest stub detection output - Required flow: - Feature IDs: `deferred -> stub -> complete -> verified` - Test IDs: `deferred -> stub -> verified` or remain `deferred` with blocker 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 ``` ### Checkpoint Protocol Between Tasks (required) Between every task boundary (Task 1 -> Task 2 -> ...): 1. Full build: ```bash /usr/local/share/dotnet/dotnet build dotnet/ ``` 2. Full unit test run: ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` 3. Commit checkpoint: ```bash git add porting.db git commit -m "feat(batch10): " ``` --- ## ANTI-STUB GUARDRAILS ### Forbidden Patterns Do not mark as `verified` if any mapped method/test includes: - `throw new NotImplementedException(...)` - empty mapped method bodies (`{ }`) - `TODO` or placeholder comments in method/test bodies - fake pass assertions (`Assert.True(true)`, equivalent no-op assertions) - tests that only assert non-behavioral values (for example, not-null only with no behavior) ### Hard Limits - Max `20` feature IDs per implementation task group. - Max `15` IDs per status update command. - No cross-group bulk verification in one command cycle. - Build gate is mandatory after each feature group. - Test gate is mandatory before any feature moves to `verified`. - Checkpoint commit is mandatory between tasks. ### If You Get Stuck Do not stub and do not fake-pass. 1. Leave item as `deferred`. 2. Record specific blocker reason (dependency ID, missing runtime path, or infra need). 3. Continue with next unblocked item. 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: Preflight and Batch Start **Files:** - Modify: `porting.db` **Step 1: Verify dependency batch state** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 9 --db porting.db ``` Expected: Batch 9 is complete enough to start Batch 10. **Step 2: Start Batch 10** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch start 10 --db porting.db ``` Expected: Batch 10 transitions to in-progress. **Step 3: Baseline dependency evidence for Batch 10 tests** ```bash cat <<'SQL' | sqlite3 -header -column porting.db WITH t AS ( SELECT ut.id, ut.name FROM unit_tests ut JOIN batch_tests bt ON bt.test_id=ut.id WHERE bt.batch_id=10 ), unresolved AS ( SELECT d.source_id AS test_id, SUM(CASE WHEN f.status NOT IN ('complete','verified','n_a') THEN 1 ELSE 0 END) AS unresolved_total, SUM(CASE WHEN f.status NOT IN ('complete','verified','n_a') AND f.id NOT IN (SELECT feature_id FROM batch_features WHERE batch_id=10) THEN 1 ELSE 0 END) AS unresolved_outside_batch FROM dependencies d JOIN features f ON d.target_type='feature' AND d.target_id=f.id WHERE d.source_type='unit_test' AND d.source_id IN (SELECT id FROM t) GROUP BY d.source_id ) SELECT * FROM unresolved ORDER BY test_id; SQL ``` Expected: `T1` IDs have `unresolved_outside_batch=0`; `T2` IDs have `>0`. **Step 4: Run checkpoint protocol and commit preflight evidence** --- ### Task 2: Implement Feature Group F1 (`1959`) JetStream Advisory Publish **Files:** - Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.JetStreamEvents.cs` - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/NatsServerJetStreamEventsTests.cs` - Modify: `porting.db` **Step 1: Mark feature `1959` as `stub`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update 1959 --status stub --db porting.db ``` **Step 2: Write failing tests for advisory decision tree** Cover: - null account falls back to `SystemAccount()` - no interest returns false without send - marshal/send errors return false - successful send returns true **Step 3: Run focused tests and confirm initial fail** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~NatsServerJetStreamEventsTests" --verbosity normal ``` **Step 4: Implement `PublishAdvisory` parity in new partial class** **Step 5: Re-run focused tests and require pass** Use same command as Step 3. **Step 6: Run stub detection + build gate + test gate** **Step 7: Promote feature `1959`** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update 1959 --status complete --db porting.db /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature update 1959 --status verified --db porting.db ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 3: Implement Feature Group F2 (`2472,2484-2495`) Local Cache Core + Stats + Compression **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/Ocsp/OcspTypes.cs` - Create: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/Ocsp/OcspHandler.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/OcspResponseCacheTests.cs` - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/OcspResponseCacheParserTests.cs` - Modify: `porting.db` **Step 1: Mark F2 IDs as `stub` (single command, 13 IDs <= 15)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2472,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495" \ --set-status stub --db porting.db --execute ``` **Step 2: Add failing tests for local cache behavior** Cover: - stats adjust on put/replace/delete - hit->miss adjustment when preserving revoked entries - `Online/Type/Config/Stats` semantics - compress/decompress round-trip - `NewOCSPResponseCacheConfig` defaults **Step 3: Run focused tests and confirm initial fail** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~OcspResponseCacheTests|FullyQualifiedName~OcspResponseCacheParserTests" --verbosity normal ``` **Step 4: Implement F2 methods with per-feature verification loop** **Step 5: Re-run focused tests and require pass** Use same command as Step 3. **Step 6: Run stub detection + build gate + test gate** **Step 7: Promote F2 IDs in two transitions (`complete`, then `verified`)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2472,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495" \ --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2472,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495" \ --set-status verified --db porting.db --execute ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 4: Implement Feature Group F3 (`2496,2497,2498,2499,2500,2501`) Load/Save + Server Wiring + Parser **Files:** - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/Ocsp/OcspTypes.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/Auth/Ocsp/OcspHandler.cs` - Create: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.OcspResponseCache.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Init.cs` - Modify: `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Lifecycle.cs` - Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/NatsServerOcspCacheTests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Auth/OcspResponseCacheParserTests.cs` - Modify: `porting.db` **Step 1: Mark F3 IDs as `stub` (6 IDs)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2496,2497,2498,2499,2500,2501" --set-status stub --db porting.db --execute ``` **Step 2: Add failing tests for load/save lifecycle + parser + server init/start/stop** Cover: - load from absent/corrupt/valid cache file - save no-op when clean + atomic write when dirty - parser type conversion + minimum save interval clamp - server init chooses no-op/local cache correctly - start/stop wiring calls cache lifecycle **Step 3: Run focused tests and confirm initial fail** ```bash /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~OcspResponseCacheTests|FullyQualifiedName~OcspResponseCacheParserTests|FullyQualifiedName~NatsServerOcspCacheTests" --verbosity normal ``` **Step 4: Implement F3 methods with per-feature verification loop** **Step 5: Re-run focused tests and require pass** Use same command as Step 3. **Step 6: Run stub detection + build gate + test gate** **Step 7: Promote F3 IDs (`complete`, then `verified`)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2496,2497,2498,2499,2500,2501" --set-status complete --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ feature batch-update --ids "2496,2497,2498,2499,2500,2501" --set-status verified --db porting.db --execute ``` **Step 8: Run checkpoint protocol and commit** --- ### Task 5: Resolve Batch 10 Tests (T1 verify, T2 defer with reason) **Files:** - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs` - Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsServerTests.Impltests.cs` - Modify: `porting.db` **Step 1: Mark T1 + T2 IDs as `stub` in chunks <= 15** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "1537,1538,1607,1625,1682,2442,2807,2894" --set-status stub --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "641,684,1407,1837,1934,1946,1978,2002,2005,2042,2049,2050,2051,2052,2055" \ --set-status stub --db porting.db --execute /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "2058,2059,2060,2061,2062,2063,2177,2250,2487,2810,2812,2839,2862,3103,3112" \ --set-status stub --db porting.db --execute ``` **Step 2: Port and verify T1 tests one-by-one using per-test loop** For each T1 test ID: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- test show --db porting.db /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \ --filter "FullyQualifiedName~" --verbosity normal ``` Expected: each verified method shows `Passed: 1`. **Step 3: Promote T1 verified tests in one chunk (8 IDs <= 15)** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test batch-update --ids "1537,1538,1607,1625,1682,2442,2807,2894" --set-status verified --db porting.db --execute ``` **Step 4: For T2, prove unresolved external dependencies and keep deferred** ```bash cat <<'SQL' | sqlite3 -header -column porting.db WITH t AS ( SELECT ut.id, ut.name FROM unit_tests ut JOIN batch_tests bt ON bt.test_id=ut.id WHERE bt.batch_id=10 AND ut.id IN (641,684,1407,1837,1934,1946,1978,2002,2005,2042,2049,2050,2051,2052,2055, 2058,2059,2060,2061,2062,2063,2177,2250,2487,2810,2812,2839,2862,3103,3112) ) SELECT t.id, t.name, f.id AS blocked_feature_id, f.name AS blocked_feature_name, f.status FROM t JOIN dependencies d ON d.source_type='unit_test' AND d.source_id=t.id AND d.target_type='feature' JOIN features f ON f.id=d.target_id WHERE f.status NOT IN ('complete','verified','n_a') AND f.id NOT IN (SELECT feature_id FROM batch_features WHERE batch_id=10) ORDER BY t.id, f.id; SQL ``` Then keep each blocked test deferred with reason: ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- \ test update --status deferred --db porting.db \ --override "blocked: unresolved dependency feature ()" ``` **Step 5: Run stub detection + build gate + test gate + checkpoint commit** --- ### Task 6: Final Batch 10 Verification and Attempted Closure **Files:** - Modify: `porting.db` - Generate: `reports/current.md` **Step 1: Full verification gates** ```bash /usr/local/share/dotnet/dotnet build dotnet/ /usr/local/share/dotnet/dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --verbosity normal ``` Expected: build passes; no unexpected test regressions. **Step 2: Global stub audit for touched scope** ```bash rg -n "NotImplementedException|TODO|PLACEHOLDER|Assert\.True\(true\)" \ dotnet/src/ZB.MOM.NatsNet.Server \ dotnet/tests/ZB.MOM.NatsNet.Server.Tests ``` Expected: no matches in Batch 10 touched code/tests. **Step 3: Verify batch/test visibility** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch show 10 --db porting.db /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db ``` **Step 4: Try completing batch** ```bash /usr/local/share/dotnet/dotnet run --project tools/NatsNet.PortTracker -- batch complete 10 --db porting.db ``` If blocked by deferred T2 tests, keep batch in-progress with documented blockers (correct behavior). **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(batch10): implement ocsp cache and js advisory with verified gates" ```