# Baseline Metrics — 01-testability-refactoring **Run**: 01-testability-refactoring **Date**: 2026-05-14 **Mode**: guided (testability) **Scope**: minimal-surgical refactor to make the documented test suite runnable. Many baseline categories are **N/A** by design because no executable test suite exists yet (this run produces the *prerequisites* for the suite to be implemented in Step 6). ## Goals (from `list-of-changes.md` Summary) 1. Unblock authenticated-endpoint tests by gating the JWKS retriever's HTTPS requirement on `ASPNETCORE_ENVIRONMENT=E2ETest`. 2. Unblock outbox-drain tests by fixing the `IPAddress.Parse` assumption in `FailsafeProducer` so DNS hostnames (the documented and operationally normal case) resolve correctly. Both goals derive directly from `_docs/02_document/tests/` and `_docs/02_document/architecture.md` Open Risks §6. ## Acceptance Criteria This run completes when: - C01 and C02 are applied to source and build cleanly under `dotnet build src/`. - The refactored code preserves every existing behavior outside the documented testability surface (verified by code review in Phase 6, not by an executing test suite that does not yet exist). - `architecture.md` Open Risks §6 is updated (entry retired, replaced by the implemented gating). - A `testability_changes_summary.md` is written and presented to the user. ## Baseline Metrics | Metric Category | Captured? | Value / Reason | |----------------|-----------|----------------| | Coverage (overall / unit / blackbox / critical paths) | **N/A** | No executable test suite exists in this repo today. `_docs/02_document/tests/` contains 67 *test specifications* but zero implemented tests. This is precisely why Step 4 (testability) precedes Step 6 (Implement Tests). | | Cyclomatic complexity (avg + top 5) | Captured (rough) | `src/Auth/JwtExtensions.cs` — 1 method (`AddJwtAuth`), cyclomatic ~3 (one inline resolver lambda with a kid-null branch). `src/Services/FailsafeProducer.cs` — `DrainQueue` is the hot function, cyclomatic ~7 (foreach + nested foreach + 3 branches for operation type). No top-5 needed for a 2-file scope. | | LOC (target files) | Captured | `JwtExtensions.cs` = 89 LOC. `FailsafeProducer.cs` = 206 LOC. | | Tech debt ratio | **N/A** | No SonarQube / dotnet-counters baseline in this repo. The architecture compliance baseline (`_docs/02_document/architecture_compliance_baseline.md`) is the qualitative substitute — verdict PASS_WITH_WARNINGS, 0 Critical, 0 High, 1 Medium, 2 Low. | | Total / critical / major code smells | Captured (qualitative) | From baseline: F1 (Medium — DatasetService writes annotation table — out of scope here, RB-08), F2 (Low — ClassesController bypasses service — out of scope, RB-06), F3 (Low — `FailsafeProducer.EnqueueAsync` static — accepted tech debt). None in the C01/C02 affected lines. | | Response times P50/P95/P99 | **N/A** | No load harness yet; perf tests are spec'd in `_docs/02_document/tests/performance-tests.md` but not implemented. Step 15 (Performance Test) is where these get measured. | | CPU / Memory baseline | **N/A** | Same as above. | | Throughput | **N/A** | Same as above. | | Dependency count (target files) | Captured | `JwtExtensions.cs` deps: `Microsoft.AspNetCore.Authentication.JwtBearer`, `Microsoft.IdentityModel.Protocols`, `Microsoft.IdentityModel.Tokens` (all pinned in `src/Azaion.Annotations.csproj`). `FailsafeProducer.cs` deps: `LinqToDB`, `RabbitMQ.Stream.Client`, `MessagePack`, `System.Net` (BCL). No new dependencies added by C01/C02. | | Outdated dependencies | **N/A** | Out of scope for testability. | | Security vulnerabilities | **N/A** | Step 14 (Security Audit) — separate concern. The change does not introduce new attack surface (C01 narrows by env, C02 same threat model). | | Build time | Captured | Not measured today; not material to a 2-file change. Phase 6 will run `dotnet build` and confirm it remains green. | | Test execution time | **N/A** | No tests yet. | | Deployment time | **N/A** | Out of scope. | ## Functionality Inventory — affected surface | Endpoint / Background work | File(s) | Affected by | Behavioral change visible to a consumer? | |----------------------------|---------|-------------|-----------------------------------------| | All `[Authorize]`-protected endpoints (everything except `/health`) | `src/Auth/JwtExtensions.cs` | C01 | In `ASPNETCORE_ENVIRONMENT=E2ETest`, the SUT will fetch JWKS over HTTP. In all other environments (Development, Production), behavior is identical — `RequireHttps=true` remains the default. | | `FailsafeProducer` (`BackgroundService`) drain loop | `src/Services/FailsafeProducer.cs` | C02 | When `RABBITMQ_HOST` is a literal IP: no behavioral change. When `RABBITMQ_HOST` is a DNS hostname: the producer now connects (previous behavior: throws `FormatException` every 10 s, outbox never drains). | | `AnnotationService.CreateAnnotation` → `FailsafeProducer.EnqueueAsync` (static, synchronous outbox insert) | `src/Services/AnnotationService.cs:102` | not affected | No change. | | Public API surface (DTOs, OpenAPI shape) | `src/DTOs/`, controllers | not affected | No change. | ## Reproducibility - Source state captured by git commit at the start of this run (next commit after `_docs/_autodev_state.md` step-4 in_progress write). - Both files have local line numbers documented in `list-of-changes.md` for unambiguous before/after diffing. - No external tooling required beyond `dotnet build` and a `grep` over the two affected files post-change. ## Self-verification - [x] RUN_DIR created with prefix `01-testability-refactoring` (no prior `NN-*` folders in `_docs/04_refactoring/`). - [x] Goals documented; map 1:1 to `list-of-changes.md` entries. - [x] Acceptance criteria stated and measurable. - [x] Metric categories captured OR explicitly marked N/A with reason. - [x] Functionality inventory covers every public-API impact of C01 and C02. - [x] Measurements are reproducible from the listed files + a clean checkout.