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
4 changes: 4 additions & 0 deletions src/content/docs-core/en/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ gh pr create --base main --head your-branch

Commit messages follow Conventional Commits (`fix(scope): subject`) and are written in English. The body explains *why*, not only *what*.

## Contributor License Agreement

A first pull request asks its author to sign the [Contributor License Agreement](https://github.com/ThinkWatchProject/ThinkWatch-Core/blob/main/CLA.md) once, by replying on the pull request with the sentence the bot gives. The signature covers every later pull request to the repository. The author keeps the copyright, and the agreement lets the project license the contribution under any terms, commercial ones included.

## Mandatory rules

ThinkWatch Lite and ThinkWatch Enterprise both depend on these crates, so working for a single use case is not sufficient. A pull request that violates any of these rules will be returned for revision, regardless of the quality of the diff:
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs-core/en/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Clients such as Claude Code and Codex send their requests to the gateway, and Co
- **Rule-based routing.** Rules match on the model, the gateway key, the input size, the presence of tools or images and other properties of a request, and send it to an upstream or a group, rewrite its parameters or refuse it. When the client and the upstream use different API formats, the request is converted between Anthropic Messages, OpenAI Chat Completions, OpenAI Responses and Gemini.
- **Failover before the first byte.** Until the first byte reaches the client, a failing upstream is replaced by the next one without the client noticing. After that point, the failure is reported. A circuit breaker keeps requests away from an upstream that keeps failing.
- **Cost accounting.** Token usage and cache hits are priced from a public price table, which the control plane refreshes daily, or from a price sheet in the configuration. Each request records its cost and where the price came from. Estimated amounts are marked as such, and usage that cannot be priced is labelled *unknown* rather than given an invented figure.
- **Outbound redaction.** Credentials and personal information anywhere in a request are replaced with placeholders before the request leaves, and restored when the model echoes them back.
- **Outbound redaction.** Credentials and personal information in a request are replaced with placeholders before the request leaves, and restored when the model echoes them back. Field names are not searched, and custom rules also skip the ids, types, roles and names a protocol needs as they are.
- **Tool-call inspection.** Tool calls returned by an upstream are checked against a rule set, and a dangerous call can be cut off mid-stream.
- **Content filter.** The user messages and tool results a client sends are checked by keyword, regular expression or code point, and each rule refuses the request, deletes what it matched or only records it; the built-in rules also catch hidden characters that can carry instructions. Each of the three guards is set to `off`, `observe` or `enforce`, and all start in `observe`.
- **An encrypted control plane.** The desktop app and `twcore` commands reach core over a local socket (a loopback port on Windows) and, when it is enabled, a remote control port. Every control connection starts with a Noise handshake keyed by `listen.control.key`; there are no certificates.
Expand Down
4 changes: 4 additions & 0 deletions src/content/docs-core/zh-CN/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ gh pr create --base main --head your-branch

提交信息遵循 Conventional Commits(`fix(scope): subject`),以英文书写。正文应说明*原因*,而不仅是*改动内容*。

## 贡献者许可协议

首次提交 PR 时,需在 PR 中按机器人给出的句子回复,签署一次[贡献者许可协议](https://github.com/ThinkWatchProject/ThinkWatch-Core/blob/main/CLA.zh-CN.md)。签署后,此后向该仓库提交的 PR 均已涵盖。贡献的版权仍归作者所有,协议授权项目以任何条款(包括商业条款)许可该贡献。

## 强制规则

ThinkWatch Lite 与 ThinkWatch 企业版都依赖这些 crate,因此仅满足单一场景并不足够。违反以下任何一条规则的 PR 都将被要求修改,无论 diff 质量如何:
Expand Down
2 changes: 1 addition & 1 deletion src/content/docs-core/zh-CN/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Claude Code、Codex 等客户端把请求发往网关后,Core 提供以下功
- **按规则路由。** 规则按模型、网关密钥、输入规模、是否携带工具或图片等请求属性匹配,将请求发往某个上游或策略组、改写其参数,或拒绝请求。客户端与上游的接口格式不同时,请求在 Anthropic Messages、OpenAI Chat Completions、OpenAI Responses 与 Gemini 之间转换。
- **首字节前的故障转移。** 首字节到达客户端之前,出错的上游由下一个上游替换,客户端无从察觉;此后发生的故障如实报告。熔断器使持续出错的上游暂不接收请求。
- **费用核算。** token 用量与缓存命中按公开价目表计价(控制面每天刷新一次),或按配置中的价目表计价;每个请求都记录费用及价格来源。估算的金额另行标注,无法计价的用量标记为「未知」,不会填入虚构的数值。
- **出站脱敏。** 请求发出之前,其中任何位置的凭据和个人信息替换为占位符;模型回显时再恢复原值。
- **出站脱敏。** 请求发出之前,其中的凭据和个人信息替换为占位符;模型回显时再恢复原值。字段名不在查找之列,自定义规则还会跳过协议要求原样保留的 id、类型、角色和名称。
- **工具调用审查。** 上游返回的工具调用按规则集审查,高危调用可在流式传输中途截断。
- **内容过滤。** 客户端发送的用户消息和工具结果按关键词、正则表达式或码位检查,每条规则可拒绝请求、删除命中的内容或仅记录;内置规则也能查出可夹带指令的隐藏字符。三项防护各可设为 `off`、`observe` 或 `enforce`,出厂均为 `observe`。
- **加密的控制面。** 桌面应用与 `twcore` 命令通过本地 socket(Windows 上为回环端口)连接 core,开启后也可经远程控制端口连接。每条控制连接都先以 `listen.control.key` 完成 Noise 握手,不使用证书。
Expand Down
4 changes: 4 additions & 0 deletions src/content/docs-lite/en/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ gh pr create --base dev --head your-branch

`main` is the release branch; `dev` receives routine work. GitHub sets the base of a new pull request to the default branch, `main`, which is not the intended target. If a pull request was opened against `main`, select *Edit* next to its title and change the base; the commits and the discussion are preserved.

## Contributor License Agreement

A first pull request asks its author to sign the [Contributor License Agreement](https://github.com/ThinkWatchProject/ThinkWatch-Lite/blob/main/CLA.md) once, by replying on the pull request with the sentence the bot gives. The signature covers every later pull request to the repository. The author keeps the copyright, and the agreement lets the project license the contribution under any terms, commercial ones included.

## Settled scope

The following decisions are settled and are not open to change through a pull request:
Expand Down
6 changes: 3 additions & 3 deletions src/content/docs-lite/en/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ Every request records the rule it matched, the group it went through and each at

The Security page holds three protections: outbound redaction, tool-call inspection and the content filter. They apply to every upstream and every key alike, and each runs in one of three modes: Off, Observe (detect and record, change nothing) and a third mode named for what it does: Replace for outbound redaction, Cut off for tool-call inspection and Enforce for the content filter. All three start in Observe, so out of the box no request is changed or refused.

- **Outbound redaction** searches the whole request before it leaves, including the system prompt, earlier turns and tool calls, for credentials and personal information: API keys and tokens for Anthropic, OpenAI, GitHub, Slack, AWS, Google, GitLab, Stripe, npm, DigitalOcean and SendGrid, private keys, JWTs and passwords in connection strings, as well as Chinese resident ID numbers and bank card numbers, which count only when their structure and check digit are valid. In Replace mode they are replaced with placeholders such as `<<TW_SECRET_1>>` and restored where the response repeats them. Rules for email addresses, Chinese mainland mobile numbers, internal IP addresses and internal domains are included and start off, and a custom rule can name its own placeholder: `PROJECT` gives `<<TW_PROJECT_1>>`.
- **Outbound redaction** searches the whole request before it leaves, including the system prompt, earlier turns and tool calls, for credentials and personal information: API keys and tokens for Anthropic, OpenAI, GitHub, Slack, AWS, Google, GitLab, Stripe, npm, DigitalOcean and SendGrid, private keys, JWTs and passwords in connection strings, as well as Chinese resident ID numbers and bank card numbers, which count only when their structure and check digit are valid. Field names are not searched, and custom rules leave alone the identifiers a protocol needs as they are, such as item and call ids, types, roles, tool names and model names, so a rule cannot break an id a client sends back. In Replace mode they are replaced with placeholders such as `<<TW_SECRET_1>>` and restored where the response repeats them. Rules for email addresses, Chinese mainland mobile numbers, internal IP addresses and internal domains are included and start off, and a custom rule can name its own placeholder: `PROJECT` gives `<<TW_PROJECT_1>>`.
- **Tool-call inspection** checks the tool calls a model returns for commands that download or decode code and run it, send out environment variables or credential files, send a credential to a host that is neither local nor the credential's own provider, read private keys or cloud credentials, read or change ThinkWatch's own data directory, or install startup items and scheduled jobs. A path that only appears in text being written, such as a document that mentions the directory, does not count. In Cut off mode such a call cuts the response off, so the client never receives a complete call to run. Deleting the home or root directory, making files world-writable and uploading a local file to an outside host are only recorded by default.
- **Content filter** checks the user messages and tool results in each request, context compaction included. A rule matches a keyword, a regular expression or code points such as `U+E0000–U+E007F`, and in Enforce mode it refuses the request, deletes the matched text and sends the rest, or only records. Built-in rules delete Unicode tag characters and bidirectional controls, which can hide instructions from people but not from a model, and refuse explicit "ignore previous instructions" phrasing. Rules for zero-width and private-use characters, which emoji, Persian text and icon fonts also use, and for jailbreaks, persona manipulation, prompt extraction and their Chinese counterparts start off and can be switched on.

The page lists every rule, the built-in ones grouped by kind. Built-in rules can be switched on or off one at a time; a built-in tool-call rule can be set to cut off or only record, and a built-in content rule to refuse, delete or only record. Custom rules are regular expressions, or for the content filter also keywords or code points. Any rule can be tried on a sample text first; for redaction and the content filter, the test also shows the text as it would be sent. Everything the protections find is kept in the log on the first tab, together with the request it came from; when hidden characters spell out text, the log shows that text.
The page lists every rule, the built-in ones grouped by kind. Built-in rules can be switched on or off one at a time; a built-in tool-call rule can be set to cut off or only record, and a built-in content rule to refuse, delete or only record. A custom redaction rule looks for its text as written (**Contains**, the default) or takes a regular expression (**Regex**), and ignores case unless **Match case** is on; a custom content rule matches a keyword, a regular expression or code points, and a custom tool-call rule is a regular expression. Any rule can be tried on a sample text first; for redaction and the content filter, the test also shows the text as it would be sent. Everything the protections find is kept in the log on the first tab, together with the request it came from; when hidden characters spell out text, the log shows that text.

An entry in the log opens in place. It lists every place the rule matched, up to 50 with the number of the rest: the part of the request or answer it was in (the system prompt, a message with its number and role, a tool call or tool result with the tool's name, or the answer text), its JSON path, and up to 80 characters of context on either side, with credentials masked. It gives the rule as it was when it matched, a custom rule's pattern or a built-in rule's name with the core version that evaluated it, so the entry stays readable after the rule is changed or deleted. It states exactly what was done: the placeholder a value was replaced with, the tool call that was cut off and the notice the client received instead, the reply the client received for a refused request, or how many matched segments were deleted. The session and, when it differs from the model requested, the model sent to the upstream are given as well. The entries in a request's timeline open the same way. **Export** saves every entry of the selected period as JSON (full detail) or CSV (one row per entry). The log is kept as long as the request records, and changes to the protections' settings are not written to it.
An entry in the log opens in place. It lists every place the rule matched, up to 50 with the number of the rest: the part of the request or answer it was in (the system prompt, a message with its number and role, a tool call or tool result with the tool's name, or the answer text), its JSON path, and up to 80 characters of context on either side, with credentials masked. It gives the rule as it was when it matched, a custom rule's pattern and how it matches, or a built-in rule's name with the core version that evaluated it, so the entry stays readable after the rule is changed or deleted. It states exactly what was done: the placeholder a value was replaced with, the tool call that was cut off and the notice the client received instead, the reply the client received for a refused request, or how many matched segments were deleted. The session and, when it differs from the model requested, the model sent to the upstream are given as well. The entries in a request's timeline open the same way. **Export** saves every entry of the selected period as JSON (full detail) or CSV (one row per entry). The log is kept as long as the request records, and changes to the protections' settings are not written to it.

The protections act on requests and answers passing through the gateway, not on files on disk. The configuration file holds keys in plain text and only its owner can read it, which keeps out other users but not programs running as the same user; outbound redaction protects what leaves the machine, not the file.

Expand Down
7 changes: 4 additions & 3 deletions src/content/docs-lite/en/keep-api-keys-from-relays.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ A relay receives every request in full, including keys that end up in the conver

## Before you start

- ThinkWatch Lite, [installed](/lite/#install), with clients connected to the gateway. This guide follows version 2026.10.6.
- ThinkWatch Lite, [installed](/lite/#install), with clients connected to the gateway. This guide follows version 2026.10.17.
- Both protections start in **Observe**: they record what they find and change nothing. **Off** checks nothing.

## Steps

1. Open the Security page. The **Log** tab lists every finding with its request; since both modes use the same rules, a few days in **Observe** show what **Replace** would change.
2. Open **Redaction**. Built-in rules turn on or off one at a time, and **Test…** shows **What is sent** for a pasted text.
3. For a key format the built-in rules do not cover, choose **New rule**, enter a **Name**, a pattern under **Match (regular expression)** and a **Placeholder name** such as `INTERNAL` (giving `<<TW_INTERNAL_1>>`), then choose **Create**.
3. For a key format the built-in rules do not cover, choose **New rule** and enter a **Name**. Under **Match by**, **Contains** looks for the text exactly as written, so `.` and `*` have no special meaning, and **Regex** takes a regular expression; **Match case**, off by default, tells capital letters from small ones. Enter the text or the pattern and a **Placeholder name** such as `INTERNAL` (giving `<<TW_INTERNAL_1>>`), then choose **Create**.
4. Set the mode at the top of the tab to **Replace**.
5. Open **Tool calls**. Each built-in rule is marked **Cut off** or **Record only**, which **View rule** can change. Set the mode to **Cut off**.
6. The log's **Action** column then shows **Replaced** or **Cut off**, and a cut-off call also raises a system notification. From ThinkWatch Lite 2026.10.12, an entry opens in place to show where the value was found and the placeholder it was replaced with, or the tool call that was cut off and the notice the client received.
Expand All @@ -23,7 +23,8 @@ A relay receives every request in full, including keys that end up in the conver
| **Observe** (default) | Findings are recorded; the request is sent unchanged. | Matching calls are recorded and returned as usual. |
| **Replace** / **Cut off** | Findings are replaced with placeholders before sending and restored in the response. | Calls matching a **Cut off** rule never fully reach the client; **Record only** rules still only record. |

- **What redaction covers.** The whole request, system prompt, earlier turns and tool calls included, except base64 data such as images. Built-in rules find API keys and tokens for Anthropic, OpenAI, GitHub, Slack, AWS (access key IDs), Google, GitLab, Stripe, npm, DigitalOcean and SendGrid, private keys, JWTs, passwords in connection strings, and Chinese resident ID and bank card numbers whose structure and check digit are valid. The rules for email addresses, Chinese mainland mobile numbers, internal IP addresses and internal domains start off.
- **What redaction covers.** The whole request, system prompt, earlier turns and tool calls included, except field names and base64 data such as images. Custom rules also leave alone the identifiers a protocol needs as they are: item and call ids, types, roles, tool names and model names; built-in rules still search them. Built-in rules find API keys and tokens for Anthropic, OpenAI, GitHub, Slack, AWS (access key IDs), Google, GitLab, Stripe, npm, DigitalOcean and SendGrid, private keys, JWTs, passwords in connection strings, and Chinese resident ID and bank card numbers whose structure and check digit are valid. The rules for email addresses, Chinese mainland mobile numbers, internal IP addresses and internal domains start off.
- **Rules from before 2026.10.17.** A custom rule saved by an earlier version was a case-sensitive regular expression; it now looks for its text as written and ignores case. A rule that relies on a regular expression still loads but stops matching, with nothing reported, so open each one and choose **Regex**, and **Match case** where capital letters matter.
- **How values come back.** A value keeps one placeholder throughout a request, on every upstream. Placeholders the model writes back, in text or tool-call arguments, are restored before the client receives them: a command using the key runs locally with the real value, while the relay sees only the placeholder.
- **What is cut off.** Calls that download or decode code and run it, send out environment variables or credential files, read private keys or cloud credentials, send a credential to an unknown host, or install startup items or scheduled jobs. Built-in rules for deleting home or root, world-writable permissions and uploading a local file only record.
- **What the relay still sees.** The key configured for its upstream in the app, and the rest of the request as written: code, file contents, the conversation. The key a client uses for the gateway is not forwarded, and neither is the client's identity unless **Forward client identity** is on for that upstream.
Expand Down
Loading
Loading