Testing & Coverage
Owner: Sekhar Prakash
This page tracks automated test coverage in blitz — what exists, what's missing, and the plan to reach 80% coverage on hand-written code. It complements Secure SDLC §4 (which covers security testing — SAST/DAST/pentest) and Coverage & Assessment Methodology (which covers security assessment lenses); this page is about functional/unit test coverage of the codebase itself, a gap neither of those currently tracks.
Current state
CI runs no tests today. blitz's GitHub Actions are Docker build/push pipelines (build-push-*.yml); the two static guards it used to run were withdrawn on 2026-09-15 (see the Control Register). Nothing invokes bun test. A PR can merge with a failing unit test and nothing in CI flags it.
A test suite exists, but it is currently red. 21 *.test.ts files under blitz/src/libs/** and packages/**, 102 tests, 180 expect() calls (bun test, checked 2026-09-14): 101 pass, 1 fail (finbase/finbasea/services/finbase/matching_output.service.test.ts), plus an unhandled error between tests from sharepoint.callback.controller.ts (@elysiajs/jwt: "Secret can't be empty"). Because CI runs no tests (below), nothing caught either issue before merge — re-verify the current pass/fail state before relying on this section, since with no CI gate it can drift again at any time.
Coverage, honestly measured: bun test --coverage's raw number is inflated by generated Prisma client files that read 100% simply from being imported. Excluding **/generated/** gives the real baseline (checked 2026-09-14):
| Functions | Lines | |
|---|---|---|
libs/**, generated code excluded | 55.5% | 64.7% |
Still inflated by trivial barrel index.ts files — real hand-written-logic coverage is lower than 57/64%.
What's missing
| Gap | Status |
|---|---|
| CI test execution | 🔴 no workflow runs bun test |
| Coverage gate | 🔴 no threshold; nothing prevents regression |
apps/* coverage | 🔴 zero — all 22 deployed services (api, ws, wfw, recon, agents, …) have no route/integration tests |
| Security/tenancy-critical libs | 🟠 present but thin (see below) |
| Honest coverage config | 🟠 no [test] block in bunfig.toml to exclude generated code or enforce a threshold |
Thinnest coverage on highest-risk libs
Ranked by business risk (a leak or a wrong financial number is worse than a crash), from libs/**:
| File | Lines | Why it matters |
|---|---|---|
libs/common/credentialcrypto.ts | 8.9% | AES-256-GCM envelope for connector secrets (SFTP passwords, OAuth tokens). An untested key-decoding path or silent {enc:"none"} fallback is a secrets-in-plaintext exposure. |
libs/tenancy/tenanconnections.service.ts | 19.7% | Resolves/caches per-tenant Prisma clients in a process-global Map. A cache-key bug here risks tenant A getting tenant B's DB client — related territory to F-38 (Temporal visibility not tenant-scoped). |
libs/rulesengine/ruleengine.service.ts | 6.1% | Rule evaluation feeding reconciliation/close logic — wrong outcomes are wrong financial results. |
libs/wfc/workflowclient.service.ts | 2.8% | Temporal client wrapper driving close/recon/collections workflows. |
libs/wfw/workflowworker.service.ts | 16.3% | Temporal worker wrapper for the same workflows. |
libs/pubsub/pubsub.service.ts | 1.9% | Cross-service event bus (546 lines) — a missed/duplicated event is a silent consistency bug, not a crash. |
libs/email/sendemail.service.ts / receiveemail.service.ts | 5.8% / 5.1% | Outbound invoicing/collections notifications; inbound remittance parsing. |
libs/queue/queue.service.ts | 10.2% | Async job queue underlying most of the above; retry/failure semantics untested. |
Target
80% line coverage on hand-written code in libs/** + packages/** (excluding **/generated/**, deprecated/**, zplayground/** — the same exclusions the withdrawn import/lockfile guards used). apps/** is tracked separately with a lower bar (Phase 4) since route-level smoke tests matter more there than line coverage.
Approach — 5 phases
- CI guardrail (non-blocking). Add a PR-triggered
unit-tests.ymlrunningbun install && bun test. Add tobunfig.toml:toml(Verified against the installed Bun 1.3.11 — production images run[test] coveragePathIgnorePatterns = ["**/generated/**"]oven/bun:1.4.0, so this needs re-verification on 1.4.0 before the gate goes live.) Publish coverage to the job summary; no threshold gate yet — the baseline is far below 80%. - Security/tenancy first.
credentialcrypto.tsandtenanconnections.service.ts— small, self-contained, severe blast radius. Target 90%+, not just 80%. - Financial correctness & workflow reliability.
ruleengine.service.ts,workflowclient.service.ts,workflowworker.service.ts(needs@temporalio/testingfor Temporal mocking). Target 70–80%. - Messaging/integration layer.
pubsub,queue,stream, both email services — slower to write (need Valkey/SMTP/RustFS fakes). Target 60–70%. apps/*entrypoints. Biggest raw gap by line count, lowest per-service urgency (regressions surface fast in staging). Elysia test-client smoke tests per service: routes register, auth guards reject wrong-tenant requests, one happy path per endpoint group. Track as its own ~50% bar, separate from the 80% business-logic target.
Once libs/**/packages/** coverage reaches ~75–80%, turn on coverageThreshold in bunfig.toml (confirmed: bun test --coverage exits 1 below threshold even with all tests passing, so it's a valid required CI check) and ratchet it up in small steps rather than jumping straight to 80%.
Open questions
- Does the 80% target apply to
libs/**+packages/**only (proposed) or repo-wide includingapps/**? - Ratchet cadence for the coverage gate — per-sprint or per-milestone?
- Real
@temporalio/testingtime-skipping environment vs. lighter mocks for Phase 3 — affects effort estimate.