← All docs

Known Limitations

Authentication

  • DID method support: Only did:plc and did:web are supported.
    Other DID methods (e.g. did:key, did:ion) are not implemented.
  • Key rotation: If a user rotates their DID document keys, existing
    sessions are not invalidated. The server does not poll for key changes.
  • Handle verification: The server resolves handles to DIDs at auth time
    but does not re-verify handles periodically. If a handle changes ownership,
    the server won't notice until the next authentication.
  • DPoP nonce rotation: PDS nonce rotation during SASL is handled via
    automatic retry (server signals nonce, client retries). If the PDS rotates
    nonces again during the retry, authentication will fail (requires reconnect).

IRC Protocol

  • No user limits (+l): Channel user limits are not implemented.
  • No secret/private channels (+s/+p): Channels always appear in LIST.
  • No WALLOPS, LINKS, STATS: Server-to-server informational commands
    are not implemented.
  • USERHOST is simplified: Returns nick@host with a cloaked hostname
    rather than the real connected host.
  • No services integration (NickServ/ChanServ): Identity is DID-based,
    not services-based.
  • Multiline messages degrade for clients that don't negotiate
    draft/multiline
    : those clients see N separate PRIVMSGs (one per
    chunk), and only the first carries the message's msgid. Editing the
    message replaces only that first row in their UI — the trailing rows
    of the original chain stay around as orphans. Deletes have the same
    shape (only row 1 disappears; rows 2-N remain). Reactions are
    correctly attributed to the right logical message but visually attach
    to the first row only. Workaround: client negotiates draft/multiline
    during CAP REQ. See MULTILINE-CLIENT-COMPATIBILITY.md
    for the full wire-shape comparison.
  • Multiline in +E channels requires the receiver to negotiate
    draft/multiline for messages larger than a single line of
    ciphertext
    (~5.6 KB plaintext / ~7.5 KB ciphertext). Smaller
    messages ride in a single +encrypted PRIVMSG and are unaffected.
    Larger messages are sent as ciphertext-chunked across a multiline
    BATCH with +draft/multiline-concat; fallback receivers see the
    fragments as separate PRIVMSGs, none of which decrypt individually
    (they're slices of one AES-GCM ciphertext). Note that vanilla IRC
    clients in +E channels have no useful UX regardless — they can't
    decrypt any ENC1 blob, multiline or not. See
    MULTILINE-CLIENT-COMPATIBILITY.md.

S2S Federation

  • Channel key removal: -k cannot propagate via SyncResponse (additive
    only). Needs a protocol change or CRDT-backed key state.
  • Outgoing peer enforcement: --s2s-allowed-peers only checks incoming
    connections. Outgoing connections go to whatever --s2s-peers specifies.
    Ensure both flags are consistent for mutual authorization.
  • Founder race condition: If two servers simultaneously create the
    same channel, both may assign different founders. The CRDT resolves
    this deterministically after sync (first-write-wins), but there is a
    brief inconsistency window.
  • Topic merge strategy: SyncResponse ignores remote topic if local is set,
    but CRDT reconciliation uses last-write-wins. The two merge strategies can
    cause flapping in edge cases.
  • Federated identity is peer-vouched, not verified: a relayed message
    carries the sender's DID (account) and a +freeq.at/origin tag, but the
    receiving server does not verify it — it trusts the origin peer (the same
    trust the message body already rides on). The signature (+freeq.at/sig) is
    not verifiable across servers (its canonical inputs don't survive S2S), so
    clients render federated messages as "via {origin}" rather than locally
    verified. End-to-end verification is future work.

Persistence

  • No message retention by age: Message pruning is count-based only
    (--max-messages-per-channel). There is no --message-retention-days.
  • No full-text search: SQLite FTS5 is not wired up. Message search
    would require a separate index.
  • Single-server SQLite: The database is a single SQLite file. There
    is no replication or multi-server persistence (state sync happens at
    the CRDT/S2S layer instead).

E2EE

  • No forward secrecy for channels: Channel encryption keys are derived
    from a static passphrase. There is no ratcheting or key rotation.
    (DMs use X3DH + Double Ratchet and do have forward secrecy.)
  • Key distribution is manual: Users must share the channel passphrase
    out-of-band. There is no key exchange protocol for channels.
  • ENC2 group size: DID-based group encryption requires all members'
    DIDs to derive the group key. Very large groups would have slow key
    derivation.

Transports

  • WebSocket is uncompressed: No per-message compression.
  • iroh relay dependency: iroh uses relay servers for NAT traversal.
    If iroh's relay infrastructure is unavailable, direct connections may
    fail for users behind restrictive NATs.

Web Client

  • No offline mode: Requires active WebSocket connection. No service
    worker message caching.
  • No push notifications: Desktop notifications only work while the
    tab is open.

TUI Client

  • No auto-reconnection: If the connection drops, you must restart.
  • Not a full IRC client: The TUI is a reference implementation. It
    lacks DCC, scripts, multiple networks, etc.
  • No mouse support: Terminal mouse events are not handled.

Plugin System

  • Compiled-in only: Plugins must be compiled into the server binary.
    There is no dynamic loading. New plugins require a rebuild.
  • No async hooks: Plugin hooks are synchronous. Long-running plugin
    logic should spawn tasks rather than blocking the hook.
  • Limited hook set: Currently only on_connect, on_auth, on_join,
    on_message, and on_nick_change are available.

Resolved (no longer limitations)

The following were previously listed as limitations and have been fixed:

  • ~~No server operators (OPER)~~ → OPER command + --oper-dids auto-oper
  • ~~No hostname cloaking~~ → freeq/plc/xxxxxxxx for DID users, freeq/guest for guests
  • ~~No S2S ban enforcement~~ → Bans sync via S2S, enforced on join (nick + DID)
  • ~~No S2S authorization~~ → Mode/kick/topic/join all verified server-side
  • ~~No S2S invite sync~~ → Invites sync via S2S, consumed on join
  • ~~No CHATHISTORY~~ → IRCv3 CHATHISTORY with batch support
  • ~~No account-notify~~ → IRCv3 account-notify + extended-join
  • ~~Open federation by default~~ → --s2s-allowed-peers for allowlist mode
  • ~~Per-IP connection limits~~ → 20 connections/IP on TCP + WebSocket
Supported by
Powered by