dsh-mask 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ARCHITECTURE.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- `dsh-mask` anonymizes PII at the model boundary: it rewrites the messages that enter a step so that phones, emails, ID cards, bank cards, keys, and IPs become `<TYPE_N>` placeholders, and it keeps a `placeholder → original` restore table so those placeholders can be mapped back at the display layer. The hard invariant is that **the plaintext never enters the session log** — the masked form is what gets logged and sent to the model, so model-visible content reconstructs from the log in placeholder form.
5
+ `dsh-mask` anonymizes PII at the model boundary: it rewrites the messages that enter a step so that phones, emails, ID cards, bank cards, keys, and IPs become `<TYPE_N>` placeholders, and it keeps a `placeholder → original` restore table host-side so those placeholders stay reversible. The restore surface this form ships is the `/mask restore <text>` command plus the exported `RestoreStore` seam; automatically mapping placeholders back in the client UI is the browser half this pure-host form does not ship (see `README.md` Known limitations). The hard invariant is that **the plaintext never enters the session log** — the masked form is what gets logged and sent to the model, so model-visible content reconstructs from the log in placeholder form.
6
6
 
7
7
  ## Roles
8
8
 
@@ -71,4 +71,4 @@ The `dsh_mask` domain has one `restore` table keyed by session id. Its record ho
71
71
 
72
72
  - `mode: regex+ner` — external name/address recognition; fails loudly until a recognizer is wired in (the detector Provider seam above is the plug point).
73
73
  - `scope: tools` — implemented as `tools/post-execute` result-content masking. Tool-argument rewriting is deliberately NOT offered upstream: `tools/pre-execute`'s `PreToolDecision` has no input rewrite because logged/rendered arguments must match what ran, so `tools` scope masks the other model-visible tool surface (the result content) instead of the arguments.
74
- - A browser half would consume the restore table to transparently un-mask assistant bubbles; the host-side restore surface (`/mask restore` + `RestoreStore.restore`) ships, and the browser slot is feature-flagged behind `maskClientEnabled` (default false) pending live slot-catalog verification.
74
+ - A browser half would consume the restore table to transparently un-mask assistant bubbles; the host-side restore surface (`/mask restore` + `RestoreStore.restore`) ships, and `maskClientEnabled` (default false) is the key reserved for that browser slot pending live slot-catalog verification. The key is declared in the schema and validated at load, but no runtime code reads it yet, so it has no effect until the browser half ships.
package/CHANGELOG.md CHANGED
@@ -5,8 +5,29 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.2.10] - 2026-09-12
9
9
 
