@@ -11,6 +11,168 @@ target.
1111
1212## [ Unreleased]
1313
14+ ## [ 3.11.0] — 2026-11-03
15+
16+ Execution and buffering now adapt automatically to available CPUs and memory,
17+ including container limits. CPU work expands with traffic and extra threads
18+ retire after ten idle seconds; no runtime configuration change is required.
19+
20+ Secrets and privacy recognises far more: the built-in redaction catalog
21+ grows from 30 rules to 131 in 20 groups, and the API keys saved
22+ for the providers are recognised by value, whatever their format. The
23+ console shows the rules' names and descriptions as thinkwatch-core
24+ writes them, in both languages. A value recognised by mistake can be made
25+ an exception without switching its rule off, and long conversations are
26+ no longer scanned from the start every turn. A provider can set the
27+ slowest generation its streams may keep up, and a stream that falls
28+ below it is cut so the client can try again. The thinkwatch-core crates
29+ move from v0.83.1 to v0.89.0.
30+
31+ No new runtime setting. Two new provider columns
32+ (` providers.min_speed_tokens_per_sec ` , ` providers.min_speed_window_secs ` ,
33+ added on startup). New metrics cover minimum generation speed, buffering
34+ pressure and audit backlog memory.
35+ The redaction policy gains one optional field (` exceptions ` ), with
36+ endpoints of its own under ` /api/admin/security/redact/exceptions ` .
37+
38+ ### Read before upgrading
39+
40+ - ** Buffering is admitted against a process-wide memory budget.** Request,
41+ response, cache and retained streaming data use limits derived from the
42+ container or machine's memory. Temporary pressure returns a retryable 429
43+ with ` Retry-After: 1 ` ; an already-started stream receives an error event.
44+ Large upstream responses and stream timelines are bounded, and new audit
45+ entries are dropped with metrics if the separate audit byte budget fills.
46+ See [ automatic process resources] ( docs/operations/resources.md ) for the
47+ limits and monitoring. These allocation budgets are not a hard RSS cap.
48+ - ** UUIDs and blockchain credentials gain built-in rules.** Core v0.88.0
49+ added 11 rules, enabled by default, including UUIDs, wallet keys and
50+ accounts, exchange credentials and recovery material. Monitor records
51+ findings; installations with protection On replace matching message
52+ text. UUIDs, hashes and public accounts do not independently trigger
53+ credential-exfiltration blocking. Review any workflows that send order
54+ or trace identifiers as message text.
55+ - ** New credential rules ship on.** Under the On state of Secrets and
56+ privacy (` security.redact ` mode ` enforce ` ), values they find start
57+ being replaced with placeholders: among them credentials in request
58+ headers, command lines, URLs and bot webhooks, and secrets assigned in
59+ ` .env ` -style configuration (` DB_PASSWORD=… ` ). Under Monitor, the
60+ factory state, they are only recorded. A rule that gets in the way can
61+ be switched off on its own in the console.
62+ - ** Some keys are reported under a rule of their own.** ` sk-or-v1- `
63+ (OpenRouter), ` sk-lf- ` (Langfuse), ` sk-svcacct- ` , ` sk-admin- ` and
64+ ` sk-api- ` keys were reported as ` openai-api-key ` ; they now have their
65+ own rule ids, and so do audit events and the
66+ ` gateway_redaction_found_total ` metric's ` kind ` label, which follows
67+ the new groups (` ai-services ` , ` dev-platforms ` , ` cloud ` , …) instead of
68+ ` api-keys ` and ` personal ` .
69+
70+ ### Added
71+
72+ - ** Expanded redaction rules** (thinkwatch-core v0.85.0 and later): about 50 more
73+ prefixed credentials (AI services, code hosting, cloud, payments and
74+ collaboration), credentials by position (request headers, command
75+ lines, URL parameters, bot webhooks, configuration assignments),
76+ cryptocurrency recovery phrases and private keys, and personal
77+ information: identity documents, foreign ID numbers, IBAN, phone
78+ numbers, addresses and coordinates, vehicles, device identifiers and
79+ values by field name. Of the new personal-information rules only the
80+ two that can be checked digit by digit ship on (passport
81+ machine-readable zone, IBAN), alongside the resident ID and bank card
82+ numbers as before.
83+ - ** Saved upstream keys are recognised by value.** The API keys in each
84+ provider's credential headers (the ` Bearer ` scheme left out) and a
85+ Bedrock provider's secret access key are matched wherever they appear
86+ in a request, as written or JSON-escaped; values shorter than 12
87+ characters are not. The list follows the providers: it is rebuilt when
88+ they load, when one is created, changed or deleted, and on the other
89+ instances through the router reload. The same keys count as
90+ credentials for the dangerous-commands rule "credential sent to an
91+ unknown host", each allowed to its own provider's host, and the
92+ console's trial recognises them too.
93+ - ** A saved key's audit event names its provider, never the value.** The
94+ ` gateway.redaction_* ` event of the rule ` thinkwatch-saved-secret `
95+ carries ` sources ` (` [{"kind": "upstream-key", "name": <provider>}] ` )
96+ and no masked values; the security log shows it as the provider's API
97+ key.
98+
99+ - ** Exception values** (` security.redact.exceptions ` , the Exceptions
100+ section under the Secrets and privacy rules). A value listed there is
101+ neither replaced nor recorded, whichever rule finds it; the rules keep
102+ working for every other value. A value is added by pasting it: the
103+ server hashes it on arrival and keeps only its SHA-256, its masked form,
104+ the rule that recognised it and when it was added, never the value. At
105+ most 500; at the cap, adding is unavailable. Saved provider keys cannot
106+ be exceptions. Listing them takes ` settings:read ` ; adding and removing
107+ take ` settings:write ` and ` pii_redactor:write ` , and each is written to
108+ the audit log (` security.redact_exception_added ` ,
109+ ` security.redact_exception_removed ` ) with the rule and the masked value
110+ only. The trial marks an excepted value as left as is.
111+ - ** Unchanged conversation history is not scanned again.** Each gateway
112+ instance keeps, in memory, where the redaction rules matched in the
113+ parts of recent requests it has scanned (positions and rule ids, never
114+ values); the next turn of the same conversation takes those parts from
115+ it and scans only what is new. What is found is the same as without it.
116+ The cache is rebuilt whenever the rules, the providers' keys or the
117+ exceptions change.
118+ - ** Stop a stream that generates too slowly** (the provider's
119+ "Stop when generation is slower than … tokens/s for … s" setting,
120+ ` min_speed_tokens_per_sec ` 1–1000 and ` min_speed_window_secs ` 5–120,
121+ default 20, on the provider endpoints; blank or ` null ` is off, the
122+ default). From the first token on, a stream is judged once a second:
123+ when the visible text it streamed over the last window (answer,
124+ reasoning streamed as generated, and tool arguments; four ASCII
125+ characters or one other character to a token) comes to fewer tokens
126+ per second than the minimum, the stream ends with a 503 error in the
127+ client's format (` overloaded_error ` for Anthropic, ` response.failed `
128+ for Responses, ` UNAVAILABLE ` for Gemini), the upstream connection is
129+ closed, and the route is charged a failure. Left out of the window:
130+ pauses of a quarter of the window or more (at most 5 s), and
131+ summarised reasoning (Responses reasoning summaries, Anthropic thinking
132+ blocks, Gemini thought parts, Bedrock reasoning content), which arrives
133+ in bursts while the model reasons; a window more than half left out is
134+ not judged. Nor is a second while summarised reasoning is open, one
135+ whose last content is more than a second old, or anything after the
136+ upstream has ended the answer. Counts the upstream reports are not
137+ used: Gemini's includes its hidden thoughts. The session's affinity to
138+ that route is dropped, the answer so far is billed as for any stream
139+ cut short, and the log row carries the error ` UpstreamTooSlow ` and the
140+ speed at the cut (` tokens_per_sec ` ). Whole answers and Responses
141+ WebSocket turns are not measured.
142+
143+ ### Changed
144+
145+ - ** CPU execution grows with load.** The permanent I/O scheduler uses at
146+ most eight workers by default. Parsing, redaction, inspection and
147+ conversion share CPU admission with password hashing; sufficiently
148+ provisioned 80-CPU machines can run 80 CPU jobs. Extra threads retire
149+ after ten idle seconds. Argon2 also observes a memory-based concurrency
150+ limit, retained until a running hash finishes even if its caller leaves.
151+ - ** Buffers and audit retries retain admission until their final owner
152+ releases them.** Chunked AI/MCP responses, cache reads, transformed
153+ output and detached stream tails use the same buffering budget. MCP
154+ discovery, provider/registry catalogs, OAuth endpoints, S3 reads and
155+ audit-forwarder diagnostics also use bounded reads. Local pressure does
156+ not count as an upstream failure. Audit queue and ClickHouse retry
157+ batches share a separate byte limit and expose buffered-memory and
158+ dropped-entry pressure through metrics.
159+ - ** Release binaries use mimalloc.** Linux also applies a process-local
160+ transparent-huge-page policy before runtime threads start. Host sysctls
161+ and deployment resource settings need no changes.
162+ - ** A redaction policy written through ` PATCH /api/admin/settings ` keeps
163+ the stored exceptions** , whatever it carries: they are changed only
164+ through their own endpoints, and the console writes the rest of the
165+ policy back from the rule view, which does not carry them.
166+ - ** Rule names and descriptions come from thinkwatch-core.** The security
167+ page shows each built-in rule's name, reason and description and each
168+ group's name as the rule view gives them, in English or Chinese; the
169+ console no longer keeps its own name tables. Security-log rows and
170+ trial hits name the rule by looking its id up in the rule view. The
171+ rule search also matches prefixes, field names and descriptions.
172+ - ** The conversion of the old PII pattern list** switches on or off only
173+ the four personal-information rules that list could express; the new
174+ personal-information rules keep their factory setting.
175+
14176## [ 3.10.0] — 2026-10-25
15177
16178Upstreams that fail for the moment before any of the answer reached the
@@ -2694,7 +2856,8 @@ unreleased builds should: stop the gateway, run `db/schema.sql`
26942856against PostgreSQL, restart against this tag. The schema is
26952857idempotent end-to-end, so the apply is safe to repeat.
26962858
2697- [ Unreleased ] : https://github.com/ThinkWatchProject/ThinkWatch/compare/v3.10.0...HEAD
2859+ [ Unreleased ] : https://github.com/ThinkWatchProject/ThinkWatch/compare/v3.11.0...HEAD
2860+ [ 3.11.0 ] : https://github.com/ThinkWatchProject/ThinkWatch/releases/tag/v3.11.0
26982861[ 3.10.0 ] : https://github.com/ThinkWatchProject/ThinkWatch/releases/tag/v3.10.0
26992862[ 3.9.1 ] : https://github.com/ThinkWatchProject/ThinkWatch/releases/tag/v3.9.1
27002863[ 3.9.0 ] : https://github.com/ThinkWatchProject/ThinkWatch/releases/tag/v3.9.0
0 commit comments