You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Added docs for exposure report
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
* Minor fixes
---------
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Copy file name to clipboardExpand all lines: source/administration-guide/manage/admin/content-flagging.rst
+94-3Lines changed: 94 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -88,6 +88,7 @@ Reviewers can select **View details** to take action as follows:
88
88
- **Keep message**: Dismiss the quarantine and restore the message if it was hidden. The status of the quarantined message changes to **Retained**.
89
89
- **Add a comment**: Record the reason for the decision when required.
90
90
- **Generate a report**: Download a report of the quarantined message and review activity for record-keeping or incident response. See :ref:`administration-guide/manage/admin/content-flagging:generate a quarantined message report` for details.
91
+
- **Download exposure report**: Download a report of the users who may have been exposed to the quarantined message while it was visible in its channel. See :ref:`administration-guide/manage/admin/content-flagging:generate a post exposure report` for details.
91
92
92
93
Once an action is taken, the **Status** field updates automatically. The **Data Spillage Bot** sends follow-up notifications to the reporter, author, and other reviewers based on how Data Spillage Handling is configured.
93
94
@@ -106,15 +107,15 @@ If you choose to skip the report download from the **Remove message** or **Keep
106
107
107
108
If report generation fails (for example, due to a network interruption or session timeout), the dialog displays an error and offers a retry option. You can also skip the report and proceed with the action, or cancel and download the report later from the message details.
108
109
109
-
Each time a reviewer generates a report, the **Data Spillage Bot** notifies all content reviewers so an auditable record exists whenever a copy of the potentially spilled data is obtained.
110
+
Each time a reviewer generates a quarantined message report or a :ref:`post exposure report <administration-guide/manage/admin/content-flagging:generate a post exposure report>`, the **Data Spillage Bot** notifies all content reviewers so an auditable record exists whenever a copy of the potentially spilled data is obtained.
110
111
111
112
.. tip::
112
113
We recommend generating a report before removing a message. Once a message is removed, its content, attachments, and edit history are permanently deleted and can't be recovered.
113
114
114
115
Report contents and format
115
116
^^^^^^^^^^^^^^^^^^^^^^^^^^
116
117
117
-
Each report is a ZIP archive containing YAML metadata filesand the original file attachments. YAML is used because it's both human-readable and machine-parseable, which makes the report suitable for manual review and for ingestion by downstream compliance or incident-response tooling.
118
+
Each quarantined message report is a ZIP archive containing YAML metadata files, a CSV exposure report, and the original file attachments. YAML is used for the metadata files because it's both human-readable and machine-parseable, which makes the report suitable for manual review and for ingestion by downstream compliance or incident-response tooling. The exposure report is CSV so that reviewers can open it directly in a spreadsheet.
118
119
119
120
The archive has the following structure:
120
121
@@ -123,6 +124,7 @@ The archive has the following structure:
123
124
/
124
125
├── report_metadata.yaml
125
126
├── content_review.yaml
127
+
├── exposure_report.csv
126
128
├── post/
127
129
│ ├── post.yaml
128
130
│ └── attachments/
@@ -133,14 +135,103 @@ The archive has the following structure:
133
135
└── attachments/
134
136
└── <original attachment files>
135
137
136
-
- **report_metadata.yaml**: Identifies the report itself, including the user ID and username of the reviewer who generated the report, the generation timestamp, and the report format version (used for forward compatibility if the report format changes in future releases).
138
+
- **report_metadata.yaml**: Identifies the report itself, including the user ID and username of the reviewer who generated the report, the generation timestamp, and the report format version (used for forward compatibility if the report format changes in future releases). Report format version 1.1 added ``exposure_report.csv`` to the archive.
137
139
- **content_review.yaml**: Captures the data spillage event, including the reporter's user ID, username, selected reason, and comment; the report timestamp; whether the message was hidden during review; and, once the quarantine is resolved, the reviewer's user ID, username, comment, and action timestamp. For unresolved quarantines, reviewer fields are omitted.
140
+
- **exposure_report.csv**: Lists the users who may have been exposed to the quarantined message while it was visible in its channel. This is the same report that reviewers can download on its own, in the same format. See :ref:`administration-guide/manage/admin/content-flagging:exposure report contents` for the columns and how to interpret them.
138
141
- **post/post.yaml**: Describes the quarantined message, including the post ID, author ID, author name, author email, message content, channel ID, channel display name, team ID, team display name, creation and update timestamps, pinned status, root ID, post properties, post metadata, reply count (for root posts), and the ordered list of edit history post IDs.
139
142
- **post/attachments/**: The original files attached to the quarantined message, included verbatim.
140
143
- **edit_history/<edit_post_id>/**: One subdirectory per previous version of the message, each containing a ``post.yaml`` and an ``attachments/`` directory in the same format as the base post directory.
141
144
142
145
To avoid duplication, attachment files are deduplicated across the entire archive by their file ID. Each unique attachment appears exactly once — under the base post if it exists in the current version of the message, or under the earliest edit-history entry that referenced it.
143
146
147
+
Generate a post exposure report
148
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
149
+
150
+
From Mattermost v11.11, reviewers can generate a post exposure report: a CSV file listing the users who may have been exposed to a quarantined message while it was visible in its channel. The report helps a reviewer scope the impact of a potential data spill and decide who needs follow-up.
151
+
152
+
.. important::
153
+
154
+
A post exposure report identifies who *may* have been exposed to a quarantined message. It isn't evidence that anyone read the message.
155
+
156
+
- The report is derived from channel membership history and from channel read timestamps. Neither records whether a message was ever displayed on screen.
157
+
- A **Last viewed channel at** timestamp after the message was posted means the user opened the channel while the message was visible. It doesn't mean the message was displayed to them, or that they read it.
158
+
- The report doesn't cover every path by which a message can reach someone. Push and email notifications can deliver message content to a user who never opens the channel, and content in a public channel can be reached without joining it.
159
+
- Treat the report as a starting point for investigation, not as the sole basis for a compliance or disciplinary finding.
160
+
161
+
See :ref:`administration-guide/manage/admin/content-flagging:exposure report limitations` for what the report can and can't establish.
162
+
163
+
A post exposure report can be obtained from either of the following entry points:
164
+
165
+
- **From the quarantined message details**: Select **View details**, then select **Download exposure report** in the **Exposure report** row. The file downloads as ``post-exposure-<post_id>-<timestamp>.csv``.
166
+
- **From the quarantined message report**: The ZIP archive produced by **Download report** includes the same data as ``exposure_report.csv``.
167
+
168
+
Only content reviewers can generate a post exposure report.
169
+
170
+
Exposure report contents
171
+
^^^^^^^^^^^^^^^^^^^^^^^^
172
+
173
+
Every row in the report is one user who was a member of the channel at some point between the message being posted and the message being quarantined, taken from channel membership history. That row set is the complete population of users who could have been exposed through channel membership. It isn't the complete population of users who could have been exposed by any means.
174
+
175
+
The report doesn't produce a separate list of users who probably saw the message. Instead, every row carries the channel read state and account activity timestamps needed to judge likelihood, so reviewers triage a single table by sorting and filtering rather than reconciling two overlapping lists.
176
+
177
+
Report metadata is written as ``#``-prefixed comment lines above the header row, so the file describes itself without a separate metadata file. Most tools can skip these lines — for example, Go's ``csv.Reader`` with ``Comment: '#'``, or pandas with ``comment='#'``.
User ID,Username,Email,Guest,Remote user,Deactivated,Was channel member,Last viewed channel at (YYYY-MM-DDTHH:MM:SSZ),User last activity time (YYYY-MM-DDTHH:MM:SSZ)
zd7pfk2vqn6ymxb3wcjs9htgr8,carlos.mendes,[email protected],No,No,Yes,Yes,Unknown,No sessions found
192
+
193
+
**Post created at** and **Flagged at** bound the reporting window that membership is resolved against. **Total users** is the number of rows in the file, counted after any users whose account records no longer exist are skipped.
194
+
195
+
The report includes the following columns:
196
+
197
+
- **User ID**: The system identifier for the user.
198
+
- **Username**: The user's Mattermost username.
199
+
- **Email**: The user's email address.
200
+
- **Guest**: ``Yes`` if the user is a guest account.
201
+
- **Remote user**: ``Yes`` if the user belongs to a remote server through a shared channel. Content on a remote server is beyond the reach of hiding or removing the message locally.
202
+
- **Deactivated**: ``Yes`` if the user's account is deactivated. Deactivating a user doesn't undo their exposure, so deactivated accounts are still reported.
203
+
- **Was channel member**: Always ``Yes`` in report version 1.0. Every row is a channel member by definition, and the column is reserved for future report versions that may add other exposure paths.
204
+
- **Last viewed channel at (YYYY-MM-DDTHH:MM:SSZ)**: The user's *current* last-viewed timestamp for the channel, not a snapshot taken when the message was quarantined. ``Unknown`` means no read state exists because the user is no longer a channel member. ``N/A`` means the user is a member who has never opened the channel.
205
+
- **User last activity time (YYYY-MM-DDTHH:MM:SSZ)**: The user's most recent session activity anywhere in Mattermost, not in this channel. ``No sessions found`` means no session records exist for the user, which is always the case for deactivated accounts.
206
+
207
+
To scope who needs follow-up, compare each row's **Last viewed channel at** value against the **Post created at** value in the report metadata:
208
+
209
+
- **At or after Post created at**: The user opened the channel while the message was visible. This is a possible exposure, and should be prioritized for follow-up.
210
+
- **Before Post created at**: The user was a channel member, but hadn't opened the channel since before the message was posted. Exposure in the channel is less probable, but not ruled out — the message content may still have reached the user through a push or email notification.
211
+
- **Unknown or N/A**: No channel read state exists for the user. Exposure is undetermined. Don't read these values as confirmation that the user didn't see the message.
212
+
213
+
.. tip::
214
+
Generate the exposure report early in the review. **Last viewed channel at** reflects live channel read state, so it moves whenever a user opens the channel again, including after the quarantine is resolved.
215
+
216
+
Rows are sorted by username, then by user ID, so row order is the same every time the report is generated. The cell values aren't: **Last viewed channel at** and **User last activity time** both reflect live state, so two reports generated at different times can differ. Column headings and values, including ``Yes``, ``No``, ``Unknown``, ``N/A``, and ``No sessions found``, are localized to the language of the reviewer who generated the report. Downstream tooling shouldn't match on the English strings.
217
+
218
+
Exposure report limitations
219
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
220
+
221
+
The report is derived from channel membership history and channel read state, which constrains what it can establish:
222
+
223
+
- **Notification delivery isn't covered**: A user can be exposed to message content without ever opening the channel. Push and email notifications can include the message text, depending on your :ref:`push notification contents <administration-guide/configure/site-configuration-settings:push notification contents>` and :ref:`email notification contents <administration-guide/configure/site-configuration-settings:email notification contents>` settings. Notifications aren't reflected in the report, so an early **Last viewed channel at** value doesn't rule out exposure.
224
+
- **Access to public channels without membership isn't covered**: The report lists channel members only. In a public channel, a message can also reach users who never joined the channel — through a :doc:`post permalink preview </end-user-guide/collaborate/share-links>` rendered when a link to the message is shared in another channel, or through search when :ref:`searching public channels without membership <administration-guide/configure/environment-configuration-settings:allow searching public channels without membership>` is enabled. None of these users appear in the report.
225
+
- **Bots are excluded**: Bot accounts are omitted from the report.
226
+
- **Users who joined after the message was quarantined are excluded**: Membership is resolved against the reporting window only.
227
+
- **Users who left and rejoined appear once**: The report is a list of users, so multiple membership periods are collapsed into a single row. Individual join and leave times aren't reported.
228
+
- **Users who left and didn't rejoin are included**: They're reported with **Last viewed channel at** set to ``Unknown``, because no channel read state survives for a former member.
229
+
- **Guests and remote users are included**: Both are identified in their own columns.
230
+
- **Archived channels are supported**: Members of an archived channel are reported as usual.
231
+
- **Deleted accounts are omitted**: If a user's account record no longer exists, that user is skipped, and **Total users** reflects the count after the skip.
232
+
233
+
Generating an exposure report queries session activity for each user in the report individually, and the whole report is assembled in memory before the download starts. On channels with several thousand members, expect generation to take proportionally longer.
0 commit comments