Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add message redaction #524

Merged
merged 29 commits into from Apr 9, 2024
Merged
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6f44ee6
First draft of message-redaction
progval May 25, 2023
d6d45f6
Add UNKNOWN_MSGID fail code
progval May 25, 2023
b092e88
must ignore the cap's value
progval May 26, 2023
0e0f71c
Mention sending REDACT in chathistory batches on join.
progval May 26, 2023
323454d
s/DELETE/REDACT/ in examples
progval May 27, 2023
4efeb02
Add a note about leaking message existence
progval May 29, 2023
4962974
fix typo in intro
progval May 29, 2023
4432a2d
I can't type
progval May 29, 2023
15f353d
really
progval May 29, 2023
6328b52
s/editable/redactable/
progval May 30, 2023
6fe3a60
Mention clients should check the target matches the msgid
progval May 30, 2023
a70a629
Fix chanop redact example
progval May 31, 2023
4ba56db
Remove another reference to edits
progval May 31, 2023
6b2074b
labeled-response isn't required
progval May 31, 2023
4e0d316
Remove "replace it with the REDACT message" option
progval Jun 1, 2023
d270474
Add 'FAIL REDACT INVALID_TARGET'
progval Jun 3, 2023
d5edb9b
Remove extraneous <window> from 'FAIL REDACT UNKNOWN_MSGID'
progval Jun 3, 2023
06d4c3c
Explicit the types of messages which can be redacted
progval Nov 17, 2023
0629dd4
Fix/clarify grammar
progval Dec 1, 2023
9a97dc1
Remove redundant restriction on msgid grammar
progval Dec 1, 2023
0258e52
Clarify PRIVMSG/NOTICE content replacement
progval Dec 1, 2023
eea9ec4
Remove msgid from REDACT messages in examples
progval Dec 1, 2023
1680c6b
Fix typo
progval Dec 1, 2023
8ab12e9
Clarify when to send REDACT on join
progval Dec 1, 2023
dfc1d8b
Describe 'reason' parameter
progval Dec 1, 2023
89e6a3c
s/second parameter/content/
progval Dec 1, 2023
8fb0a99
Clarify the position of REDACT messages in chathistory batches
progval Dec 1, 2023
16ccba5
Re-add 'Message validation' section
progval Feb 22, 2024
2ef31eb
fix swapped links
progval Feb 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
206 changes: 206 additions & 0 deletions extensions/message-redaction.md
@@ -0,0 +1,206 @@
---
title: Message redaction
layout: spec
work-in-progress: true
copyrights:
-
name: "James Wheare"
email: "james@irccloud.com"
period: "2020"
-
name: "Val Lorentz"
email: "progval+ircv3@progval.net"
period: "2023"
---

## Notes for implementing work-in-progress version

This is a work-in-progress specification.

Software implementing this work-in-progress specification MUST NOT use the
unprefixed `message-redaction` capability name.
Instead, implementations SHOULD use the `draft/message-redaction` capability
name to be interoperable with other software implementing a compatible
work-in-progress version.

The final version of the specification will use an unprefixed capability name.

## Introduction

This specification enables messages to be deleted.
Use cases include retracting accidentally sent messages, moderation,
and removing a [`+draft/react` client tag][], amongst others.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should happen to existing reactions to the redacted message? And what should happen to attempts to redact such reacts later?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely think that react needs a way to unreact that doesn't rely on this spec. We can maybe mention that reactions can be REDACTed and this should have the same result, but that probably belongs in the react spec, not this one.

I would rather remove all references to react in this spec, but I can't think of another TAGMSG for the examples section. Original discussion here: https://github.com/ircv3/ircv3-specifications/pull/425/files#r602543189

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to have it both in the intro of this spec, and formally in the react spec

These are cosmetic use cases and do not provide any operational security
guarantees.

## Architecture

### Dependencies

Clients wishing to use this capability MUST negotiate the [`message-tags`][]
capability with the server.
Clients SHOULD negotiate the [`echo-message`][] capability in order to receive
message IDs for their own messages, so they can be redacted.


### Capability

This specification adds the `draft/message-redaction` capability.
Clients MUST ignore this capability's value, if any.

Implementations that negotiate this capability indicate that they are
capable of handling the command described below.


### Command

To redact a message, a client MUST negotiate the `draft/message-redaction`
capability and send a `REDACT` command to a target nickname or channel.
The command is defined as follows:

REDACT <target> <msgid> [<reason>]

Where `<msgid>` is the id of the message to be redacted, which MUST be a
`PRIVMSG`, `NOTICE`, or `TAGMSG`.

An optional `<reason>` MAY be provided. As the last parameter, it MAY contain spaces.
If the client is authorised to delete the message, the server:

* SHOULD forward this `REDACT`, with an appropriate prefix, to the target
recipients that have negotiated the `draft/message-redaction` capability, in the
same way as PRIVMSG messages.
* MUST not forward this `REDACT` to target recipients that have not negotiated
this capability (see "Fallback" below)

### Chat history

After a message is redacted, [`chathistory`][] responses SHOULD either:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to note that REDACT messages should be returned as part of regular chathistory requests too, as described in https://github.com/ircv3/ircv3-specifications/pull/524/files#r1213533699.


* exclude it entirely
* replace its content and/or tags with a placeholder and
add the `REDACT` message to the response (not counting toward message limits)
jwheare marked this conversation as resolved.
Show resolved Hide resolved
progval marked this conversation as resolved.
Show resolved Hide resolved
after the redacted message
* add the `REDACT` message to the response (not counting toward message limits)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this interact with the event-playback cap?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in, redacting JOIN/PART/... messages?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question is basically: are REDACT messages always returned by chathistory regardless of event-playback?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say yes. The motivation for event-playback is that it's hard to deal with channel state (membership, op list, ...) and not necessarily very useful, right? Here this shouldn't be an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I agree.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be specified in this spec?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not counting toward message limits

This is at odds with #437 (comment).

Clients have no way to differentiate between a REDACT returned implicitly by chathistory due to another message, or a standalone REDACT message,

Standalone REDACT messages are important to return in the case of a mobile client synchronizing its history at regular intervals via chathistory. Example:

  • A PRIVMSG is sent at 20:00
  • A mobile client synchronizes, gets the PRIVMSG via chathistory
  • A REDACT is sent at 20:30
  • The mobile client synchronizes again, queries all messages sent strictly after 20:00

The server must return REDACT at that point, or else the client misses it.

Copy link
Contributor Author

@progval progval Jun 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do clients need to differentiate between the two?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the linked discussion above, my clients check whether there is more history to fetch by counting the number of messages. If it's less than the limit, no more messages.

Hm, but now that I've written this, this would only cause the number of messages to exceed the limit, causing needless but harmless chathistory requests in the edge case where there are no more messages. So it should be all fine?

Does a standalone REDACT count towards the limit? I'd say yes. This draws a line between "standalone" and "context" messages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't the linked discussion settle on the empty batch to signify the end?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The discussion hasn't really settled AFAIU, and my clients are still doing the limit check.

Please note, there is an interleaved discussion about what should happen when a channel has chathistory disabled, and this one has settled on empty batches instead of a FAIL. But it's unrelated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh, true

Copy link
Contributor

@emersion emersion Jun 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two ways to fix this issue that I see:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does a resolution to this issue require changes to the redaction spec, or just to the chathistory spec? i.e. is this a blocker for merge/ratification?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only the chathistory spec IMO

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just spotted this other comment from @emersion that appears unaddressed https://github.com/ircv3/ircv3-specifications/pull/524/files#r1213547049

This PR has become a bit of a nightmare to review lol.

after the redacted message

### Errors

This specification defines `FAIL` messages using the [standard replies][]
framework for notifying clients of errors with message editing and deletion.
The following codes are defined, with sample plain text descriptions.

* `FAIL REDACT INVALID_TARGET <target> :You cannot delete messages from <target>`
* `FAIL REDACT REDACT_FORBIDDEN <target> <target-msgid> :You are not authorised to delete this message`
* `FAIL REDACT REDACT_WINDOW_EXPIRED <target> <target-msgid> <window> :You can no longer edit this message`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the window communicated to clients?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, it's not. It could be an informational mode though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an easy thing to add later if needed. I don't believe it's worth blocking this PR because of this.

* `FAIL REDACT UNKNOWN_MSGID <target> <target-msgid> :This message does not exist or is too old`

## Client implementation considerations

It is strongly RECOMMENDED that clients provide visible redaction history to users.
This helps ensure accountability, and mitigates abuse through malicious or
surreptitious redaction. This could be done via a tool tip, or a separate log.
Redacted messages MAY be hidden entirely from the primary message log,
but a deletion log SHOULD be made available.

For the purposes of user interface, clients MAY assume that their own messages
are redactable.
However, this will not always be the case, and there could be other messages
that they have permission to act on.
Pending a mechanism for discovering redaction permissions, clients SHOULD
allow users to attempt to delete any message via some mechanism.

Clients SHOULD NOT provide a default reason if users do not provide one.

When a `REDACT` command's `msgid` parameter references a known message not in
the `target`'s history, clients MUST ignore it.
This allows servers to safely relay `REDACT` commands targeting messages which they
did not keep in their history.

## Server implementation considerations

This section is non-normative.

A key motivation for specifying this capability as a server tag, rather than
a client-only message tag, is to enable more granular redaction permissions.
Clients might be able to determine which messages are their own, but other
use cases would not be feasible without server validation.

Such use cases might include:

* Allowing channel moderators or server admins to delete unwelcome messages from others
* Specifying a cut-off time after which message edits are no longer allowed

jwheare marked this conversation as resolved.
Show resolved Hide resolved
If a message is redacted while a client is not present in a channel, servers may send the `REDACT` command in a `chathistory` batch when it re-joins the channel.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If a message is redacted while a client is not present in a channel, servers may send the `REDACT` command in a `chathistory` batch when it re-joins the channel.
Servers may send the `REDACT` command in a `chathistory` batch.

Removes the implication that servers are tracking whether clients are present in a channel or not.

Should this section be in the normative part of the spec?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implication was intentional. And the normative already says REDACT can be sent in chathistory batches.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec talks about the chathistory spec, not chathistory batches.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh. I guess I meant all chathistory batches rather than just chathistory responses

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure why this implication is necessary. Which servers keep track of past membership when determining whether to send REDACTs in chathistory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none of them, but they could if they wanted to

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could apply to a lot of things, what's the motivation for the special case here. Are you thinking of this in the context of e.g. the server can send a REDACT and omit the original PRIVMSG?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, so that clients end up showing the same things as if they were in the channel the whole time


If servers use predictable or guessable `msgid`s, they should consider whether errors
returned on `REDACT` may leak a message's existence to users who did not receive it
(in a channel they are/were not in or in private messages).

### Message validation

To implement validation, servers require a mechanism for determining the permissions of
a particular edit or delete action.
The user requesting the action would need to be compared against properties of
the message, given only the message ID and target.

Servers with message history storage could look up the message properties from the ID,
but this might not be possible or desirable in all cases.
Another mechanism could involve encoding any required properties within the message ID
itself, e.g. the account ID, timestamp, etc. Servers might choose to encrypt this
information if it isn't usually public facing. Any information encoded in a message ID
is still opaque and not intended to be parsed by clients.

### Fallback

Server implementations might choose to inform clients that haven't negotiated
the capability that a deletion has taken place.
The fallback method used (if any) is left up to server implementations, but
could take the form of a standard NOTICE or PRIVMSG with information about the
action.
It might be preferable to use relative time descriptions if referring to
messages in the past, for example:

:irc.example.com NOTICE #channel :nickname redacted a message from othernick from 5 seconds ago: spam

Implementations might also choose not to send a fallback, if this behaviour
is considered too noisy for users.

## Security considerations

The ability to delete messages does not offer any information or operational
security guarantees.
Once a message has been sent, assume that it will remain visible to any
recipients or servers, whether or not it is subsequently redacted.
Above all else, clients that do not support this specification will not see
any changes to the original message.

## Examples

Deleting a PRIVMSG:

C: PRIVMSG #channel :an example
S: @msgid=123 :nick!u@h PRIVMSG #channel :an example
C: REDACT #channel 123 :bad example
S: :nick!u@h REDACT #channel 123 :bad example

Deleting a TAGMSG:

C: @draft/react=🤞TAGMSG #channel
S: @msgid=123;draft/react=🤞TAGMSG #channel
C: REDACT #channel 123
S: :nick@u@h REDACT #channel 123

Deleting someone else's PRIVMSG:

C1: PRIVMSG #channel :join my network for cold hard chats
S: @msgid=123 :nick!u@h PRIVMSG #channel :join my network for cold hard chats
C2: REDACT #channel 123 spam
S: :chanop!u@h REDACT #channel 123 spam


[`echo-message`]: ../extensions/echo-message.html
[`+draft/react` client tag]: ../client-tags/react.html
[standard replies]: ../extensions/standard-replies.html
[`message-tags`]: ../extensions/message-tags.html
[`msgid`]: ../extensions/message-tags.html
[`chathistory`]: ../extensions/message-tags.html
progval marked this conversation as resolved.
Show resolved Hide resolved