Skip to content

test: pin the delivery callback, JWT, and audience opt-out - #112

Draft
cursor[bot] wants to merge 3 commits into
productionfrom
cursor/missing-test-coverage-dfba
Draft

test: pin the delivery callback, JWT, and audience opt-out#112
cursor[bot] wants to merge 3 commits into
productionfrom
cursor/missing-test-coverage-dfba

Conversation

@cursor

@cursor cursor Bot commented Sep 3, 2026

Copy link
Copy Markdown

Coverage for recently merged production paths that shipped without tests, or whose tests never ran in CI.

Risky behavior now covered

  • Delivery confirmation (POST /api/responses/delivered): unset/empty callback token fails closed (503, not "no auth"); bearer mismatch including length mismatch is 401 without throwing; traversal-shaped session ids are 400; the UPDATE is write-once (pdf_delivered_at IS NULL) so a re-send cannot restart the shred clock.
  • Key-box callback (notifyDelivered): a 404 is logged rather than treated as success — the failure that left pdf_delivered_at unset for months; a network miss cannot fail a send that already happened.
  • Key-box push (pushBundle): unconfigured / non-2xx / network failure all become a contentless KeyboxUnavailableError, so a log line cannot carry the questionnaire.
  • Questionnaire JWT: round-trip carries the email hash, never the address; tamper, wrong secret, expiry, and missing JWT_SECRET fail closed; the secret is read per call (the boot-order trap).
  • Audience middleware: /api/health and /api/metrics are not visitors; GPC and DNT opt out; counting cannot change the response.
  • Shared utilities: Gmail normalisation and suspicious-pattern rejection; question-order invariants (gate questions stay out of a post-gate shuffle); HMAC key non-extractability; funnel index mapping.

Test files added/updated

  • routes/api/responses/delivered_test.ts (new)
  • romania/tests/callback_test.ts (new)
  • lib/romania-client_test.ts (new)
  • lib/jwt_test.ts (new)
  • routes/_middleware_test.ts (new)
  • lib/emailValidator_test.ts (new)
  • lib/questionnaire_test.ts (new)
  • lib/crypto_test.ts (new)
  • lib/metrics_test.ts (new)
  • .github/workflows/ci.yml — these suites, plus existing lib/audience_test.ts, lib/client-ip_test.ts, lib/qr-scans_test.ts, and romania/tests/, now run on the check job.

Tiny production changes only where tests required them: KEYBOX_RENDER_* and RENDER_CALLBACK_* are read on each call (same boot-order trap lib/jwt.ts already documents), and notifyDelivered is exported. No delivery, auth, or counting behavior otherwise changes.

Why this reduces regression risk

The callback route existed to stamp delivery and start the shred clock; without tests, a 404 or an unset token could (and did) look like success. JWT verification is the resume capability: an expiry skip or an address in the payload would be a privacy and auth break with no other alarm. Audience middleware claims "bookkeeping cannot change what a visitor receives" and honours GPC/DNT — those were untested request-path contracts. CI was not running the lib/romania suites that already existed, so they could not have stopped a repeat.

Hermetic: no Postgres, no SMTP, no live key box. fetch is stubbed. 184 passed locally on the expanded CI command (12 romania PDF tests ignored where typst/qpdf are absent).

Open in Web View Automation 

cursoragent and others added 2 commits September 3, 2026 20:34
…WT that must not carry an address

The delivery confirmation route, the key-box callback, and questionnaire
JWTs shipped without tests. Pin fail-closed auth, write-once pdf_delivered_at,
GPC/DNT opt-out, and session tokens that verify as hashes not mailboxes.

Read KEYBOX_RENDER_* and RENDER_CALLBACK_* on each call (same boot-order
trap jwt.ts already documents) so the tests can set them, and so a missing
.env at import cannot lock the consent path into "unavailable" forever.

Co-authored-by: Ralphie B. <nyagrodha@users.noreply.github.com>
… nowhere

These suites already existed or just landed; the check job never invoked
them. Add --allow-write for keystore temp dirs. Leave tests/ out: it still
carries the pre-existing type errors that fail before any test executes.

Co-authored-by: Ralphie B. <nyagrodha@users.noreply.github.com>
Keep production's lib/gate_encrypt_test.ts on the check job alongside the
delivery, auth, and audience suites this branch already added. The two
edits collided on the same deno test path list after #113 landed.

Co-authored-by: rbauer <rbauer@colorado.edu>
cursor Bot pushed a commit that referenced this pull request Sep 7, 2026
Union the CI test path lists so this branch (consent, session-key
injection, contact rate-limit) no longer conflicts with the delivery/JWT
suites from #112 or with production's gate_encrypt_test.ts from #113.

Co-authored-by: rbauer <rbauer@colorado.edu>
cursor Bot pushed a commit that referenced this pull request Sep 7, 2026
Union visitor-counting, questionnaire-auth, and session-cleanup tests
with the stacked coverage from #112#116. Deduplicate rust-server/target
in .gitignore. This branch now merges cleanly into production and
contains the earlier cursor test PRs, so they no longer conflict.

Co-authored-by: rbauer <rbauer@colorado.edu>
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