remarkbox/docs/tickets/1.md
russell@unturf.com f1cffe2e79 Resolve all 14 tracked tickets (T0-T13)
High priority fixes:
- T0: Profile page now filters comments by namespace (was leaking cross-site)
- T1: URI hostnames and namespace names normalized to lowercase (was causing
  duplicate threads and "stock comments" bug). Includes merge script.
- T2: Thread detail API now paginated with SQL-side filtering (was 502 on
  267+ reply threads)

Features:
- T3: GDPR account deletion (tombstone user with scrubbed PII) and data export
- T4: Customizable button text and comment labels per namespace
- T5: Self-service namespace deletion for owners
- T6: @mention notifications with profile links
- T7: Webmention receiving endpoint with h-card extraction
- T8: Configurable max nesting depth and collapse depth per namespace
- T9: AJAX thread title search to prevent duplicates
- T10: Browser push notification support (VAPID/service worker)

Docs and housekeeping:
- T11: Documented thread_uri behavior when moving embeds
- T12/T13: Drafted community replies for resolved feature requests
- Collapse depth defaults to infinite (load-more disabled unless configured)

364 tests pass, 4 skipped.
2026-02-01 20:02:47 -05:00

2.8 KiB

T1: Namespace/URI case-sensitivity causes "stock comments" bug

Status: resolved Priority: high Source: FAQ 7eb0baec-2da1-11ef-b0c7-1f90b6841245, 6b21e360-ce62-11ef-b298-29ab4fb285a0 Filed: 2026-02-01

Problem

Users embed Remarkbox on their site and see pre-existing comments that don't belong to them ("stock comments"). Two separate FAQ threads report this for sparklingcyber.com and acrosstheborder.blog.

Root Cause

Same class of bug as the duplicate email accounts issue (see docs/postmortem-2026-01-29-duplicate-email-accounts.md). URIs and namespace names are compared case-sensitively:

  1. get_uri_by_uri() in remarkbox/models/uri.py:82Uri.data == unicode(external_uri) is case-sensitive
  2. get_namespace_by_name() in remarkbox/models/namespace.py:363Namespace.name == unicode(name) is case-sensitive

When a user visits https://Example.com/page vs https://example.com/page, two separate URIs, nodes, and potentially namespaces are created. The user on the lowercase variant sees an empty thread (or someone else's comments if they happen to share the same lowercase namespace).

Example scenario

Time 1: User A embeds on https://Example.com/blog
  → Uri "https://Example.com/blog" created
  → Namespace "Example.com" created
  → Comments posted here

Time 2: User B visits https://example.com/blog
  → Uri lookup for "https://example.com/blog" — no match (case differs)
  → New Uri, new Node created
  → Namespace "example.com" — no match, new namespace created (empty)
  → User B sees no comments or wrong comments

Proposed Fix

Follow the same pattern as the email fix:

  1. Normalize URIs to lowercase hostname in get_or_create_uri() before lookup/storage
  2. Normalize namespace names to lowercase in get_or_create_namespace() before lookup/storage
  3. Use func.lower() for comparisons in lookup functions
  4. Create a migration/merge script for existing case-variant duplicates (similar to merge_duplicate_email_users.py)
  5. Add regression tests

Files

  • remarkbox/models/uri.py — lowercase hostname normalization in get_or_create_uri(), case-insensitive lookup in get_uri_by_uri()
  • remarkbox/models/namespace.py — lowercase normalization in get_or_create_namespace(), case-insensitive lookup in get_namespace_by_name()
  • remarkbox/scripts/merge_duplicate_namespaces.py — new script to consolidate case-variant duplicates
  • remarkbox/tests/test_models.py — regression tests for case-insensitive URI and namespace matching

Acceptance Criteria

  • https://Example.com/page and https://example.com/page resolve to the same thread
  • Example.com and example.com resolve to the same namespace
  • Existing duplicate namespaces/URIs can be merged with a script
  • Regression tests prevent reintroduction