Skip to content

Test sweep: 144 new tests across services + middleware + verifier package (73 → 217)#30

Merged
pulkitpareek18 merged 1 commit into
mainfrom
dev
May 14, 2026
Merged

Test sweep: 144 new tests across services + middleware + verifier package (73 → 217)#30
pulkitpareek18 merged 1 commit into
mainfrom
dev

Conversation

@pulkitpareek18
Copy link
Copy Markdown
Collaborator

Closes the long-standing coverage gap on services + middleware that integration tests had been covering indirectly. Plus adds the verifier package's first ever tests (it shipped this morning without any).

What's covered

Backend (8 new test files, +121 tests):

Suite Tests Surface
api-keys.test.ts 16 SHA-256 key hashing (DB stores hash never raw), expiry + revoked rejection, listApiKeys never projects key_hash, audit-row plumbing
tenants.test.ts 18 scrypt password hashing (salt:hex), distinct salts, malformed-hash rejection (no colon / missing salt / non-hex / truncated), email lower-case, PLAN_LIMITS
jwt.test.ts 12 issueTokens, jti uuid v4, refresh strips claims, verifyToken rejects wrong-secret/wrong-issuer/garbage
middleware.test.ts 14 authenticateJWT 5 reject paths + happy, authenticateAdmin, errorHandler stack-leak guard (prod vs dev), demoAuthOnly 503 gate
session-store.test.ts 7 in-memory create/get/delete, auto-expiry, getStats prune + biometric-zero invariant
usage.test.ts 16 fire-and-forget invariant, endpoint→counter routing, checkQuota -1-unlimited fast path
platform.test.ts 18 recordAuditEvent shape, AuditActor plumbing (issue #26 F-3), tenant-scoping (A-01) assertions, sanitizeLimit boundaries
leads.test.ts 20 POST /pilot + /whitepaper validation, lower-case + trim, Postgres-unavailable degraded path, DB-error doesn't leak, admin gating + type filter + injection-resistance

Verifier package (2 new test files, +23 tests):

Suite Tests Surface
verifier/tests/groth16.test.ts 9 initVerifier missing-vkey path, structural fallback flag, rejects wrong protocol / curve / wrong-length pi_a / empty string / non-string
verifier/tests/server.test.ts 14 POST /verify envelope (uuid v4 verifierAuditId, latencyMs, circuitVersion, structuralFallback), 400s for invalid bodies, unique audit id per call, GET /health degraded reporting, 404 routing

Numbers

  • Backend: 73 → 194 tests (+121)
  • Verifier: 0 → 23 tests (+23)
  • Total: 73 → 217 tests (+144 net)
  • All passing
  • Typecheck: both packages clean
  • Lint: 0 errors, 10 pre-existing warnings unchanged

What's deliberately NOT tested

  • src/services/db.ts — thin pg pool wrapper, hard to unit-test without spinning Postgres in CI
  • src/services/logger.ts — winston wrapper, no logic
  • src/types/ — declarations only
  • src/config/ — env-var parsing, exercised through every other test
  • src/middleware/tenant-auth.ts direct unit — already covered by central-api + console-proxy integration tests
  • src/server.ts startup — covered by deploy smoke + Playwright e2e

Test plan

  • npx tsc --noEmit clean both packages
  • npm test — 194 backend
  • npm --workspace @zeroauth/verifier test — 23 verifier
  • npm run lint — 0 errors
  • CI validate + Playwright green on this PR
  • After merge: production deploy still green (zero behavioural change — tests only)

🤖 Generated with Claude Code

… verifier

73 → 217 tests passing (144 new). Covers every previously-untested
service + middleware in the API repo, plus the verifier package which
shipped on Day 4 with zero of its own tests.

Backend (tests/, +121):

- tests/api-keys.ts (16) — generateRawKey shape, SHA-256 hashing
  (DB stores the hash, never the raw key — verified by digest
  comparison), authenticateApiKey expiry + revoked rejection,
  listApiKeys never projects key_hash, revokeApiKey audit row +
  no-op return, countActiveKeys parses pg's string count.
- tests/tenants.ts (18) — scrypt password hashing (salt:hex format
  verified by regex), distinct salts → distinct hashes, password
  verification rejects on wrong password / malformed stored hash /
  missing colon / non-hex / truncated, email lower-case-trim on
  signup + lookup, PLAN_LIMITS application.
- tests/jwt.ts (12) — issueTokens shape, jti uuid v4 verified,
  refresh token stripped of payload claims, verifyToken throws on
  wrong secret / wrong issuer / no issuer / garbage, decodeToken
  no-verify path.
- tests/middleware.ts (14) — authenticateJWT happy + 5 reject paths
  (no header, non-Bearer, invalid jwt, expired, wrong-secret),
  authenticateAdmin x-api-key matching, errorHandler 500 with stack
  in dev only / suppressed in prod, notFoundHandler 404,
  demoAuthOnly 503 unless ENABLE_DEMO_AUTH=true.
- tests/session-store.ts (7) — in-memory create/get/delete,
  auto-expiry on get, getStats prunes + biometricDataStored=false
  invariant, provider breakdown bumps.
- tests/usage.ts (16) — logApiCall fire-and-forget invariant
  (swallows errors), endpoint→counter routing (zkp_verifications,
  zkp_registrations, saml_auths, oidc_auths, total_requests),
  checkQuota allowed/used/limit logic with -1 unlimited fast-path.
- tests/platform.ts (18) — recordAuditEvent INSERT shape,
  AuditActor plumbing (issue #26 F-3): console → actor_type=console
  + actor_email in metadata, v1 → actor_type=api_key, missing actor
  → default to api_key+null. Tenant-scoping (A-01) assertions:
  every listDevices/listTenantUsers/listAuditEvents WHERE clause
  includes tenant_id AND environment. sanitizeLimit boundaries
  ([1,100] clamp, default 50, negative clamps to 1).
- tests/leads.ts (20) — POST /pilot validation + persist, lower-case
  + trim, Postgres-unavailable degraded path, DB-error-doesn't-leak,
  POST /whitepaper download URL, GET /api/leads admin gating + type
  filter + injection-resistance (invalid ?type ignored).

Verifier (verifier/tests/, +23):

- groth16.test.ts (9) — initVerifier handles missing vkey path,
  structural fallback returns structuralFallback=true, rejects
  wrong protocol / wrong curve / wrong-length pi_a / empty string
  in pi_a / non-string in pi_c / totally malformed object.
- server.test.ts (14) — supertest against the Express app:
  POST /verify envelope shape (200 + verifierAuditId uuid v4 +
  latencyMs + circuitVersion + structuralFallback), 400s for
  missing proof / missing publicSignals / length != 3 / non-array,
  custom circuitVersion echo, unique verifierAuditId per call,
  monotonic uptime, GET /health degraded when no vkey, 404 on
  unknown routes including GET /verify.

Infra:

- verifier/jest.config.js added (ts-jest preset, tests in
  verifier/tests/)
- verifier/package.json test script wired
- verifier/tests/ directory created
- All 18 jest devDeps pulled in via npm workspace install

Typecheck both packages clean. Lint 0 errors (10 pre-existing
warnings unchanged).

What's still untested (deferred — lower priority):

- src/services/db.ts pg pool wrapper (thin, hard to unit-test
  meaningfully without spinning up Postgres)
- src/services/logger.ts (winston wrapper, no logic)
- src/types/ (type declarations only)
- src/config/ (env var parsing — exercised via every other test)
- src/middleware/tenant-auth.ts unit (already covered by
  integration via central-api.test.ts + console-proxy.test.ts)
- src/server.ts startup (covered by deployment smoke + e2e)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 14, 2026 06:56
@pulkitpareek18 pulkitpareek18 merged commit 23c136e into main May 14, 2026
2 checks passed
@pulkitpareek18 pulkitpareek18 deleted the dev branch May 14, 2026 06:56
@pulkitpareek18 pulkitpareek18 review requested due to automatic review settings May 14, 2026 07:20
pulkitpareek18 added a commit that referenced this pull request May 15, 2026
… verifier (#30)

73 → 217 tests passing (144 new). Covers every previously-untested
service + middleware in the API repo, plus the verifier package which
shipped on Day 4 with zero of its own tests.

Backend (tests/, +121):

- tests/api-keys.ts (16) — generateRawKey shape, SHA-256 hashing
  (DB stores the hash, never the raw key — verified by digest
  comparison), authenticateApiKey expiry + revoked rejection,
  listApiKeys never projects key_hash, revokeApiKey audit row +
  no-op return, countActiveKeys parses pg's string count.
- tests/tenants.ts (18) — scrypt password hashing (salt:hex format
  verified by regex), distinct salts → distinct hashes, password
  verification rejects on wrong password / malformed stored hash /
  missing colon / non-hex / truncated, email lower-case-trim on
  signup + lookup, PLAN_LIMITS application.
- tests/jwt.ts (12) — issueTokens shape, jti uuid v4 verified,
  refresh token stripped of payload claims, verifyToken throws on
  wrong secret / wrong issuer / no issuer / garbage, decodeToken
  no-verify path.
- tests/middleware.ts (14) — authenticateJWT happy + 5 reject paths
  (no header, non-Bearer, invalid jwt, expired, wrong-secret),
  authenticateAdmin x-api-key matching, errorHandler 500 with stack
  in dev only / suppressed in prod, notFoundHandler 404,
  demoAuthOnly 503 unless ENABLE_DEMO_AUTH=true.
- tests/session-store.ts (7) — in-memory create/get/delete,
  auto-expiry on get, getStats prunes + biometricDataStored=false
  invariant, provider breakdown bumps.
- tests/usage.ts (16) — logApiCall fire-and-forget invariant
  (swallows errors), endpoint→counter routing (zkp_verifications,
  zkp_registrations, saml_auths, oidc_auths, total_requests),
  checkQuota allowed/used/limit logic with -1 unlimited fast-path.
- tests/platform.ts (18) — recordAuditEvent INSERT shape,
  AuditActor plumbing (issue #26 F-3): console → actor_type=console
  + actor_email in metadata, v1 → actor_type=api_key, missing actor
  → default to api_key+null. Tenant-scoping (A-01) assertions:
  every listDevices/listTenantUsers/listAuditEvents WHERE clause
  includes tenant_id AND environment. sanitizeLimit boundaries
  ([1,100] clamp, default 50, negative clamps to 1).
- tests/leads.ts (20) — POST /pilot validation + persist, lower-case
  + trim, Postgres-unavailable degraded path, DB-error-doesn't-leak,
  POST /whitepaper download URL, GET /api/leads admin gating + type
  filter + injection-resistance (invalid ?type ignored).

Verifier (verifier/tests/, +23):

- groth16.test.ts (9) — initVerifier handles missing vkey path,
  structural fallback returns structuralFallback=true, rejects
  wrong protocol / wrong curve / wrong-length pi_a / empty string
  in pi_a / non-string in pi_c / totally malformed object.
- server.test.ts (14) — supertest against the Express app:
  POST /verify envelope shape (200 + verifierAuditId uuid v4 +
  latencyMs + circuitVersion + structuralFallback), 400s for
  missing proof / missing publicSignals / length != 3 / non-array,
  custom circuitVersion echo, unique verifierAuditId per call,
  monotonic uptime, GET /health degraded when no vkey, 404 on
  unknown routes including GET /verify.

Infra:

- verifier/jest.config.js added (ts-jest preset, tests in
  verifier/tests/)
- verifier/package.json test script wired
- verifier/tests/ directory created
- All 18 jest devDeps pulled in via npm workspace install

Typecheck both packages clean. Lint 0 errors (10 pre-existing
warnings unchanged).

What's still untested (deferred — lower priority):

- src/services/db.ts pg pool wrapper (thin, hard to unit-test
  meaningfully without spinning up Postgres)
- src/services/logger.ts (winston wrapper, no logic)
- src/types/ (type declarations only)
- src/config/ (env var parsing — exercised via every other test)
- src/middleware/tenant-auth.ts unit (already covered by
  integration via central-api.test.ts + console-proxy.test.ts)
- src/server.ts startup (covered by deployment smoke + e2e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant