chore(lotw): log the record TQSL refused

'No QSOs processed' (exit 8) covers already-uploaded, out-of-certificate-
date-range, and a station callsign that does not match the location being
signed with -- TQSL's message does not say which. An operator whose QSO
was refused and then accepted after a round trip through another logger
is reporting a difference in the record itself, and the temp ADIF is
deleted the moment TQSL returns, so that difference could not be seen.

Logged on any non-zero exit: the record verbatim, the exit code and the
station location. It is QSO data; the key password is not logged.
This commit is contained in:
2026-08-24 11:08:15 +02:00
parent 56c103140c
commit 1b63483596
2 changed files with 20 additions and 2 deletions
+16
View File
@@ -265,6 +265,22 @@ func UploadLoTW(ctx context.Context, cfg ServiceConfig, tempDir, adifRecord stri
// callsign certificate's validity is silently left out, and reporting that as
// success stamped it sent for ever. TQSL says which case it is in its output,
// so the message is carried up rather than replaced with a guess.
if code != 0 && LogSink != nil {
// The ADIF that was handed to TQSL, verbatim, and how TQSL was called.
//
// TQSL says "no QSOs processed" for several unrelated reasons — already
// uploaded, outside the certificate's dates, or a STATION_CALLSIGN that
// does not match the station location it was told to sign with — and its
// message does not distinguish them. An operator whose contact was
// refused, then accepted after a round trip through another logger, is
// reporting a difference in THIS RECORD, and there is no way to see it
// afterwards: the temp file is deleted as soon as TQSL returns.
//
// Nothing secret here: it is a QSO, and the key password is not logged.
LogSink("lotw: tqsl exit %d for station location %q", code, loc)
LogSink("lotw: record was: %s", strings.TrimSpace(adifRecord))
}
switch code {
case 0:
return UploadResult{OK: true, Message: "uploaded to LoTW"}, nil