Skip to content
Last updated: Sep 25, 2026

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):

FunctionsLines
libs/**, generated code excluded55.5%64.7%

Still inflated by trivial barrel index.ts files — real hand-written-logic coverage is lower than 57/64%.

What's missing ​

GapStatus
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/**:

FileLinesWhy it matters
libs/common/credentialcrypto.ts8.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.ts19.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.ts6.1%Rule evaluation feeding reconciliation/close logic — wrong outcomes are wrong financial results.
libs/wfc/workflowclient.service.ts2.8%Temporal client wrapper driving close/recon/collections workflows.
libs/wfw/workflowworker.service.ts16.3%Temporal worker wrapper for the same workflows.
libs/pubsub/pubsub.service.ts1.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.ts5.8% / 5.1%Outbound invoicing/collections notifications; inbound remittance parsing.
libs/queue/queue.service.ts10.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 ​

  1. CI guardrail (non-blocking). Add a PR-triggered unit-tests.yml running bun install && bun test. Add to bunfig.toml:
    toml
    [test]
    coveragePathIgnorePatterns = ["**/generated/**"]
    (Verified against the installed Bun 1.3.11 — production images run 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%.
  2. Security/tenancy first. credentialcrypto.ts and tenanconnections.service.ts — small, self-contained, severe blast radius. Target 90%+, not just 80%.
  3. Financial correctness & workflow reliability. ruleengine.service.ts, workflowclient.service.ts, workflowworker.service.ts (needs @temporalio/testing for Temporal mocking). Target 70–80%.
  4. Messaging/integration layer. pubsub, queue, stream, both email services — slower to write (need Valkey/SMTP/RustFS fakes). Target 60–70%.
  5. 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 including apps/**?
  • Ratchet cadence for the coverage gate — per-sprint or per-milestone?
  • Real @temporalio/testing time-skipping environment vs. lighter mocks for Phase 3 — affects effort estimate.

Finaisse Internal — Confidential. Access-restricted; not for external distribution.