Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ categories = ["network-programming", "web-programming::http-server"]

# 二进制走 CalVer,crate 走 SemVer —— 两者是两回事,卖给不同的人。
# 这里是 crate 的版本。
version = "0.73.0"
version = "0.74.0"

[workspace.dependencies]
# ── 内部 crate ───────────────────────────────────────────
Expand Down
18 changes: 10 additions & 8 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -756,14 +756,16 @@ refuses, deletes, replaces or only records.

#### `security.redact`

Before a request leaves, the whole request (system prompt, earlier answers
and tool calls included) is searched for credentials and personal
information. Under `enforce` what a rule finds is replaced with placeholders,
and put back where the answer repeats them; what a rule with `action: record`
finds is sent as it is and only recorded. Images, files and other base64
payloads are not searched, nor are field names; custom rules also leave alone
the identifiers a protocol needs as they are, such as item and call ids,
types, roles, tool names and model names.
Before a request leaves, the text written in it is searched for credentials
and personal information: system prompts, the messages of every role
(earlier answers included), reasoning, tool-call arguments, tool results and
tool descriptions. Under `enforce` what a rule finds is replaced with
placeholders, and put back where the answer repeats them; what a rule with
`action: record` finds is sent as it is and only recorded. Values the
protocol needs as they are, such as ids, types, roles, tool names, model
names and signatures, are never searched, nor are field names, images,
files, settings, or parts of a request the gateway does not recognize as
written text.

<!-- generated: table security.redact -->
<a id="cfg-security-redact"></a>
Expand Down
2 changes: 1 addition & 1 deletion docs/config.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ pricing:

#### `security.redact`

请求发出前,在整个请求中(包括系统提示、之前的回答和工具调用)查找凭据和个人信息。`enforce` 下将规则找到的内容替换为占位符,回答中重复出现时再换回原值;`action: record` 的规则找到的内容原样发送,只作记录。图片、文件等 base64 内容不查,字段名也不查;自定义规则还不查协议要求原样保留的标识,如条目和调用的 id、类型、角色、工具名、模型名。
请求发出前,在请求中写出的正文里查找凭据和个人信息:系统提示、各角色的消息(包括之前的回答)、推理、工具调用的参数、工具结果和工具说明。`enforce` 下将规则找到的内容替换为占位符,回答中重复出现时再换回原值;`action: record` 的规则找到的内容原样发送,只作记录。协议要求原样保留的值(如 id、类型、角色、工具名、模型名、签名)一律不查,字段名、图片、文件、配置项以及网关不认作正文的部分也不查。

<!-- generated: table security.redact -->
<a id="cfg-security-redact"></a>
Expand Down
18 changes: 18 additions & 0 deletions release-notes/0.74.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
This release makes outbound redaction look only at the text written in a request, located by the request's format, so it can no longer change an id or another value the protocol needs and get the request refused.

**Upgrade notes**

- The control-plane protocol version stays at 48; ThinkWatch Lite releases that include 0.73.0 connect to 0.74.0 and the other way round.
- The request store's schema and the configuration are unchanged; nothing is cleared.
- Requests to paths the gateway does not recognize, and WebSocket connections other than Responses and Realtime, are no longer searched by redaction; they were searched as whole text before.
- Request fields outside the written text, such as `metadata`, are no longer searched.
- For crates that embed the gateway: `tw_guard::redact::flow::find`, `look`, `look_from`, `look_hits` and `replace` take the request's `Shape`, and `reported` takes a `Scope`. `hits` still searches the whole text; `hits_in` searches a `Scope`. New module `tw_dialect::written` with `Shape`, `spots` and `ranges`.

**Redaction searches only written text.** Rules used to run over the whole JSON body, with field names and a fixed list of identifier fields left out for custom rules only. A built-in rule could still match inside a protocol value: with the mobile-number rule on, eleven digits inside a Codex reasoning item id (`rs_` followed by hexadecimal) were replaced with a placeholder, the upstream refused the id, and since the history is sent again on every turn, every later turn of that conversation was refused too.

Redaction now searches only the text people, models and tools wrote:
- Anthropic, Chat Completions, Responses, Gemini and Converse requests: system prompts and instructions, the text of every message whatever its role, reasoning text and summaries, tool-call arguments and inputs, tool results, and tool descriptions.
- Embeddings (`input`), legacy completions (`prompt` and `suffix`), Gemini embeddings, and the client events of a Realtime connection.
- Ids, types, roles, names, model names, signatures, encrypted content, images and files, and settings are never searched, and neither are blocks or fields not on this list.

Reasoning text stays on the list: placeholders in an answer are restored before the client sees it, and when the client sends the history back, the values in it are replaced again. A request converted to another format is searched as the format it is sent in. Stored bodies and security-log excerpts are still masked as whole text.
Loading