History is keyed by name, so the next holder of a nick or of a channel name can read the previous holder's messages #148

Closed
opened 2026-10-20 17:04:05 +02:00 by clawbot · 1 comment
Collaborator

GET /api/v1/history selects messages by msg_to alone (GetHistory and queryHistory in internal/db/queries.go), and canAccessHistory (internal/handlers/api.go) allows a DM target that equals the caller's current nick and a channel the caller is a member of now. Nicks are released on QUIT and channels are deleted when empty (README.md, Nick Semantics and Channels), and both names can be taken again by anyone. The messages stay. Seen on eceb5f2:

  • dmA sends a DM to victimV; victimV sends QUIT; a third user changes nick to victimV and GET /api/v1/history?target=victimV returns dmA's message to the first victimV.
  • roomR creates #priv, sets +k topsecret, says something, and parts, which deletes the channel; a stranger who never had the key joins #priv (creating it again, as operator) and GET /api/v1/history?target=%23priv returns roomR's message.

That is one user reading another's messages.

Reading: README.md settles this. It makes the server-assigned user ID the stable identity and a nick a display name, and lets only a channel's members read its history. So history is bound to identity, not to the name: each message row records the recipient's session id for a DM and the channel row's id for a channel message, and history selects by those. Session and channel ids are AUTOINCREMENT, so they are never reused. A channel created again starts with no history; a reused nick sees nothing of its previous holder. Queue delivery (client_queues) and MESSAGE_MAX_AGE pruning are unchanged. The schema change goes in internal/db/schema/001_initial.sql.

Definition of done

  1. GET /api/v1/history for a nick returns only DMs sent to the calling session, and for a channel only messages sent to the current channel row.
  2. The two scenarios above return nothing to the newcomer; handler tests in internal/handlers for both, and the existing history and paging tests still hold.
  3. The schema section and the history section of README.md match the code.
  4. One reviewed PR against next.

Model: fable-5-1 (audit); opus-5-5 (reading and brief)

`GET /api/v1/history` selects messages by `msg_to` alone (`GetHistory` and `queryHistory` in `internal/db/queries.go`), and `canAccessHistory` (`internal/handlers/api.go`) allows a DM target that equals the caller's current nick and a channel the caller is a member of now. Nicks are released on QUIT and channels are deleted when empty (`README.md`, Nick Semantics and Channels), and both names can be taken again by anyone. The messages stay. Seen on `eceb5f2`: - `dmA` sends a DM to `victimV`; `victimV` sends QUIT; a third user changes nick to `victimV` and `GET /api/v1/history?target=victimV` returns `dmA`'s message to the first `victimV`. - `roomR` creates `#priv`, sets `+k topsecret`, says something, and parts, which deletes the channel; a stranger who never had the key joins `#priv` (creating it again, as operator) and `GET /api/v1/history?target=%23priv` returns `roomR`'s message. That is one user reading another's messages. Reading: `README.md` settles this. It makes the server-assigned user ID the stable identity and a nick a display name, and lets only a channel's members read its history. So history is bound to identity, not to the name: each message row records the recipient's session id for a DM and the channel row's id for a channel message, and history selects by those. Session and channel ids are `AUTOINCREMENT`, so they are never reused. A channel created again starts with no history; a reused nick sees nothing of its previous holder. Queue delivery (`client_queues`) and `MESSAGE_MAX_AGE` pruning are unchanged. The schema change goes in `internal/db/schema/001_initial.sql`. ## Definition of done 1. `GET /api/v1/history` for a nick returns only DMs sent to the calling session, and for a channel only messages sent to the current channel row. 2. The two scenarios above return nothing to the newcomer; handler tests in `internal/handlers` for both, and the existing history and paging tests still hold. 3. The schema section and the history section of `README.md` match the code. 4. One reviewed PR against `next`. Model: fable-5-1 (audit); opus-5-5 (reading and brief)
sneak was assigned by clawbot 2026-10-20 17:04:05 +02:00
sneak was unassigned by clawbot 2026-10-20 17:15:16 +02:00
clawbot self-assigned this 2026-10-20 17:15:16 +02:00
Author
Collaborator

No decision needed from the owner: README.md already makes the user ID the identity and limits channel history to members, so history bound to the session and channel ids is built, as the audit recommended. The body is now the implementer's brief.

Model: opus-5-5

No decision needed from the owner: `README.md` already makes the user ID the identity and limits channel history to members, so history bound to the session and channel ids is built, as the audit recommended. The body is now the implementer's brief. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/neoirc#148