10
+ ### Fixed
11
+
12
+ - Correct the package description: it claimed the plugin anonymizes "names … and addresses", which the pure-host form never did — `person` and `address` are NER-only entities and `mode: regex+ner` fails loudly at load (see `README.md` Known limitations, `ARCHITECTURE.md`, `SECURITY.md`). The description now states the regex-detectable set (phone, email, ID card, bank card, key, opt-in IP) and records the NER limitation. The false claim was the only one in the repository and was visible on the npm package page; a published version cannot be corrected retroactively, so this takes effect with the next release.
13
+ - Correct the display-layer claim in the description and in all five READMEs. Both said the restore table lets placeholders be mapped back "at the display layer" / that "the restore table and `restore()` are the complete host-side seam a client plugin would consume". There is no display-layer restore: the browser half is not shipped, `index.mjs` exports no bare `restore()` (the seam is the `RestoreStore` class, whose methods take a session id), and `RestoreStore` is a host-side class a browser half cannot consume directly. The text now states what exists — the host-side table and `RestoreStore` seam, reached through a host remote by any future client half, with `/mask restore <text>` as today's unmasking surface.
14
+ - Describe `maskClientEnabled` accurately rather than as dead code. The key is deliberately part of the published surface — declared in `types.d.ts`, documented in `cordis.patch.yml` with its rationale, defaulted in the `Config` schema, and asserted by `test/index.test.mjs` — so it stays. What the docs now say is narrower and true: the key is schema-declared and validated at load, but no runtime code reads it yet, so it has no effect until the browser half ships.
15
+ - Correct the "opt-in" scope in the Chinese README's request-time masking bullet: it called every entity opt-in, while only `ip` is (phone, email, ID card, bank card, and key are on by default). The English copy already said this; the Spanish, Portuguese, and Hindi bullets already scoped `(opt-in)` to `ip` and were left unchanged.
16
+
17
+ ### Docs
18
+
19
+ - Declare the region-specific scope of the built-in detectors in all five READMEs' Known limitations: `phone` matches mainland-China mobile numbers only (`1[3-9]` plus nine digits) and `id-card` matches the 18-character Chinese resident ID only, so other countries' phone numbers and national identifiers are not detected. `email`, `ip`, and `key` are region-agnostic; `bank-card` accepts any 16-19 digit run at a lower confidence score. The behaviour is unchanged — the limitation was simply undocumented.
20
+
21
+ ## [0.2.9] - 2026-09-12
22
+
23
+ ### Changed
24
+
25
+ - Rename the four translated READMEs to `README-<lang>.md`. npm selects the package-page readme as the first markdown file matching its `{README,README.*}` glob (`@npmcli/package-json`, publish path), and that glob order puts `README.<lang>.md` ahead of `README.md` — so npm was serving the Simplified-Chinese file for this package too (measured on 15/15 sampled packages of the family). The new names sit outside the glob, so the English source is served again. No content changed apart from the language-switcher link each translation holds to its siblings, and the repo readme gate still passes. Takes effect with the next release; an already-published version cannot gain a corrected readme retroactively.
26
+ - Pin the `@deepseek-ai/dsh-*` dev/test dependencies to the published `0.1.5-rc.2` line and record `0.1.5-rc.2` in `dshWorkshop.compatibility.dshVersions`; the monthly Compat workflow now runs against `0.1.5-rc.2`. The peer range `>=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0` is unchanged, so no supported host line is dropped.
27
+
28
+ ### Fixed
29
+
30
+ - The release workflow claimed provenance but never passed the flag: it runs `npm publish --access public`, and npm only attests a token-based publish when `--provenance` is given explicitly. The publish step is now `npm publish --access public --provenance`, matching the rest of the family. Takes effect from the next release; an already-published version cannot gain attestations retroactively.
10
31
  ## [0.2.8] - 2026-09-10
11
32
 
12
33
  ### Changed
