Skip to content

fix(lotw): filter QSOs by cert's allowed date range before upload#214

Open
patrickrb wants to merge 1 commit into
mainfrom
fix/lotw-cert-qso-date-range
Open

fix(lotw): filter QSOs by cert's allowed date range before upload#214
patrickrb wants to merge 1 commit into
mainfrom
fix/lotw-cert-qso-date-range

Conversation

@patrickrb
Copy link
Copy Markdown
Owner

Summary

LoTW silently rejects any QSO whose date falls outside the cert's QSO date range (ARRL X.509 extensions 1.3.6.1.4.1.12348.1.2 / .3) — separate from the cert's own X.509 notBefore / notAfter validity. Wavelog enforces this filter server-side before signing (application/controllers/Lotw.php:256-264 + get_lotw_qsos_to_upload); nextlog wasn't reading those extensions at all. The .tq8 still queues at LoTW with <!-- .UPL. accepted -->, so out-of-range QSOs got marked lotw_qsl_sent='Y' locally while LoTW quietly dropped them and emailed the cert holder a rejection notice.

K1AF's cert window is currently 2024-04-08 → 2027-04-08, so this isn't the cause of the issue we've been chasing today — but it is a real silent-failure bug. This PR makes it self-diagnose next time: an operator with an expired cert window will see the actual reason in the upload log instead of seeing "completed" while LoTW drops every QSO.

Changes

  • parseP12 reads ARRL OIDs .2 and .3 into qsoStartDate / qsoEndDate on the ParsedP12 result. Generalized the DER extraction into readArrlPrintableExt so it can share with the DXCC extension (OID .4).
  • isQsoWithinCertDateRange exported from lib/lotw.ts. End-of-day handling is inclusive through 23:59:59.999 UTC of the end date, matching wavelog's qso_end_date . ' 23:59:59'.
  • /api/lotw/upload pre-reads cert metadata, splits contacts into in-range / out-of-range / unsupported-prop-mode buckets, and writes both the count and the actual date window into the upload log's error_message (Skipped N QSOs outside cert's QSO date range (YYYY-MM-DD to YYYY-MM-DD)) so it shows up on /lotw.
  • /api/lotw/upload-contact rejects the single-QSO upload up front with the same human-readable error rather than queuing a file LoTW will silently drop.

Test plan

  • Upload a .p12 with a known QSO date range, then attempt to log + upload a QSO outside that range → upload-contact returns 400 with a clear date-range error
  • Bulk /api/lotw/upload with a mix of in-range and out-of-range contacts → only in-range get marked 'Y', log shows the skip count and date window
  • Bulk upload with all in-range contacts → behaves as before, no notice
  • Bulk upload where every contact is out of range → log row's error_message says No upload-eligible contacts (skipped N outside cert's QSO date range (...)) and 0 contacts get marked

🤖 Generated with Claude Code

LoTW silently rejects any QSO whose date falls outside the cert's
qso_start_date / qso_end_date window (ARRL X.509 OIDs .2 / .3), even
when the cert itself is within its notBefore/notAfter validity. Wavelog
enforces this server-side filter before signing
(application/controllers/Lotw.php:256-264 + get_lotw_qsos_to_upload);
nextlog wasn't reading those extensions at all and was relying on LoTW
to reject the file. LoTW's rejection isn't visible in the upload
response — the .tq8 still queues with <!-- .UPL. accepted --> — so
out-of-range QSOs got marked lotw_qsl_sent='Y' locally while LoTW
quietly dropped them.

Changes:

- parseP12 reads ARRL OIDs 1.3.6.1.4.1.12348.1.{2,3}, parsed into
  qsoStartDate / qsoEndDate on the ParsedP12 result. Generalized the
  DER extraction into readArrlPrintableExt to share with the DXCC
  field (OID .4).

- Added isQsoWithinCertDateRange helper exported from lib/lotw.ts.
  End-of-day handling is inclusive through 23:59:59.999 UTC of the
  end date, matching wavelog's `qso_end_date . ' 23:59:59'`.

- /api/lotw/upload pre-reads cert metadata via readCertMetadata,
  splits contacts into in-range / out-of-range / unsupported-prop-mode
  buckets, and reports the count + the actual date window in the
  upload log error_message ("Skipped N QSOs outside cert's QSO date
  range (YYYY-MM-DD to YYYY-MM-DD)") so it shows up on /lotw.

- /api/lotw/upload-contact rejects the single-QSO upload up front
  with the same human-readable date-range error rather than queuing
  a file LoTW will drop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nodelog Ready Ready Preview, Comment May 12, 2026 6:40pm

Request Review

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