Test report
DigiFIR is tested at every level: unit tests in each repository, contract tests that hold the backend to its OpenAPI file, cross-language test vectors that keep Go, TypeScript and Dart byte-for-byte identical, and end-to-end scenarios that run on a real Hyperledger Fabric network. Each security finding with a reproduction is kept as a regression test.
Latest results
| Suite | Where | Result | Date |
|---|---|---|---|
| Backend unit and integration tests | digifir-backend, npm test | 2,280 tests, all passing | 3 Nov 2026 |
| Backend smoke walk (three processes over HTTP, scripted peer) | npm run smoke | 11 steps, passing | 3 Nov 2026 |
| TypeScript SDK | sdk/ts | 295 tests, passing | 3 Nov 2026 |
| Dart SDK | sdk/dart, dart test | 509 tests, passing | 3 Nov 2026 |
| Backend network walk on the development Fabric network | npm run smoke:network | 12 of 12 | 3 Nov 2026 |
| Backend end-to-end scenarios S1, S2, S6, S7, S9 on the network | npm run e2e:network | 37 passed, 1 skipped | 3 Nov 2026 |
| Load smoke, scenario S8 | npm run load:network | 5 of 5 checks | 3 Nov 2026 |
| Officials' console | apps/console | 265 unit tests, 132 browser tests against a mocked API, 10 browser tests against the real backend in English and Hindi | 4 Nov 2026 |
| Chaincode unit tests | digifir-chaincode, make test (race detector) | 369 test functions with about 695 subtests, 7 fuzz targets, 104 golden files | Batch 3 |
| Chaincode integration scenarios on the network | make integration | 19 tests, about 22 minutes from nothing | Batch 3 |
| Network smoke test | digifir-network, network.sh smoke | 53 checks; 55 after the State C onboarding drill | 1 Nov 2026 |
| Court app | flutter test | 977 passing, 2 skipped | 3 Nov 2026 |
The citizen, police and lab apps are tested with Flutter's tests and web builds; their final update pass is in progress. On the migration branch the four apps hold 498 (citizen, plus 541 portal tests), 481 (police), 546 (lab) and 861 (court) test declarations.
NOTE
Android and iOS release builds have not been compiled in the build environment, which has no Android SDK or Xcode. Native code changes are listed for the build stage.
What the end-to-end scenarios prove
These run against the real development network: five organisations' certificate authorities, three Raft orderers, six peers with CouchDB and the four chaincodes. The test harness connects as the backend does, through each organisation's gateway identity over mutual TLS, names the endorsing organisations of every transaction, and after each commit checks the block itself.
| Scenario | What it proves |
|---|---|
| Bootstrap | InitNetwork, onboarding of both states, a registrar per organisation through its MSP administrator, gateway keys, reference data, officials, services, and a citizen DID registered by a KYC attestor |
| S1, main flow | A complaint with private data (values only on State A and judiciary peers, hashes elsewhere), eSign, FIR with its CCTNS number (endorsed by the wrong organisations: ENDORSEMENT_POLICY_FAILURE), IO, diary and statement, seizure and memo (not seen by the laboratory), a two-party custody hop, dispatch, laboratory acceptance, key escrow, stages, private lab notes, sealing, chargesheet, cognizance (a replay refused as ERR_REPLAY, a direct call as ERR_CALLER), verification of the FIR copy and lab report by hash, a court erasure order carried out in two chaincodes, disposal |
| S2, Zero FIR across states | A Zero FIR from a Jaipur station to a New Delhi station, endorsed by both states and the judiciary, carrying copies of the private data; the receiving station registers it and the first state can no longer change it |
| S2b, transfer with evidence | A court transfer to another state with its handover of private data and evidence keys, a 2 GiB seizure video and a 2 GiB video statement |
| S3, duplicates and the magistrate | Hint models adopted by configuration change, tier-1 and tier-2 hints, referral, the magistrate's comparison and decisions |
| S4, closure path | Closure report, further investigation, status request and reply, closure accepted |
| S5, custody clocks | Arrest, production, police and judicial remand with the default-bail day, bail |
| S6, authority failures | Replays, stale, future and badly timed actions, a state reading another state's private data, wrong endorsers, a non-registrar registering a key, a submitter that is not the gateway, a revoked key |
| S7, integrity | The integrity check finds rows changed directly in PostgreSQL (backend e2e) |
| S8, load | 200 filings from 20 apps (see Performance) |
| S9, edge cases | IO assignment after a court transfer, court remand overriding police records, a 202-event arrest timeline sealed into segments, Sessions Court bail, CCTNS number anchoring and release, canonical text refused at endorsement, session-only keys, laboratory label checks and supplementary reports |
| Queries on CouchDB | Lookups, history, every paginated list followed bookmark by bookmark, rich queries through the shipped indexes |
The backend's end-to-end suite also checks every committed action on the chain (valid, created by the right gateway, endorsed by exactly the right organisations), in the explorer, in the read views of the screens that show it, and on the event streams of exactly the people entitled to it.
What the network smoke test proves
| Area | Checks |
|---|---|
| Identity | Certificates carry the MSP and the digifir.* attributes |
| Public data | A write endorsed by State A and the judiciary is valid and readable on all six peers; CouchDB rich queries through the shipped index |
| Private data | Members read, non-members are refused, the value is absent from non-member CouchDB, the block carries only the hash |
| Endorsement | A write endorsed by State A alone fails with ENDORSEMENT_POLICY_FAILURE and never reaches world state |
| Access control | A caller without a role is refused; a magistrate cannot register a record; State B cannot overwrite State A's records |
| Network | A client without a TLS certificate is refused; discovery sees all peers; metrics and health answer on every node |
| Raft | The leader orderer is stopped, a transaction is still ordered, a new leader is elected, and the old one catches up |
Static checks and CI
| Repository | Checks in CI |
|---|---|
| Backend | npm audit, strict TypeScript, ESLint, unit tests, contract type check, OpenAPI lint, test vectors, integration, smoke, Dart SDK; a conformance test fails the build if any operation of the contract has no implementation; responses validated against the contract in tests |
| Chaincode | Race-detector tests, at least 85 % coverage per contract package, govulncheck, staticcheck, gosec, 30 seconds of fuzzing per target, the seven analysers, test vectors |
| Network | ShellCheck, yamllint, gitleaks over the whole history, 91 channel configuration checks, Prometheus rule tests, kubeconform on every Kubernetes overlay, the admin signing tool's 52 tests; the smoke test on request |
| Apps | Flutter tests, contract checkers that hold the apps' signed actions to the backend's contract and the chaincode's catalogue, screenshot harnesses that render every state of the design (39 in the citizen app, about 60 in the lab app, 80 in the court app) |
Run the tests
# Backend (needs PostgreSQL, Redis and SeaweedFS: npm run deps:up)
npm test
npm run smoke
DIGIFIR_NETWORK=1 npm run e2e:network # needs the development network and the chaincodes
# Chaincode
make test
make integration # brings the network up and deploys the chaincodes
# Network
./scripts/network.sh all # up, channel, sample chaincode, smoke test
# Apps
flutter testSources: digifir-backend README.md, docs/PROJECT-STATUS.md, docs/NETWORK.md, docs/DEVELOPMENT.md; digifir-chaincode README.md, docs/SPEC.md section 11; digifir-network README.md; app repositories on the migration branch.