diff --git a/changelog.mdx b/changelog.mdx
index 971d78f..930e6db 100644
--- a/changelog.mdx
+++ b/changelog.mdx
@@ -14,21 +14,46 @@ This page tracks releases of SenderKit's developer libraries — the
documents. New entries land here as each library ships a version.
+
+ ## `blockedReason` is operator-only
+
+ The `blockedReason` field is not returned in any customer-facing message read
+ (`messages.list`, `messages.get`, the SDK, the SSE tail, or the Logs page).
+
+ When the outbound abuse scanner halts a send, the customer-visible message timeline
+ records only a generic notice: **"Blocked by automated content safety checks."**
+ The detailed signal breakdown (which heuristic fired, LLM confidence score, etc.)
+ is kept operator-only in the admin console and is intentionally not disclosed to
+ senders — surfacing detection signals would help bad actors evade them.
+
+ The `Message.blockedReason` property in the SDK type (`string | null | undefined`)
+ is retained as an optional field but is never populated in customer API responses.
+ The earlier June 17 changelog entry described `blockedReason` as containing
+ human-readable detail (e.g. `"High-confidence phishing content detected"`) — that
+ description was incorrect and has been superseded by this entry.
+
+ ### What still works
+
+ - `messages.list({ status: "blocked" })` — filtering for blocked messages works as
+ documented. Only `blockedReason` is withheld; every other message field is present.
+ - `Message.status === "blocked"` — detection and the status transition are unchanged.
+
+
- ## `blocked` message status + `blockedReason`
+ ## `blocked` message status
**`@senderkit/sdk@0.10.0` / `@senderkit/cli@0.6.3`**
SenderKit now runs outbound anti-phishing detection over email and SMS content
before handing a message to a provider. A flagged send is halted and the message
- lands in a new terminal `blocked` status with a human-readable reason.
+ lands in a new terminal `blocked` status.
### What's new
- **`blocked` status** — `Message.status` can now be `"blocked"`. A blocked message
was stopped by the abuse scanner before provider dispatch and will not be retried.
- - **`Message.blockedReason`** — optional `string | null` field that explains why the
- message was flagged (e.g. `"High-confidence phishing content detected"`).
+ The message timeline records a generic notice; detection details are operator-only
+ (see the [June 19 entry](#june-19-2026) for clarification).
- **`messages.list({ status: "blocked" })`** — the status filter now accepts
`"blocked"` in the SDK, CLI (`--status blocked`), and MCP
(`senderkit_messages_list`). Before this release, filtering by `"blocked"`
diff --git a/concepts/messages.mdx b/concepts/messages.mdx
index 992ba6d..6812881 100644
--- a/concepts/messages.mdx
+++ b/concepts/messages.mdx
@@ -40,7 +40,7 @@ stateDiagram-v2
| `delivered` | The provider confirmed delivery | Provider webhook |
| `failed` | Delivery failed | Provider webhook, a config error, or retries exhausted |
| `opted_out` | Recipient is unsubscribed/suppressed | Provider webhook, one-click unsubscribe link, or send skipped because the recipient previously opted out |
-| `blocked` | Delivery halted by outbound abuse detection | Phishing scan flagged the content with high confidence; the message is never handed to a provider. The `blockedReason` field explains why. |
+| `blocked` | Delivery halted by outbound abuse detection | Phishing scan flagged the content with high confidence; the message is never handed to a provider. The message timeline records a generic notice; detection details are operator-only and not exposed via the customer API. |
| `canceled` | Delivery intentionally stopped before dispatch | `messages.cancel()` or the dashboard cancel action |
diff --git a/sdks/typescript.mdx b/sdks/typescript.mdx
index 3f4a176..a23d36a 100644
--- a/sdks/typescript.mdx
+++ b/sdks/typescript.mdx
@@ -374,10 +374,11 @@ return a `409` (`SenderKitApiError`) — and resolves to
- **`blocked` status and `blockedReason`** — `Message.status` can be `"blocked"` when
- outbound abuse detection halts a send before it reaches a provider. A `blocked`
- message also carries an optional `blockedReason: string | null` field explaining the
- flag. Filter for blocked messages with `messages.list({ status: "blocked" })`.
+ **`blocked` status** — `Message.status` can be `"blocked"` when outbound abuse
+ detection halts a send before it reaches a provider. The message timeline records a
+ generic notice (`"Blocked by automated content safety checks."`); detailed detection
+ signals are operator-only and not returned in customer API responses. Filter for
+ blocked messages with `messages.list({ status: "blocked" })`.
```ts