remarkbox/docs/tickets/0.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.2 KiB

T0: User profile leaks comments across namespaces

Status: resolved Priority: high Source: meta cc62eb06-8e4b-11ea-93cc-040140774501 Filed: 2026-02-01

Problem

Clicking a username on any site with Remarkbox installed shows ALL that user's comments from every namespace. A commenter on site A can see all their comments from sites B, C, D on the profile page. Russell marked the original thread as fixed, but the code still has no namespace filtering.

Xii also reported that unapproved comments leaked cross-namespace. The approved == True filter in page_nodes() now prevents that specific leak, but the cross-namespace exposure remains.

Root Cause

User.page_nodes() in remarkbox/models/user.py:266-276 queries all nodes for a user with no namespace filter:

def page_nodes(self, limit=100, offset=0):
    return (
        self.nodes.filter(
            Node.disabled == False, Node.verified == True,
            Node.user_id != None, Node.approved == True
        )
        .order_by(Node.changed.desc())
        .limit(limit)
        .offset(offset)
    )

The user_nodes() view in remarkbox/views/list_nodes.py:114-137 calls subject_user.page_nodes() without passing any namespace context. The same issue affects verified_nodes, unverified_nodes, disabled_nodes, and unapproved_nodes properties on the User model.

Proposed Fix

  1. Add a namespace parameter to User.page_nodes() that filters Node.namespace_id == namespace.id
  2. Update user_nodes() view to pass request.namespace (or derive it from the embed/site context)
  3. Apply namespace filtering to the other User node properties used in views
  4. Ensure namespace-specific settings (hide_unless_approved, hide_unverified) are respected

Files

  • remarkbox/models/user.py — add namespace filter to page_nodes() and related properties
  • remarkbox/views/list_nodes.py — pass namespace context to user queries
  • remarkbox/tests/test_views.py — regression test: user profile only shows same-namespace comments

Acceptance Criteria

  • User profile page only shows comments from the current namespace
  • Namespace moderation settings are respected on the profile page
  • Regression test prevents reintroduction