fix(verify): per-contact context in output, drop noisy duplicate-stanza-id warning #115

Manually merged
jabber.developer2 merged 1 commits from fix/verify-per-contact-context into master 2026-05-06 14:11:15 +00:00
Collaborator

Summary

Follow-up to the flat-file backend (#94) — three issues with /history verify output that surfaced on real-world history.

1. Flatfile output didn't identify which contact

Every issue was reported as history.log:NNN — ... regardless of contact. With many contacts in flatlog/<account>/, the user has no way to tell which history.log the message refers to.

Fix: _verify_contact_dir now reconstructs the contact JID from the directory name (reversing _at_@) and uses <contact>/history.log as the basename for every issue from that contact.

2. Duplicate stanza-id was reported as WARNING

Older clients (Pidgin, Adium, early Profanity) reuse client-generated stanza-ids across distinct messages. On a long history this floods /history verify with dozens-to-hundreds of false positives.

Fix: demoted to log_debug — kept for diagnostics in the log file, removed from verify output. Duplicate archive-id stays at WARNING since XEP-0359 server-generated stanza-ids are required to be unique and a collision is a genuine integrity defect.

3. SQLite timestamp-ordering false positives across conversations

The query joined adjacent rows by B.id = A.id + 1 without filtering by conversation pair. With overlapping conversations (alice and bob active simultaneously), adjacent SQL rows belong to different contacts — their timestamps legitimately go out of order, but the verify reported every such pair as Timestamp out of order.

Fix: query now joins on matching from_jid/to_jid and uses a NOT EXISTS subquery to ensure B is the actually-next row in the same conversation. Both timestamp-ordering and broken-LMC-reference messages also include from_jid↔to_jid for context.

Test plan

  • /history verify on a flatfile with 5+ contacts — every issue line names the contact
  • Same on a flatfile that contains stanza-id collisions from a Pidgin peer — no spurious WARNING entries, only debug-log entries in ~/.local/share/profanity/logs/profanity.log
  • /history switch sqlite && /history verify on a db with multiple parallel conversations — no spurious Timestamp out of order between cross-contact adjacent rows
  • Real timestamp-ordering or LMC-reference defects are still reported, with from↔to JID pair in the message
## Summary Follow-up to the flat-file backend (#94) — three issues with `/history verify` output that surfaced on real-world history. ### 1. Flatfile output didn't identify which contact Every issue was reported as `history.log:NNN — ...` regardless of contact. With many contacts in `flatlog/<account>/`, the user has no way to tell which `history.log` the message refers to. **Fix**: `_verify_contact_dir` now reconstructs the contact JID from the directory name (reversing `_at_` → `@`) and uses `<contact>/history.log` as the basename for every issue from that contact. ### 2. Duplicate stanza-id was reported as WARNING Older clients (Pidgin, Adium, early Profanity) reuse client-generated stanza-ids across distinct messages. On a long history this floods `/history verify` with dozens-to-hundreds of false positives. **Fix**: demoted to `log_debug` — kept for diagnostics in the log file, removed from verify output. **Duplicate archive-id stays at WARNING** since XEP-0359 server-generated stanza-ids are required to be unique and a collision is a genuine integrity defect. ### 3. SQLite timestamp-ordering false positives across conversations The query joined adjacent rows by `B.id = A.id + 1` without filtering by conversation pair. With overlapping conversations (alice and bob active simultaneously), adjacent SQL rows belong to different contacts — their timestamps legitimately go out of order, but the verify reported every such pair as `Timestamp out of order`. **Fix**: query now joins on matching `from_jid`/`to_jid` and uses a `NOT EXISTS` subquery to ensure B is the actually-next row in the same conversation. Both timestamp-ordering and broken-LMC-reference messages also include `from_jid↔to_jid` for context. ## Test plan - [ ] `/history verify` on a flatfile with 5+ contacts — every issue line names the contact - [ ] Same on a flatfile that contains stanza-id collisions from a Pidgin peer — no spurious WARNING entries, only debug-log entries in `~/.local/share/profanity/logs/profanity.log` - [ ] `/history switch sqlite && /history verify` on a db with multiple parallel conversations — no spurious `Timestamp out of order` between cross-contact adjacent rows - [ ] Real timestamp-ordering or LMC-reference defects are still reported, with `from↔to` JID pair in the message
jabber.developer2 added 1 commit 2026-05-06 11:27:46 +00:00
fix(verify): per-contact context in output, demote duplicate stanza-id to debug
Some checks failed
CI Code / Check spelling (pull_request) Successful in 19s
CI Code / Check coding style (pull_request) Failing after 32s
CI Code / Code Coverage (pull_request) Successful in 2m24s
CI Code / Linux (debian) (pull_request) Successful in 4m36s
CI Code / Linux (arch) (pull_request) Successful in 5m39s
CI Code / Linux (ubuntu) (pull_request) Successful in 6m53s
b89f688d70
jabber.developer requested changes 2026-05-06 11:54:34 +00:00
Dismissed
jabber.developer left a comment
Owner

please address the issues pointed out in the review and use make format

please address the issues pointed out in the review and use `make format`
@@ -306,0 +311,4 @@
// own history.log, so the bare filename is ambiguous).
auto_gchar gchar* dir_name = g_path_get_basename(cdir_path);
char* dir_unescaped = str_replace(dir_name, "_at_", "@");
auto_gchar gchar* basename_owned = g_strdup_printf("%s/history.log",

It's not an accurate path. Just avoid using /history.log suffix (preferred) or do not unescape the path.

The only two valid ways:

  • Show unescaped jid
  • Show accurate path
It's not an accurate path. Just avoid using /history.log suffix (preferred) or do not unescape the path. The only two valid ways: - Show unescaped jid - Show accurate path
jabber.developer marked this conversation as resolved
@@ -306,0 +313,4 @@
char* dir_unescaped = str_replace(dir_name, "_at_", "@");
auto_gchar gchar* basename_owned = g_strdup_printf("%s/history.log",
dir_unescaped ? dir_unescaped : dir_name);
free(dir_unescaped);

we could use auto_char instead

we could use `auto_char` instead
jabber.developer marked this conversation as resolved
jabber.developer2 force-pushed fix/verify-per-contact-context from b89f688d70 to 1aaa382d5e 2026-05-06 14:02:30 +00:00 Compare
jabber.developer approved these changes 2026-05-06 14:10:34 +00:00
jabber.developer left a comment
Owner

LGTM

LGTM
jabber.developer2 manually merged commit 1aaa382d5e into master 2026-05-06 14:11:15 +00:00
Sign in to join this conversation.
No description provided.