@@ -16,7 +16,7 @@
16
16
  [![npm version](https://img.shields.io/npm/v/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
17
17
  [![npm downloads](https://img.shields.io/npm/dm/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
18
18
 
19
- [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
19
+ [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
20
20
 
21
21
  </div>
22
22
 
@@ -26,7 +26,7 @@
26
26
 
27
27
  | Superficie | Estado |
28
28
  |---|---|
29
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.1` (adaptado el 2026-09-09): el sobre de sesión conserva su campo ignorable solo para compatibilidad de lectura de logs almacenados - Session.append aún no puede estamparlo, por lo que el comportamiento de la puerta no cambia. Verificado el 2026-09-10 contra el checkout master `dsh-v0.1.5-rc.1` (cadena completa de puertas + smoke de instalación de perfil). |
29
+ | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2` (adaptado el 2026-09-09): el sobre de sesión conserva su campo ignorable solo para compatibilidad de lectura de logs almacenados - Session.append aún no puede estamparlo, por lo que el comportamiento de la puerta no cambia. Verificado el 2026-09-11 contra el checkout master `dsh-v0.1.5-rc.2` (cadena completa de puertas + smoke de instalación de perfil). |
30
30
  | Node | `^22.19.0 \|\| >=24.0.0` |
31
31
  | Plataformas | Donde corra DSH (host puro, regex sin dependencias; sin mitad de navegador) |
32
32
  | Modelo | Modelos de texto totalmente soportados |
@@ -121,7 +121,8 @@ Todas las opciones son campos Schemastery `Config` (modificables desde cordis.ym
121
121
  ## Known limitations
122
122
 
123
123
  - **Solo regex.** `person` y `address` requieren un reconocedor NER externo; fallan al cargar. Cubierto de serie: teléfono, correo, documento, tarjeta, clave e IP (opt-in).
124
- - **La restauración visual necesita una mitad de cliente.** Enmascarar es host-side; desenmascarar burbujas en la UI es una función de navegador que esta forma host puro no incluye. La tabla y `restore()` son el seam host-side completo.
124
+ - **Patrones específicos de región.** Los detectores `phone` e `id-card` solo reconocen formatos de China continental: `phone` es `1[3-9]` seguido de nueve dígitos, e `id-card` es un documento de residente chino de 18 caracteres (17 dígitos más un dígito o `X`). Los teléfonos y documentos de otros países no se detectan. `email`, `ip` y `key` no dependen de la región; `bank-card` acepta cualquier secuencia de 16-19 dígitos con menor confianza.
125
+ - **La restauración visual necesita una mitad de cliente.** Enmascarar es host-side; desenmascarar burbujas en la UI es una función de navegador que esta forma host puro no incluye. El host conserva la tabla y el seam `RestoreStore` exportado (sus métodos piden un id de sesión), así que una futura mitad de cliente debe consumirlos mediante un remoto del host, no directamente; hoy la superficie de desenmascarado es el comando `/mask restore <text>`, y la clave `maskClientEnabled` se declara y valida pero ningún código en ejecución la lee todavía.
125
126
  - **Eventos en `0.1.2-rc.1`.** El host aún no registra `mask/*`, así que los appends de auditoría se omiten (las sesiones siguen cargando).
126
127
 
127
128
  ## Development
@@ -16,7 +16,7 @@
16
16
  [![npm version](https://img.shields.io/npm/v/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
17
17
  [![npm downloads](https://img.shields.io/npm/dm/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
18
18
 
19
- [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
19
+ [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
20
20
 
21
21
  </div>
22
22
 
@@ -26,7 +26,7 @@
26
26
 
27
27
  | सतह | स्थिति |
28
28
  |---|---|
29
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.1` (2026-09-09 को अनुकूलित): सत्र लिफ़ाफ़ा अपना ignorable फ़ील्ड केवल संग्रहीत-लॉग पठन संगतता के लिए रखता है - Session.append अभी भी इसे स्टैम्प नहीं कर सकता, इसलिए गेट व्यवहार अपरिवर्तित है। 2026-09-10 को `dsh-v0.1.5-rc.1` master checkout के विरुद्ध सत्यापित (पूर्ण गेट शृंखला + profile इंस्टॉल स्मोक)। |
29
+ | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2` (2026-09-09 को अनुकूलित): सत्र लिफ़ाफ़ा अपना ignorable फ़ील्ड केवल संग्रहीत-लॉग पठन संगतता के लिए रखता है - Session.append अभी भी इसे स्टैम्प नहीं कर सकता, इसलिए गेट व्यवहार अपरिवर्तित है। 2026-09-11 को `dsh-v0.1.5-rc.2` master checkout के विरुद्ध सत्यापित (पूर्ण गेट शृंखला + profile इंस्टॉल स्मोक)। |
30
30
  | Node | `^22.19.0 \|\| >=24.0.0` |
31
31
  | प्लेटफ़ॉर्म | जहाँ DSH चले (शुद्ध host, शून्य-निर्भरता regex; कोई ब्राउज़र आधा नहीं) |
32
32
  | मॉडल | टेक्स्ट मॉडल पूर्ण रूप से समर्थित |
@@ -121,7 +121,8 @@ dsh --profile web --dump-config | grep -A2 'id: mask'
121
121
  ## Known limitations
122
122
 
123
123
  - **केवल regex।** `person` और `address` को बाहरी NER पहचानकर्ता चाहिए; लोड पर विफल। बॉक्स में: फ़ोन, ईमेल, आईडी कार्ड, बैंक कार्ड, कुंजी और IP (opt-in)।
124
- - **डिस्प्ले-लेयर पुनर्स्थापना को क्लाइंट आधा चाहिए।** मास्किंग host-side है; UI बुलबुलों को खोलना एक ब्राउज़र-आधा सुविधा है जो यह शुद्ध-host रूप नहीं देता। तालिका और `restore()` पूर्ण host-side seam हैं।
124
+ - **क्षेत्र-विशिष्ट पैटर्न।** `phone` और `id-card` डिटेक्टर केवल मुख्य भूमि चीन के प्रारूप पहचानते हैं: `phone` = `1[3-9]` के बाद नौ अंक, और `id-card` = 18 वर्णों वाला चीनी निवासी आईडी (17 अंक और एक अंक या `X`)। अन्य देशों के फ़ोन नंबर और राष्ट्रीय पहचान पत्र नहीं पकड़े जाते। `email`, `ip` और `key` क्षेत्र-निरपेक्ष हैं; `bank-card` किसी भी 16-19 अंकों की श्रृंखला को कम विश्वास के साथ स्वीकार करता है।
125
+ - **डिस्प्ले-लेयर पुनर्स्थापना को क्लाइंट आधा चाहिए।** मास्किंग host-side है; UI बुलबुलों को खोलना एक ब्राउज़र-आधा सुविधा है जो यह शुद्ध-host रूप नहीं देता। host तालिका और निर्यातित `RestoreStore` seam रखता है (उसके मेथड को session id चाहिए), इसलिए भविष्य का क्लाइंट आधा उन्हें host remote से लेगा, सीधे नहीं; आज अनमास्किंग का सतह `/mask restore <text>` कमांड है, और `maskClientEnabled` कुंजी schema में घोषित व मान्य होती है पर अभी कोई रनटाइम कोड उसे नहीं पढ़ता।
125
126
  - **`0.1.2-rc.1` इवेंट।** host अभी `mask/*` दर्ज नहीं करता, इसलिए ऑडिट appends छोड़े जाते हैं (सत्र लोड होते रहते हैं)।
126
127
 
127
128
  ## Development
@@ -16,7 +16,7 @@
16
16
  [![npm version](https://img.shields.io/npm/v/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
17
17
  [![npm downloads](https://img.shields.io/npm/dm/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
18
18
 
19
- [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
19
+ [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
20
20
 
21
21
  </div>
22
22
 
@@ -26,7 +26,7 @@
26
26
 
27
27
  | Superfície | Estado |
28
28
  |---|---|
29
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.1` (adaptado em 2026-09-09): o envelope de sessão mantém seu campo ignorable apenas para compatibilidade de leitura de logs armazenados - o Session.append ainda não consegue estampá-lo, então o comportamento da porta não muda. Verificado em 2026-09-10 contra o checkout master `dsh-v0.1.5-rc.1` (cadeia completa de portas + smoke de instalação de perfil). |
29
+ | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2` (adaptado em 2026-09-09): o envelope de sessão mantém seu campo ignorable apenas para compatibilidade de leitura de logs armazenados - o Session.append ainda não consegue estampá-lo, então o comportamento da porta não muda. Verificado em 2026-09-11 contra o checkout master `dsh-v0.1.5-rc.2` (cadeia completa de portas + smoke de instalação de perfil). |
30
30
  | Node | `^22.19.0 \|\| >=24.0.0` |
31
31
  | Plataformas | Onde o DSH rodar (host puro, regex sem dependências; sem metade de navegador) |
32
32
  | Modelo | Modelos de texto totalmente suportados |
@@ -121,7 +121,8 @@ Todas as opções são campos Schemastery `Config` (alteráveis via cordis.yml).
121
121
  ## Known limitations
122
122
 
123
123
  - **Somente regex.** `person` e `address` exigem um reconhecedor NER externo; falham ao carregar. Coberto de série: telefone, e-mail, documento, cartão, chave e IP (opt-in).
124
- - **A restauração visual precisa de uma metade de cliente.** Mascarar é host-side; desmascarar bolhas na UI é uma função de navegador que esta forma host puro não inclui. A tabela e `restore()` são o seam host-side completo.
124
+ - **Padrões específicos de região.** Os detectores `phone` e `id-card` reconhecem apenas formatos da China continental: `phone` é `1[3-9]` seguido de nove dígitos, e `id-card` é um documento de residente chinês de 18 caracteres (17 dígitos mais um dígito ou `X`). Telefones e documentos de outros países não são detectados. `email`, `ip` e `key` não dependem da região; `bank-card` aceita qualquer sequência de 16-19 dígitos com menor confiança.
125
+ - **A restauração visual precisa de uma metade de cliente.** Mascarar é host-side; desmascarar bolhas na UI é uma função de navegador que esta forma host puro não inclui. O host mantém a tabela e o seam `RestoreStore` exportado (seus métodos pedem um id de sessão), então uma futura metade de cliente precisa consumi-los por um remoto do host, não diretamente; hoje a superfície de desmascaramento é o comando `/mask restore <text>`, e a chave `maskClientEnabled` é declarada e validada mas nenhum código em execução a lê ainda.
125
126
  - **Eventos em `0.1.2-rc.1`.** O host ainda não registra `mask/*`, então os appends de auditoria são omitidos (sessões continuam carregando).
126
127
 
127
128
  ## Development
@@ -16,7 +16,7 @@
16
16
  [![npm version](https://img.shields.io/npm/v/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
17
17
  [![npm downloads](https://img.shields.io/npm/dm/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
18
18
 
19
- [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
19
+ [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
20
20
 
21
21
  </div>
22
22
 
@@ -26,7 +26,7 @@
26
26
 
27
27
  | 维度 | 状态 |
28
28
  |---|---|
29
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.1`(2026-09-09 已适配):会话信封保留 ignorable 字段但仅用于存量日志读取兼容——Session.append 仍无法盖章,门控行为不变。已于 2026-09-10 针对 `dsh-v0.1.5-rc.1` master checkout 核验(全量门禁链 + profile 安装冒烟测试)。 |
29
+ | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2`(2026-09-09 已适配):会话信封保留 ignorable 字段但仅用于存量日志读取兼容——Session.append 仍无法盖章,门控行为不变。已于 2026-09-11 针对 `dsh-v0.1.5-rc.2` master checkout 核验(全量门禁链 + profile 安装冒烟测试)。 |
30
30
  | Node | `^22.19.0 \|\| >=24.0.0` |
31
31
  | 平台 | 任何 DSH 可运行处(纯 host、零依赖正则;无浏览器半) |
32
32
  | 模型 | 文本模型完全支持;无需额外模型能力 |
@@ -35,7 +35,7 @@
35
35
 
36
36
  `dsh-mask` 在**模型边界**匿名化个人数据——消息进入模型之前——并维护一张恢复表,以便在展示层把占位符映射回原文:
37
37
 
38
- - **请求前遮罩** —— 重写 `agent/pre-step` 消息,使电话、邮箱、身份证、银行卡、密钥与 IP(均可按需开启)变成 `<PHONE_1>` 之类的占位符。被遮罩的文本才是落盘并发送给模型的内容。
38
+ - **请求前遮罩** —— 重写 `agent/pre-step` 消息,使电话、邮箱、身份证、银行卡、密钥(默认开启)与 IP(可选)变成 `<PHONE_1>` 之类的占位符。被遮罩的文本才是落盘并发送给模型的内容。
39
39
  - **恢复表** —— `占位符 → 原文` 映射只存内存与受控 storage domain(`dsh_mask`);原文绝不进会话日志。
40
40
  - **审计不含明文** —— `mask/applied` 会话事件只记「替换了 N 处 + 类型分布」,不记原文与映射。
41
41
  - **`/mask` 命令** —— `status`(计数 + 分布)、`on`/`off`(运行时开关)、`restore <text>`(还原占位符)、`help`。
@@ -139,14 +139,15 @@ profile patch 覆盖示例:
139
139
  ## Known limitations
140
140
 
141
141
  - **仅正则。** 姓名(`person`)与地址(`address`)识别需要外部 NER 识别器,纯 host 零依赖形态未捆绑;`mode: regex+ner` 与这些实体在加载期响亮失败。开箱即用覆盖电话、邮箱、身份证、银行卡、密钥与(可选)IP。
142
- - **展示层还原需要浏览器半。** 遮罩完全在 host 侧,但客户端 UI 中透明还原助手气泡属于浏览器半功能,本纯 host 形态未交付;恢复表与 `restore()` 是供客户端插件消费的完整 host 侧 seam,交互需求现由 `/mask restore` 覆盖。
142
+ - **正则具地域局限。** `phone` 与 `id-card` 只匹配中国大陆格式:`phone` 为 `1[3-9]` 加九位数字,`id-card` 为 18 位中国居民身份证(17 位数字加一位数字或 `X`)。其他国家的电话号码与证件号码不会被检出。`email`、`ip`、`key` 与地域无关;`bank-card` 以较低置信度接受任意 16-19 位数字串。
143
+ - **展示层还原需要浏览器半。** 遮罩完全在 host 侧,但客户端 UI 中透明还原助手气泡属于浏览器半功能,本纯 host 形态未交付。host 侧保留恢复表与已导出的 `RestoreStore` seam(其方法需要会话 id),因此未来的客户端半需经 host 远程面间接消费,而非直接使用;当前的反遮罩入口是 `/mask restore <text>` 命令;`maskClientEnabled` 键会被 schema 声明与校验,但尚无任何运行时代码读取它。
143
144
  - **`0.1.2-rc.1` 会话事件。** 宿主尚未收录 `mask/*` 事件类型,且其 `Session.append` 不盖章 `ignorable` 信封,因此 alpha.3 上会话日志审计 append 被跳过(会话仍可加载);宿主收录类型或支持 `ignorable` 信封后自动开启。
144
145
 
145
146
  ## Development
146
147
 
147
148
  ```sh
148
149
  pnpm install # node ^22.19 || >=24
149
- pnpm run typecheck && pnpm run typecheck:ci # tsc --checkJs(对照 0.1.5-rc.1 peers)
150
+ pnpm run typecheck && pnpm run typecheck:ci # tsc --checkJs(对照 0.1.5-rc.2 peers)
150
151
  pnpm test # node --test
151
152
  pnpm run verify:self-contained # 依赖 spec 均来自 registry
152
153
  pnpm run verify:artifacts # 发布文件齐全 + index.mjs 可 import
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  - **1024 store channel**: `npm i -g dsh1024` once, then `dsh1024 plugin --profile web add dsh-mask` (counts toward the [deepseek1024.com](https://deepseek1024.com) install ranking).
5
5
  [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-mask)
6
6
 
7
- **PII masking middleware for DeepSeek Harness — anonymize personal data before it reaches the model, restore it at the display layer.**
7
+ **PII masking middleware for DeepSeek Harness — anonymize personal data before it reaches the model, keep it reversible host-side.**
8
8
 
9
9
  *Phones, emails, ID cards, bank cards, keys, and more become placeholders at the model boundary; the plaintext never enters your session log.*
10
10
 
@@ -17,7 +17,7 @@
17
17
  [![npm version](https://img.shields.io/npm/v/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
18
18
  [![npm downloads](https://img.shields.io/npm/dm/dsh-mask)](https://www.npmjs.com/package/dsh-mask)
19
19
 
20
- [English](README.md) · [简体中文](README.zh.md) · [Español](README.es.md) · [Português](README.pt.md) · [हिन्दी](README.hi.md)
20
+ [English](README.md) · [简体中文](README-zh.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
21
21
 
22
22
  </div>
23
23
 
@@ -27,16 +27,16 @@
27
27
 
28
28
  | Surface | Status |
29
29
  |---|---|
30
- | Harness | DeepSeek Harness `dsh-v0.1.5-rc.1` (adapted 2026-09-09): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged. Verified 2026-09-10 against the dsh-v0.1.5-rc.1 master checkout (full gate chain + profile install smoke). |
30
+ | Harness | DeepSeek Harness `dsh-v0.1.5-rc.2` (adapted 2026-09-09): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged. Verified 2026-09-11 against the dsh-v0.1.5-rc.2 master checkout (full gate chain + profile install smoke). |
31
31
  | Node | `^22.19.0 \|\| >=24.0.0` |
32
32
  | Platforms | Anywhere DSH runs (pure host, zero-dependency regex; no browser half) |
33
33
  | Model | Text models fully supported; no extra model capability required |
34
34
 
35
35
  ## What you get
36
36
 
37
- `dsh-mask` anonymizes personal data **at the model boundary** — before a message reaches the model — and keeps a restore table so placeholders can be mapped back to the originals at the display layer:
37
+ `dsh-mask` anonymizes personal data **at the model boundary** — before a message reaches the model — and keeps a restore table host-side so placeholders stay reversible:
38
38
 
39
- - **Request-time masking** — `agent/pre-step` messages are rewritten so phones, emails, ID cards, bank cards, keys, and IPs (each opt-in) become `<PHONE_1>`-style placeholders. The masked text is what gets logged and sent to the model.
39
+ - **Request-time masking** — `agent/pre-step` messages are rewritten so phones, emails, ID cards, bank cards, and keys (on by default) and IPs (opt-in) become `<PHONE_1>`-style placeholders. The masked text is what gets logged and sent to the model.
40
40
  - **Restore table** — the `placeholder → original` map lives only in memory and a controlled storage domain (`dsh_mask`); the plaintext never enters the session log.
41
41
  - **Audit, not plaintext** — the `mask/applied` session event records only "replaced N values + type distribution", never the original text or the mapping.
42
42
  - **`/mask` command** — `status` (counts + distribution), `on`/`off` (runtime toggle), `restore <text>` (unmap placeholders), `help`.
@@ -100,7 +100,7 @@ All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id
100
100
  | `persistRestoreTable` | `true` | Persist the restore table to the controlled `dsh_mask` storage domain (`false` = memory only) |
101
101
  | `maxRestoreEntriesPerSession` | `500` | Per-session restore entry cap (oldest evicted first) |
102
102
  | `maxSessions` | `1000` | In-memory session cap (least-recently-used evicted, mapping reloaded on demand) |
103
- | `maskClientEnabled` | `false` | Feature flag for the browser half "reveal" bubble (defensive; off by default until the live slot catalog verifies the target slot) |
103
+ | `maskClientEnabled` | `false` | Feature flag for the browser half "reveal" bubble (defensive; off by default until the live slot catalog verifies the target slot). The key is schema-declared and validated, but no runtime code reads it yet, so it changes nothing until the browser half ships |
104
104
 
105
105
  Example override in your profile patch:
106
106
 
@@ -142,14 +142,15 @@ Example override in your profile patch:
142
142
  ## Known limitations
143
143
 
144
144
  - **Regex only.** Name (`person`) and address (`address`) recognition needs an external NER recognizer, which the pure-host zero-dependency form does not bundle; `mode: regex+ner` and those entities fail loudly at load. The PII types covered out of the box are phone, email, ID card, bank card, key, and (opt-in) IP.
145
- - **Display-layer restore needs a client half.** Masking is fully host-side, but transparently un-masking the assistant bubbles in the client UI is a browser-half feature this pure-host form does not ship; the restore table and `restore()` are the complete host-side seam a client plugin would consume, and `/mask restore` covers interactive needs today.
145
+ - **Region-specific patterns.** The `phone` and `id-card` detectors match mainland-China formats only: `phone` is `1[3-9]` followed by nine digits, and `id-card` is an 18-character Chinese resident ID (17 digits plus a digit or `X`). Phone numbers and national identifiers from other countries are not detected. `email`, `ip`, and `key` are region-agnostic; `bank-card` accepts any 16-19 digit run at a lower confidence score.
146
+ - **Display-layer restore needs a client half.** Masking is fully host-side, but transparently un-masking the assistant bubbles in the client UI is a browser-half feature this pure-host form does not ship. The host side keeps the restore table and the exported `RestoreStore` seam (its methods take a session id), so a future client half would reach them through a host remote rather than directly; today the unmasking surface is the `/mask restore <text>` command, and the `maskClientEnabled` key is validated but read by no runtime code yet.
146
147
  - **Session events on `0.1.2-rc.1`.** The harness does not yet record `mask/*` event types, and its `Session.append` does not stamp the `ignorable` envelope, so on alpha.3 the session-log audit appends are skipped (sessions keep loading); the plugin enables them automatically once a host records the types or supports the `ignorable` envelope.
147
148
 
148
149
  ## Development
149
150
 
150
151
  ```sh
151
152
  pnpm install # node ^22.19 || >=24
152
- pnpm run typecheck && pnpm run typecheck:ci # tsc --checkJs against the published 0.1.5-rc.1 peers
153
+ pnpm run typecheck && pnpm run typecheck:ci # tsc --checkJs against the published 0.1.5-rc.2 peers
153
154
  pnpm test # node --test
154
155
  pnpm run verify:self-contained # dependency specs resolve from the registry
155
156
  pnpm run verify:artifacts # shipped files present + index.mjs importable
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-mask",
3
- "description": "PII masking middleware for DeepSeek Harness: anonymize names, phones, emails, ID cards, bank cards, keys, and addresses to placeholders before they reach the model, restore them at the display layer, keep the restore table only in memory and a controlled storage domain, never log plaintext, and expose /mask and the mask_test tool",
4
- "version": "0.2.8",
3
+ "description": "PII masking middleware for DeepSeek Harness: regex-detect and replace phones, emails, ID cards, bank cards, keys, and (opt-in) IPs with placeholders before they reach the model, keep the restore table host-side (memory plus a controlled storage domain, never the session log) with the /mask restore command and the exported RestoreStore seam, and expose /mask status and the mask_test tool. Name and address recognition needs an external NER recognizer, which this pure-host form does not bundle: mode \"regex+ner\" and the person/address entities fail loudly at load. The phone and ID-card detectors match mainland-China formats only.",
4
+ "version": "0.2.10",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/PerryLink/dsh-mask.git"
@@ -28,10 +28,10 @@
28
28
  "lib",
29
29
  "cordis.patch.yml",
30
30
  "README.md",
31
- "README.zh.md",
32
- "README.es.md",
33
- "README.pt.md",
34
- "README.hi.md",
31
+ "README-zh.md",
32
+ "README-es.md",
33
+ "README-pt.md",
34
+ "README-hi.md",
35
35
  "ARCHITECTURE.md",
36
36
  "CHANGELOG.md",
37
37
  "SECURITY.md",
@@ -69,7 +69,7 @@
69
69
  "network:none"
70
70
  ],
71
71
  "compatibility": {
72
- "dshVersions": ["0.1.2-rc.1","0.1.5-rc.1"]
72
+ "dshVersions": ["0.1.2-rc.1","0.1.5-rc.2"]
73
73
  },
74
74
  "capability": {
75
75
  "id": "mask",
@@ -98,18 +98,18 @@
98
98
  "zod": "^4.4.3"
99
99
  },
100
100
  "devDependencies": {
101
- "@deepseek-ai/dsh-attachment": "0.1.5-rc.1",
101
+ "@deepseek-ai/dsh-attachment": "0.1.5-rc.2",
102
102
  "@deepseek-ai/cordis": "^4.0.2",
103
103
  "@deepseek-ai/cordis-plugin-include": "^1.0.7",
104
104
  "@deepseek-ai/cordis-plugin-loader": "^1.0.3",
105
- "@deepseek-ai/dsh-agent": "0.1.5-rc.1",
106
- "@deepseek-ai/dsh-commands": "0.1.5-rc.1",
107
- "@deepseek-ai/dsh-session": "0.1.5-rc.1",
108
- "@deepseek-ai/dsh-storage": "0.1.5-rc.1",
109
- "@deepseek-ai/dsh-storage-domain": "0.1.5-rc.1",
110
- "@deepseek-ai/dsh-storage-json": "0.1.5-rc.1",
111
- "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.1",
112
- "@deepseek-ai/dsh-tools": "0.1.5-rc.1",
105
+ "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
106
+ "@deepseek-ai/dsh-commands": "0.1.5-rc.2",
107
+ "@deepseek-ai/dsh-session": "0.1.5-rc.2",
108
+ "@deepseek-ai/dsh-storage": "0.1.5-rc.2",
109
+ "@deepseek-ai/dsh-storage-domain": "0.1.5-rc.2",
110
+ "@deepseek-ai/dsh-storage-json": "0.1.5-rc.2",
111
+ "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
112
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
113
113
  "@deepseek-ai/schemastery": "^3.18.2",
114
114
  "@types/node": "^22.19.0",
115
115
  "oxlint": "0.18.1",