Stability checkpoint — 0 packages under 90% gate + BUNDLE 0.92 ratchet

- test(ml): close ChurnPredictor 18.7% to 81.3% via ONNX test fixture
  (166-byte synthetic model: logit = sum(features), single MatMul)
- test(ml): cover ChurnPredictor.loadModel corrupt-file catch
  (OrtException ORT_INVALID_PROTOBUF via @TempDir + invalid bytes)
- test(auth): close SecurityConfig 26.9% to 99.0% via plain
  @SpringJUnitConfig context (NOT @SpringBootTest — that polluted
  OtelLogbackInstallerTest static state via OpenTelemetry auto-config)
- build(jacoco): ratchet BUNDLE gate 0.85 to 0.92
- docs(tasks): trim items shipped via stable-v1.2.16 + the ONNX
  fixture note

CI :
- ✅ MR pipeline #2486921484 green — https://gitlab.com/iris-7/iris-service-java/-/pipelines/2486921484
- ✅ Post-merge main pipeline #2486926949 green — https://gitlab.com/iris-7/iris-service-java/-/pipelines/2486926949
  - unit-test ✅
  - integration-test ✅
  - sonar/code-quality ✅
  - openapi-lint ✅
  - secret-scan ✅
  - owasp-dependency-check ✅
  - build-jar ✅

Local pre-push lefthook unit-tests hook : ✅ ran on every commit (5/5)
Local ./mvnw verify -DskipITs : ✅ passes the new BUNDLE 0.92 gate

JaCoCo gates verified at the new floors :
- ✅ BUNDLE 0.92 (measured 94.97% UT-only)
- ✅ org.iris.order PACKAGE 0.90 (measured 100%)
- ✅ org.iris.product PACKAGE 0.90 (measured 100%)

Per-package coverage (UT-only, sorted) — every package above 90% :
- org.iris.diag, org.iris.mcp.actuator, org.iris.mcp.domain,
  org.iris.mcp.dto, org.iris.observability.quality,
  org.iris.order, org.iris.product : 100%
- org.iris.chaos : 99.5%
- org.iris.observability.quality.providers : 93.3%
- org.iris.mcp : 97.9%
- org.iris.mcp.openapi : 97.3%
- org.iris.resilience : 96.2%
- org.iris.observability.quality.parsers : 91.8%
- org.iris.api : 92.1%
- org.iris.observability : (post buildJarLayers fixture) past 90%
- org.iris.customer : 92.5%
- org.iris.integration : 100%
- org.iris.mcp.metrics : 97.6%
- org.iris.mcp.logs : 94.5%
- org.iris.messaging : 97.8%
- org.iris.ml : (post ONNX fixture) past 90%
- org.iris.auth : (post SecurityConfig context test) past 90%

Regression check vs stable-v1.2.16 :
- ✅ All previous tests still green (787 unit tests, 0 failures)
- ✅ JaCoCo gate ratchet survives the climb (0.92 cushion vs measured 94.97%)
- 🆕 OtelLogbackInstallerTest — confirmed clean after switching from
  @SpringBootTest to @SpringJUnitConfig (OpenTelemetry auto-config no
  longer pollutes the static appender state)

- ChurnPredictor inference path now end-to-end tested : ONNX session
  load + tensor input + run + sigmoid output. The 4 happy-path tests
  (sigmoid 0/0.5/0.982/0.018) pin the numerically-stable sigmoid
  branch split as a contract. Fixture is reproducible via
  bin/dev/build-churn-test-onnx.py — re-run only when the input/output
  contract changes.
- ChurnMcpToolService still 100% (from stable-v1.2.16) so the MCP
  predict_customer_churn @Tool path is fully exercised.

- SecurityConfig filter chain end-to-end verified : 18 requestMatcher
  rules, sessionManagement STATELESS, CSRF disabled, CORS allowlist,
  exception handling 401, both custom filters wired before
  UsernamePasswordAuthenticationFilter. The lambda DSL bodies were
  the largest unit-coverage gap in the codebase (282 missed instructions).
- LoginAttemptService brute-force protection 100% covered (carried
  forward from 1.2.16).
- Auth0 + Keycloak JWT validation paths still pinned (KeycloakConfig
  guard branches at 85.3%, full Auth0/Keycloak issuer-shape detection
  + audience validator covered).

- E-commerce slice still 100% (carried forward).
- Customer 360 + ChurnPredictor full inference flow end-to-end.

- ⏭ N/A — no infra changes in this batch.

- AuditService findAll RowMapper, QualityReportEndpoint formatUptime
  + buildJarLayersSection, DependenciesSectionProvider — all carried
  forward from 1.2.16.
- @SpringJUnitConfig context test pattern documented (avoids
  polluting OtelLogbackInstaller static state) — DevX win.

- Bundle JaCoCo : 93.0% to **94.97%** (UT-only).
- 0 packages under 90% (was 2 in 1.2.16 : ml + auth).
- BUNDLE gate ratchet : 0.85 to 0.92 — locks the climb.
- Test count : ~140 new tests across 1.2.16 + 1.2.17.

- JaCoCo gate ratchet history :
  - !270 : BUNDLE 0.70 to 0.85
  - !271 : BUNDLE 0.85 to 0.92
- Order/product PACKAGE 0.90 floors hold (measured 100%).
- Pipeline stages green : openapi-lint, owasp-dependency-check,
  secret-scan, unit-test, integration-test, build-jar,
  sonar/code-quality. Compat matrix + native-build remain manual.

- Hexagonal Lite (ADR-0044), feature-slicing (ADR-0008) preserved.
- Test pattern : @SpringJUnitConfig (plain Spring) for security DSL
  coverage — narrower than @SpringBootTest, no auto-config pollution
  side-effects.

- ⏭ N/A — backend repo.

- bin/dev/build-churn-test-onnx.py : reproducible 166-byte ONNX
  fixture generator (uses the onnx Python package available in
  iris-service-python's dev deps).
- src/test/resources/churn-predictor-test.onnx : checked-in binary
  fixture, no per-build regen.
- Pre-push lefthook unit-tests hook stable around 25-35 s warm cache.

- KafkaHealthIndicator UP path + KeycloakHealthIndicator UP path —
  need real broker / OAuth server. DOWN paths fully unit-tested.
- ChurnPredictor closeSession OrtException catch (~6 missed
  instructions) — needs a corrupt-mid-close session, low-value to
  synthesise.
- The 27 missed instructions in observability that remain are infra-
  bound (Process/git CLI invocations in QualityReportEndpoint).

- Per-package gate ratchet : order + product 0.90 to 0.95 (both
  measured 100%, 5% cushion).
- Mutation testing (PIT) : measure score on org.iris.{order,product}.*
  and target ≥ 75%.
- bin/dev/api-smoke.sh : POST /orders + 2 OrderLines + GET + DELETE
  + total recalc — scriptable cluster-demo entry.
- Cluster work : RPO measurement + SLO dashboard screenshots when
  cluster is up.