Skip to content

Channel Scoping by Timeline #493

@davxdo

Description

@davxdo

Problem

Channels are currently stored as Set with just the channel name. This causes namespace collision when users join the same channel on different timelines.

When a user joins #gaming on mesh (Bluetooth) and #gaming on geohash 9q8yy (Nostr), all messages mix together, violating timeline isolation.

Solution

Composite keys with timeline namespacing:

Format: "{timeline}:{identifier}:{channel}"

Examples:
mesh:#gaming
geo:9q8yy:#gaming
geo:dr5ru:#gaming

This scales naturally to:

  • ✅ Multiple geohashes (SF vs NYC)
  • ✅ Future timeline types (satellite, LoRa, etc.)
  • ✅ Backward compatibility (old keys → mesh: prefix)

Implementation

New: ChannelKeys Helper Object

Single source of truth for all composite key operations - create, parse, validate. Prevents string manipulation bugs and provides clean abstractions.

Core Changes

Component Change
ChannelManager Accept timeline param, create composite keys
Message Handlers Route to composite keys, support legacy message.channel field
UI Sidebar Group by timeline: "MESH 🔵" / "GEO 9q8yy 🌐" sections
DataManager Lazy migration: old "#gaming" → "mesh:#gaming"

Key Features

✅ Scalable - Works with N timelines without schema changes
✅ Backward Compatible - Auto-migration, supports legacy clients
✅ Clean Abstractions - ChannelKeys helper prevents duplication
✅ Type-Safe - Uses existing ChannelID sealed class

Why This Scales

  1. No schema changes - Still Set, just different string format
  2. Timeline-agnostic - Composite key pattern works for any future timeline type
  3. Zero migration cost - Normalization happens lazily on load
  4. Composable - Can extend to additional dimensions if needed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions