@dsh-enhanced/assistant-policy 0.1.3
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/LICENSE +21 -0
- package/README.md +136 -0
- package/cordis.patch.yml +13 -0
- package/lib/approval-reviewer.d.ts +39 -0
- package/lib/approval-reviewer.d.ts.map +1 -0
- package/lib/approval-reviewer.js +119 -0
- package/lib/approval-reviewer.js.map +1 -0
- package/lib/auto-review.d.ts +22 -0
- package/lib/auto-review.d.ts.map +1 -0
- package/lib/auto-review.js +442 -0
- package/lib/auto-review.js.map +1 -0
- package/lib/evaluator.d.ts +4 -0
- package/lib/evaluator.d.ts.map +1 -0
- package/lib/evaluator.js +127 -0
- package/lib/evaluator.js.map +1 -0
- package/lib/index.d.ts +20 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +16 -0
- package/lib/index.js.map +1 -0
- package/lib/ledger.d.ts +253 -0
- package/lib/ledger.d.ts.map +1 -0
- package/lib/ledger.js +891 -0
- package/lib/ledger.js.map +1 -0
- package/lib/redaction.d.ts +2 -0
- package/lib/redaction.d.ts.map +1 -0
- package/lib/redaction.js +21 -0
- package/lib/redaction.js.map +1 -0
- package/lib/service.d.ts +124 -0
- package/lib/service.d.ts.map +1 -0
- package/lib/service.js +773 -0
- package/lib/service.js.map +1 -0
- package/lib/session-event-registration.d.ts +23 -0
- package/lib/session-event-registration.d.ts.map +1 -0
- package/lib/session-event-registration.js +384 -0
- package/lib/session-event-registration.js.map +1 -0
- package/lib/settlement.d.ts +30 -0
- package/lib/settlement.d.ts.map +1 -0
- package/lib/settlement.js +54 -0
- package/lib/settlement.js.map +1 -0
- package/lib/sqlite.d.ts +9 -0
- package/lib/sqlite.d.ts.map +1 -0
- package/lib/sqlite.js +276 -0
- package/lib/sqlite.js.map +1 -0
- package/lib/tool-risk.d.ts +10 -0
- package/lib/tool-risk.d.ts.map +1 -0
- package/lib/tool-risk.js +321 -0
- package/lib/tool-risk.js.map +1 -0
- package/lib/types.d.ts +73 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/version.d.ts +2 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +2 -0
- package/lib/version.js.map +1 -0
- package/package.json +98 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-enhanced contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# @dsh-enhanced/assistant-policy
|
|
2
|
+
|
|
3
|
+
个人助理的统一授权边界:默认拒绝、单调工具 guard、策略自有硬预算、持久审批提案、紧急停止和脱敏审计。后续 Memory、Wiki、Automation、Channel 与 Credential 插件只通过 `ctx.assistantPolicy` 请求授权,不应各自实现一套可绕过的规则。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
dsh plugin --profile web add @dsh-enhanced/assistant-policy
|
|
9
|
+
dsh --profile web --dump-config
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
默认配置把数据库放在 `$DSH_HOME/assistant-policy/policy.sqlite`,并且 `rules` 为空、`toolDefaultEffect` 为 `deny`。因此插件安装后会拒绝所有经过 DSH `tools.guard()` 的工具调用,直到 profile 的 `cordis.patch.yml` 明确配置 allow 规则。这是预期的 fail-closed 行为。把 `toolDefaultEffect` 设为 `allow` 只会放行没有匹配规则的工具执行;显式 deny、紧急停止、身份缺失和已耗尽预算始终优先,不能被“完全访问”或自动审核绕过。
|
|
13
|
+
|
|
14
|
+
## 最小配置
|
|
15
|
+
|
|
16
|
+
下面只允许 `primary` preset 在指定 workspace 的前台会话读取文件;`bash` 和后台任务仍会被拒绝:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: dsh-enhanced-assistant-policy
|
|
20
|
+
name: '@dsh-enhanced/assistant-policy'
|
|
21
|
+
config:
|
|
22
|
+
databasePath: !!js dshHomePath('assistant-policy/policy.sqlite')
|
|
23
|
+
proposalMaintenanceIntervalMs: 15000
|
|
24
|
+
toolDefaultEffect: deny
|
|
25
|
+
autoReview:
|
|
26
|
+
enabled: true
|
|
27
|
+
timeoutMs: 30000
|
|
28
|
+
maxTokens: 512
|
|
29
|
+
rules:
|
|
30
|
+
- id: allow-primary-workspace-read
|
|
31
|
+
effect: allow
|
|
32
|
+
subject:
|
|
33
|
+
kind: agent
|
|
34
|
+
id: primary
|
|
35
|
+
workspace: /absolute/path/to/workspace
|
|
36
|
+
actions: [execute]
|
|
37
|
+
resource:
|
|
38
|
+
kind: tool
|
|
39
|
+
id: read
|
|
40
|
+
context:
|
|
41
|
+
initiators: [foreground]
|
|
42
|
+
budgets: []
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
匹配支持完整字符串中的 `*` 通配符。任意匹配的 deny 都优先于 allow;同 effect 先选更具体的规则,再按声明顺序决定。工具身份来自 rc.8 的 `Agent.session.header.agentPreset` 与绝对 `cwd`,缺少 agent、preset 或 workspace 时直接拒绝,调用方参数不能伪造这些字段。
|
|
46
|
+
|
|
47
|
+
## 三档即时审批
|
|
48
|
+
|
|
49
|
+
生产三档由标准 `permission/preset`、`sandbox/mode` 与 `approval/policy` 共同决定:官方 id `workspace-write` / `auto` / `danger-full-access` 分别映射 reviewer `user` / `auto-review` / `none`,而且日志中更晚的官方选择会覆盖更早的旧 reviewer 事件。`assistant-policy/approval-reviewer` 仍保留为旧 session、单 workspace preset 或第三方动态 id 的兼容事实;无论意图来自哪一种事件,执行状态仍逐项核验:
|
|
50
|
+
|
|
51
|
+
- **请求批准**:`sandbox/mode: workspace-write` + `approval/policy: ask` + reviewer `user`。低风险精确 allowlist 直接继续,其余动作交给人工。
|
|
52
|
+
- **帮我批准**:`sandbox/mode: workspace-write` + `approval/policy: ask` + reviewer `auto-review`。只有本地归为 `ask-review` 的未知或可能低风险动作才会进入隔离 LLM reviewer;本地明确识别出的网络、凭据、后台、破坏性、提权和复杂 shell 始终交给人工。
|
|
53
|
+
- **完全访问权限**:只有显式且同时生效的 `sandbox/mode: danger-full-access` + `approval/policy: never` + reviewer `none` 才会绕过参数级即时风险门。单独的 `never`、缺少 sandbox 事件、事件畸形或三者暂时不一致都会失败关闭,绝不会把 headless 的“不询问”误解成 full;此时敏感工具直接返回稳定的 `[approval-disabled]` 诊断,并明确说明没有向用户展示审批,不再制造 `the user rejected tool` 的错误归因。`tools.guard()` 的显式 deny、紧急停止、身份和预算检查仍然单调生效;若希望未匹配工具也可执行,需要显式配置 `toolDefaultEffect: allow`。
|
|
54
|
+
|
|
55
|
+
包根导出 `approvalReviewerOf(events)`、`getApprovalReviewer(session)` 和兼容 setter `setApprovalReviewer(session, reviewer)`;setter 只接受 `user | auto-review | none`。auto 与 full 都要求 preset 意图、显式 approval 和显式 sandbox 完整一致;缺项、畸形事件或切换中的中间状态只会折回 `user`。因此 Web 的 full→auto、ask→auto,以及 Delivery auto→Web ask 都由最新官方 preset 直接串行折叠,不再依赖另写 custom reviewer。
|
|
56
|
+
|
|
57
|
+
canonical `danger-full-access` 现在直接折叠为 reviewer `none`,不需要迁移写入。仅对旧版/第三方的非 canonical full preset,插件仍在 live session 扫描、`session/created` 和工具执行屏障做严格兼容迁移;它要求显式 full bundle、sandbox 与 approval 完全一致且没有 reviewer,失败则收窄并拒绝本次工具。
|
|
58
|
+
|
|
59
|
+
`assistant-policy/approval-reviewer` 是 required session event。DSH rc.8 尚无公开事件注册 API,而且独立安装/软链接插件时,插件和 DSH Host 可能各自加载一份 `@deepseek-ai/dsh-session`。本包会同步校验 format v0,并在插件本地目录与从真实 Host 入口解析出的目录不同的情况下同时做精确、进程生命周期内单调注册;npm/pnpm bin 会先解析软链接,不依赖固定安装路径。注册不能在插件卸载或 HMR 时删除,否则 persistence 的关机 drain 和已有 session 冷恢复可能再次把事件判为 unknown。若无法从真实入口解析 Host copy,或已解析到的 copy 在格式、导出形态、同步加载能力上不兼容,插件都会 fail fast,拒绝仅修改本地目录并要求同步更新兼容层。
|
|
60
|
+
|
|
61
|
+
参数级风险门不是宽泛的字符串前缀判断,也不声称实现了完整 shell parser:
|
|
62
|
+
|
|
63
|
+
- `read` / `read_image` 只有一个可证明位于 workspace 内且不带 credential-sensitive 标记的本地路径时可继续;`glob` / `grep` 只接受已知参数形态,并对 search root、glob/include 做同样的词法范围检查。workspace 外、`.env`、`.ssh`、`.codex/auth.json` 等敏感目标、URL、缺失路径或未知参数一律交人工;
|
|
64
|
+
- `pwd`、受限 `ls`、`git status --short` 等少量精确 argv 形态可继续;其 `workdir` 与 `ls` 路径操作数仍必须位于非 credential 的 workspace 范围内,未知或畸形 bash 参数失败关闭;
|
|
65
|
+
- 简单但未分类的命令(例如 `pnpm test`)与未知工具进入 `ask-review`。`run_code` 例外:当前 worker runtime 是 bash-equivalent 的便利执行环境,不是 OS 安全边界,代码可触达 Node/进程能力,因此在 ask/auto 档始终进入 `ask-human`,不会交给模型自动批准;仅显式完整的 full 档会按其“不再请求批准”的语义直接继续;
|
|
66
|
+
- 网络(包括内置 `web_search` / `web_fetch`)、credential 痕迹、后台执行(包括 `bash.run_in_background: true`)、破坏性操作、提权、workspace 外写入,以及包含管道、重定向、替换、引号等需要真实 shell 解析的命令进入 `ask-human`;`npx`、`npm exec`、`pnpm/yarn dlx` 与 `git submodule update` 也按潜在下载/远端执行直接归入这一档;
|
|
67
|
+
- `pwsh` 在具备独立严格解析器前一律进入 `ask-human`;
|
|
68
|
+
- `bash` / `pwsh` / `write` / `edit` 已携带 DSH rc.8 合法的 `sandbox_permissions: workspace-write | danger-full-access` 和非空 `justification` 时交还工具自身的原生审批,避免弹两次;Codex 风格的 `require_escalated` 或其他畸形升级参数仍交人工。
|
|
69
|
+
|
|
70
|
+
workspace 路径判断是保守的词法检查,不替代宿主对 symlink、文件权限和进程的最终约束。尤其 DSH rc.8 的 `workspace-write` sandbox 不能被当作网络或子进程隔离;这里的风险门只负责授权路由,不是 OS 安全边界。
|
|
71
|
+
|
|
72
|
+
### 隔离自动 reviewer
|
|
73
|
+
|
|
74
|
+
`autoReview.enabled` 默认开启,但只有 session 明确选择 `auto-review` 且动作是 `ask-review` 时才调用。`provider` / `model` 可选;省略时沿用当前 request header 的 provider/model,因此 Codex、TraeX 或其他已选 route 都能供应 reviewer,也可把两者固定到独立 route。请求由插件手工构造,使用独立 system prompt、`tools: []`,不继承 Agent 工具,也不写入主会话。
|
|
75
|
+
|
|
76
|
+
Reviewer 只接收当前 open turn 中唯一、尚未结算的 exact `callId` 参数,以及最近的真实 user-role 文本意图;只信任核心 `user` 与可选 Delivery 的 `delivery` source,`plugin` / `tool` 或未知扩展来源不能充当授权。可信消息只要还含图片等非文本 block 就整体转人工,不会丢掉上下文后让 reviewer 猜测。调用 LLM 前会快照 `permission/preset`、sandbox、approval、reviewer 四类最新事件的 seq/identity、open `turn/start` seq、exact call/settlement event seq、可信 intent event seq 与精确内容;LLM await 返回后以及签发 grant 的同步边界会再次校验 signal 与完整快照。权限或事实漂移(包括先改走再改回的 ABA)绝不会得到 `allowed-once`:仍为一致 auto 档时降级人工,否则返回失败关闭结果。参数和意图都有硬字节上限;发生截断、secret 脱敏、参数 prompt injection、找不到 exact call、重复或已结算 call、route 缺失、超时、provider 错误或非严格 JSON 时,都会交给人工,绝不静默允许。只有严格返回 `outcome=allow`、`riskLevel=low` 且 `authorization` 至少为 `medium` 才可能签发一次性 `allowed-once`;rationale 不进入主模型会话。
|
|
77
|
+
|
|
78
|
+
发送 reviewer 前的本地 secret-like 检查是失败关闭的:除 password/passphrase/passwd/secret/token 等敏感字段名与常见 token 前缀外,也拦截对应自然语言赋值、URI userinfo、PEM private key、JWT,以及 `AKIA` / `ASIA` AWS access key。任何命中都会保持 reviewer 请求数为零并转人工;这是避免跨 provider 外发的最后本地边界,不应把 reviewer provider 当成秘密扫描器。
|
|
79
|
+
|
|
80
|
+
包根的 `isAutoReviewEscalation(request)` 是 auto reviewer 与人工 answerer 的对象级交接信号:它只在同一个 `ApprovalRequest` 被明确升级并执行下游 `next()` 的期间为真,并在 `finally` 中清除。Reviewer listener 使用 waterfall 的 `prepend` 注册,即使 LLM service 晚于人工 listener 到达也先完成自动判定。人工渠道在 auto 档只应认领这个信号标记的请求;其他插件的自定义 approval reason 不会被本插件标记或抢占。
|
|
81
|
+
|
|
82
|
+
## 硬预算
|
|
83
|
+
|
|
84
|
+
额度定义属于 policy 配置,消费者只能引用 `budgetId`,不能传入或抬高 `limit`、`periodMs`:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
rules:
|
|
88
|
+
- id: allow-budgeted-background-tool
|
|
89
|
+
effect: allow
|
|
90
|
+
actions: [execute]
|
|
91
|
+
resource: { kind: tool, id: wiki_* }
|
|
92
|
+
context: { initiators: [background] }
|
|
93
|
+
budget: { id: background-tool-calls, amount: 1 }
|
|
94
|
+
budgets:
|
|
95
|
+
- id: background-tool-calls
|
|
96
|
+
metric: tool-calls
|
|
97
|
+
limit: 100
|
|
98
|
+
periodMs: 86400000
|
|
99
|
+
scope: subject
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
每次带预算的授权必须提供幂等键。策略先在 SQLite 短事务中预留,再立即计入固定收费;进程在两步之间崩溃最多造成保守占额,不会超额。同一业务操作即使跨过预算周期仍重放原 reservation,不会重复扣费;换 scope、metric、period 或 amount 继续失败关闭。可变成本消费者使用 `reserve()`,完成后调用 `finalize()`,失败调用 `release()`。`scope` 可为 `global`、`subject` 或 `workspace`,同样由配置决定。
|
|
103
|
+
|
|
104
|
+
## 服务 API
|
|
105
|
+
|
|
106
|
+
注入名为 `assistantPolicy`。持久账本只属于 service 内部,不从包根导出;消费者不能直接打开数据库或绕过 service 规则。主要方法为:
|
|
107
|
+
|
|
108
|
+
- `evaluate(request)`:只评估,不写审计;紧急停止优先于所有规则。
|
|
109
|
+
- `getEmergencyStop()`:只读返回当前硬门状态,不做 authorize、不写审计且不消耗预算;Delivery 等最终授权方可在提交外部批准前再次复核。
|
|
110
|
+
- `authorize(request, options)`:执行预算检查并追加脱敏审计。
|
|
111
|
+
- `reserve` / `finalize` / `release`:策略配置约束下的可变成本预算。
|
|
112
|
+
- `propose` / `decideProposal`:绑定 principal、版本 CAS、TTL 与幂等键的持久审批提案。所有提案永久保存 diff SHA-256;只有携带 `dispatch` 的 pending 提案会临时保存 immutable diff 原文,路由与提案在同一个 SQLite 事务中落盘。路由 principal 必须与提案 principal 完全一致、workspace 必须为绝对路径。无路由提案和 v1 legacy 提案只凭 hash 安全重放,绝不会在重放时补建路由。
|
|
113
|
+
- `getProposal`:只读地返回某个提案的当前状态(含终态与决定者)。`getProposalByIdempotencyKey` 用完整的 requester、principal、action 和 resource scope 做只读诊断;它绝不创建、重放或延长提案。
|
|
114
|
+
- `recoverOrCreateProposal`:业务域跨 SQLite 恢复时使用的原子入口。调用方提交不可移动的绝对 `notAfter`;Policy 在 `BEGIN IMMEDIATE` 中选择“恢复 exact 既有提案 / 创建一次 / 过期后永久 tombstone 幂等键”。tombstone 的 SHA-256 intent hash 固定绑定 deadline、requester、principal、action、resource、diff、summary 以及 dispatch presence/route,但不保存 diff 明文;v4 遗留 tombstone 缺少可验证 identity,迁移后只会阻止复用,任何 recovery 都失败关闭。因此多个进程不能在 lookup 与 create 之间制造孤儿审批卡,也不能借重启获得新 TTL。本插件**从不回调**业务域,方向永远是域读取 Policy 后通过自己的 gate 提交。
|
|
115
|
+
- `listPendingApprovalDispatches` / `markApprovalDispatchEnqueued`:向 Delivery 提供有界、可 CAS 的 durable approval outbox。展示用的 summary、diff、action、resource、版本与过期时间只能从 policy 已持久化的 canonical proposal 派生,调用方不能替换卡片文案。终态或已过期提案不会被列出。
|
|
116
|
+
- `validateApprovalSettlement(snapshot, expectation)`:跨 Memory / Wiki / Automations / Evolution 共用的纯函数提交门。它逐字段核对 immutable proposal、重新计算 diff SHA-256,并要求终态版本恰好为原版本 `+1`;approved/rejected 必须由绑定 principal 决定,expired 必须由 `system:expiry` 决定。缺失或冲突会抛出稳定的 `ApprovalSettlementConflict`,业务域应 fail closed。
|
|
117
|
+
- `setEmergencyStop` / `getEmergencyStop`:持久紧急停止。
|
|
118
|
+
- `queryAudit`:按 sequence 有界分页,单次最多 100 条。
|
|
119
|
+
- `bindInitiator(agent, initiator, principal?)`:供受信调度器在 Agent 生命周期内绑定 initiator;外部调度器同时传入 canonical principal 后,`authorizeAgent()` 与工具 guard 会把它作为 Agent subject 的精确 principal。释放后恢复前一层绑定。
|
|
120
|
+
|
|
121
|
+
DSH 原生 `user-approval` 仍只负责 open turn 内的即时询问;本插件的 proposal 是跨 turn、可重启恢复的审批状态,不把两者混为一个授权凭证。
|
|
122
|
+
|
|
123
|
+
## 数据与权限
|
|
124
|
+
|
|
125
|
+
- 文件系统:创建一个 SQLite 数据库及 WAL/SHM 辅助文件;新目录权限 `0700`,主数据库 `0600`。数据库使用 WAL、`busy_timeout`、外键、FULL synchronous 和前向 schema 版本。
|
|
126
|
+
- 网络:插件不直接打开 socket;启用隔离自动 reviewer 时会调用宿主 `dsh-llm`,所选 provider route 可能使用网络。provider 的认证与传输仍由宿主拥有,本插件不直接读取其凭据。
|
|
127
|
+
- 子进程:无。
|
|
128
|
+
- 凭据:不读取或保存凭据值。审计按敏感 key/value、shell `command`、授权头、token、password、path/cwd 做脱敏,资源 id 仅保存 SHA-256。自动 reviewer 输入只要需要任何 secret 脱敏就失去自动放行资格并转人工。
|
|
129
|
+
- 浏览器:无。
|
|
130
|
+
- 安装脚本:无。
|
|
131
|
+
|
|
132
|
+
审批展示预算由包根的 frozen `APPROVAL_DISPLAY_BUDGET` 统一公开:Delivery 默认文本上限 64 KiB,summary 最多 120 UTF-8 bytes,diff 最多 60 KiB,预留 4 KiB 给渠道渲染。原始 diff 只在 routed dispatch 仍为 pending 时存在;成功 enqueue、批准、拒绝或过期都会在同一状态事务中清除,v2→v3 迁移也会清除无路由、已 enqueue 和终态记录的遗留原文。业务域仍不得把 credential、token 或其他秘密写进 diff。`proposalMaintenanceIntervalMs` 默认每 15 秒有界地过期 stale proposal,设为 `0` 可关闭,最大值为 `2147483647`。审计是 append-only;当前版本不会自动删除记录,部署者应根据自己的隐私与合规周期备份或轮换整个数据库。SQLite 提供单机多连接并发安全,不承诺多主机共享文件系统上的一致性。
|
|
133
|
+
|
|
134
|
+
## 兼容性
|
|
135
|
+
|
|
136
|
+
已针对 DeepSeek Harness `0.1.0-rc.8`(源码提交 `141eb6fef83422698aef7a981029e843e8161534`)验证。详见仓库[兼容性基线](../../docs/compatibility.md)。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
- insert:
|
|
2
|
+
- id: dsh-enhanced-assistant-policy
|
|
3
|
+
name: '@dsh-enhanced/assistant-policy'
|
|
4
|
+
config:
|
|
5
|
+
databasePath: !!js dshHomePath('assistant-policy/policy.sqlite')
|
|
6
|
+
proposalMaintenanceIntervalMs: 15000
|
|
7
|
+
toolDefaultEffect: deny
|
|
8
|
+
autoReview:
|
|
9
|
+
enabled: true
|
|
10
|
+
timeoutMs: 30000
|
|
11
|
+
maxTokens: 512
|
|
12
|
+
rules: []
|
|
13
|
+
budgets: []
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
|
|
2
|
+
export declare const APPROVAL_REVIEWERS: readonly ["user", "auto-review", "none"];
|
|
3
|
+
export type ApprovalReviewer = typeof APPROVAL_REVIEWERS[number];
|
|
4
|
+
type ApprovalPolicy = 'ask' | 'never';
|
|
5
|
+
type SandboxMode = 'workspace-write' | 'danger-full-access';
|
|
6
|
+
export interface ApprovalPermissionState {
|
|
7
|
+
approvalPolicy?: ApprovalPolicy;
|
|
8
|
+
approvalPolicyEvent: boolean;
|
|
9
|
+
reviewer?: ApprovalReviewer;
|
|
10
|
+
reviewerEvent: boolean;
|
|
11
|
+
sandboxMode?: SandboxMode;
|
|
12
|
+
sandboxModeEvent: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare module '@deepseek-ai/dsh-session/types' {
|
|
15
|
+
interface SessionEventMap {
|
|
16
|
+
/** Durable reviewer selection; log-only and never projected into model history. */
|
|
17
|
+
'assistant-policy/approval-reviewer': {
|
|
18
|
+
reviewer: ApprovalReviewer;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Fold the three durable permission dimensions without inventing missing values. */
|
|
23
|
+
export declare function approvalPermissionStateOf(events: readonly SessionEvent[]): ApprovalPermissionState;
|
|
24
|
+
/** Stable exact-state fingerprint used to close asynchronous reviewer races. */
|
|
25
|
+
export declare function approvalPermissionFingerprint(events: readonly SessionEvent[]): string;
|
|
26
|
+
export declare function hasCoherentFullAccess(events: readonly SessionEvent[]): boolean;
|
|
27
|
+
export declare function hasCoherentAutoReview(events: readonly SessionEvent[]): boolean;
|
|
28
|
+
/** Return the last valid reviewer event, without applying approval-policy compatibility. */
|
|
29
|
+
export declare function foldApprovalReviewer(events: readonly SessionEvent[]): ApprovalReviewer | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Resolve a reviewer conservatively against the standard approval policy.
|
|
32
|
+
* Inconsistent intermediate event order never widens authority.
|
|
33
|
+
*/
|
|
34
|
+
export declare function approvalReviewerOf(events: readonly SessionEvent[]): ApprovalReviewer;
|
|
35
|
+
export declare function getApprovalReviewer(session: Pick<Session, 'events'>): ApprovalReviewer;
|
|
36
|
+
/** Append a validated reviewer transition only when it changes the durable selection. */
|
|
37
|
+
export declare function setApprovalReviewer(session: Session, reviewer: ApprovalReviewer): boolean;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=approval-reviewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-reviewer.d.ts","sourceRoot":"","sources":["../src/approval-reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIrE,eAAO,MAAM,kBAAkB,0CAA2C,CAAA;AAE1E,MAAM,MAAM,gBAAgB,GAAG,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAA;AAEhE,KAAK,cAAc,GAAG,KAAK,GAAG,OAAO,CAAA;AACrC,KAAK,WAAW,GAAG,iBAAiB,GAAG,oBAAoB,CAAA;AAE3D,MAAM,WAAW,uBAAuB;IACtC,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,mBAAmB,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAC3B,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED,OAAO,QAAQ,gCAAgC,CAAC;IAC9C,UAAU,eAAe;QACvB,mFAAmF;QACnF,oCAAoC,EAAE;YACpC,QAAQ,EAAE,gBAAgB,CAAA;SAC3B,CAAA;KACF;CACF;AAwBD,qFAAqF;AACrF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,uBAAuB,CAelG;AAED,gFAAgF;AAChF,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAUrF;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAK9E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAK9E;AAwBD,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAOlG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,gBAAgB,CAGpF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,gBAAgB,CAEtF;AAED,yFAAyF;AACzF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAQzF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { assertApprovalReviewerSessionEventReady } from './session-event-registration.js';
|
|
2
|
+
export const APPROVAL_REVIEWERS = ['user', 'auto-review', 'none'];
|
|
3
|
+
function isApprovalReviewer(value) {
|
|
4
|
+
return typeof value === 'string' && APPROVAL_REVIEWERS.includes(value);
|
|
5
|
+
}
|
|
6
|
+
function asRecord(value) {
|
|
7
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
8
|
+
return undefined;
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function lastPermissionEvent(events, type) {
|
|
12
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
13
|
+
const event = events[index];
|
|
14
|
+
if (String(event.type) !== type)
|
|
15
|
+
continue;
|
|
16
|
+
const data = asRecord(event.data);
|
|
17
|
+
return data === undefined ? { present: true, event } : { present: true, data, event };
|
|
18
|
+
}
|
|
19
|
+
return { present: false };
|
|
20
|
+
}
|
|
21
|
+
/** Fold the three durable permission dimensions without inventing missing values. */
|
|
22
|
+
export function approvalPermissionStateOf(events) {
|
|
23
|
+
const approval = lastPermissionEvent(events, 'approval/policy');
|
|
24
|
+
const reviewer = lastPermissionEvent(events, 'assistant-policy/approval-reviewer');
|
|
25
|
+
const sandbox = lastPermissionEvent(events, 'sandbox/mode');
|
|
26
|
+
const approvalPolicy = approval.data?.policy;
|
|
27
|
+
const reviewerValue = reviewer.data?.reviewer;
|
|
28
|
+
const sandboxMode = sandbox.data?.mode;
|
|
29
|
+
return {
|
|
30
|
+
approvalPolicyEvent: approval.present,
|
|
31
|
+
...(approvalPolicy === 'ask' || approvalPolicy === 'never' ? { approvalPolicy } : {}),
|
|
32
|
+
reviewerEvent: reviewer.present,
|
|
33
|
+
...(isApprovalReviewer(reviewerValue) ? { reviewer: reviewerValue } : {}),
|
|
34
|
+
sandboxModeEvent: sandbox.present,
|
|
35
|
+
...(sandboxMode === 'workspace-write' || sandboxMode === 'danger-full-access' ? { sandboxMode } : {}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Stable exact-state fingerprint used to close asynchronous reviewer races. */
|
|
39
|
+
export function approvalPermissionFingerprint(events) {
|
|
40
|
+
return JSON.stringify([
|
|
41
|
+
'permission/preset',
|
|
42
|
+
'sandbox/mode',
|
|
43
|
+
'approval/policy',
|
|
44
|
+
'assistant-policy/approval-reviewer',
|
|
45
|
+
].map((type) => {
|
|
46
|
+
const current = lastPermissionEvent(events, type).event;
|
|
47
|
+
return current === undefined ? null : [current.seq, String(current.type), current.data];
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
export function hasCoherentFullAccess(events) {
|
|
51
|
+
const state = approvalPermissionStateOf(events);
|
|
52
|
+
return state.approvalPolicyEvent && state.approvalPolicy === 'never'
|
|
53
|
+
&& reviewerIntentOf(events) === 'none'
|
|
54
|
+
&& state.sandboxModeEvent && state.sandboxMode === 'danger-full-access';
|
|
55
|
+
}
|
|
56
|
+
export function hasCoherentAutoReview(events) {
|
|
57
|
+
const state = approvalPermissionStateOf(events);
|
|
58
|
+
return state.approvalPolicyEvent && state.approvalPolicy === 'ask'
|
|
59
|
+
&& reviewerIntentOf(events) === 'auto-review'
|
|
60
|
+
&& state.sandboxModeEvent && state.sandboxMode === 'workspace-write';
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve reviewer intent from the latest durable selector event. The official
|
|
64
|
+
* three-level bundle uses stable preset ids; every other preset is treated as
|
|
65
|
+
* human-reviewed unless a later legacy reviewer event explicitly says
|
|
66
|
+
* otherwise. That default is intentionally fail-closed and lets old logs and
|
|
67
|
+
* third-party one-workspace-preset bundles keep using the compatibility event.
|
|
68
|
+
*/
|
|
69
|
+
function reviewerIntentOf(events) {
|
|
70
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
71
|
+
const event = events[index];
|
|
72
|
+
if (event.type === 'assistant-policy/approval-reviewer') {
|
|
73
|
+
return isApprovalReviewer(event.data.reviewer) ? event.data.reviewer : 'user';
|
|
74
|
+
}
|
|
75
|
+
if (event.type !== 'permission/preset')
|
|
76
|
+
continue;
|
|
77
|
+
const preset = event.data.preset;
|
|
78
|
+
if (preset === 'auto')
|
|
79
|
+
return 'auto-review';
|
|
80
|
+
if (preset === 'danger-full-access')
|
|
81
|
+
return 'none';
|
|
82
|
+
return 'user';
|
|
83
|
+
}
|
|
84
|
+
return 'user';
|
|
85
|
+
}
|
|
86
|
+
/** Return the last valid reviewer event, without applying approval-policy compatibility. */
|
|
87
|
+
export function foldApprovalReviewer(events) {
|
|
88
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
89
|
+
const event = events[index];
|
|
90
|
+
if (event.type !== 'assistant-policy/approval-reviewer')
|
|
91
|
+
continue;
|
|
92
|
+
return isApprovalReviewer(event.data.reviewer) ? event.data.reviewer : undefined;
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Resolve a reviewer conservatively against the standard approval policy.
|
|
98
|
+
* Inconsistent intermediate event order never widens authority.
|
|
99
|
+
*/
|
|
100
|
+
export function approvalReviewerOf(events) {
|
|
101
|
+
if (hasCoherentFullAccess(events))
|
|
102
|
+
return 'none';
|
|
103
|
+
return hasCoherentAutoReview(events) ? 'auto-review' : 'user';
|
|
104
|
+
}
|
|
105
|
+
export function getApprovalReviewer(session) {
|
|
106
|
+
return approvalReviewerOf(session.events);
|
|
107
|
+
}
|
|
108
|
+
/** Append a validated reviewer transition only when it changes the durable selection. */
|
|
109
|
+
export function setApprovalReviewer(session, reviewer) {
|
|
110
|
+
if (!isApprovalReviewer(reviewer)) {
|
|
111
|
+
throw new TypeError('approval reviewer must be one of "user", "auto-review", or "none"');
|
|
112
|
+
}
|
|
113
|
+
if (reviewerIntentOf(session.events) === reviewer)
|
|
114
|
+
return false;
|
|
115
|
+
assertApprovalReviewerSessionEventReady(session);
|
|
116
|
+
session.append('assistant-policy/approval-reviewer', { reviewer });
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=approval-reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-reviewer.js","sourceRoot":"","sources":["../src/approval-reviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { ApprovalRequest } from '@deepseek-ai/dsh-user-approval';
|
|
3
|
+
export interface AutoReviewConfig {
|
|
4
|
+
enabled?: boolean;
|
|
5
|
+
provider?: string;
|
|
6
|
+
model?: string;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
maxTokens?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface AutoReviewAssessment {
|
|
11
|
+
riskLevel: 'low' | 'medium' | 'high' | 'critical';
|
|
12
|
+
authorization: 'unknown' | 'low' | 'medium' | 'high';
|
|
13
|
+
outcome: 'allow' | 'escalate';
|
|
14
|
+
rationale: string;
|
|
15
|
+
}
|
|
16
|
+
/** True only while this exact request is being handed from auto review to a downstream human answerer. */
|
|
17
|
+
export declare function isAutoReviewEscalation(request: ApprovalRequest): boolean;
|
|
18
|
+
/** Strict local parser: prose, fences, missing fields, and extension fields are all rejected. */
|
|
19
|
+
export declare function parseAutoReviewAssessment(text: string): AutoReviewAssessment | undefined;
|
|
20
|
+
/** Register an isolated answerer only when both host services are present. */
|
|
21
|
+
export declare function registerAutoReviewAnswerer(ctx: Context, input: AutoReviewConfig | undefined): void;
|
|
22
|
+
//# sourceMappingURL=auto-review.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-review.d.ts","sourceRoot":"","sources":["../src/auto-review.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAQlD,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,gCAAgC,CAAA;AAQtF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAUD,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAA;IACjD,aAAa,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IACpD,OAAO,EAAE,OAAO,GAAG,UAAU,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AA6BD,0GAA0G;AAC1G,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAExE;AAwBD,iGAAiG;AACjG,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAsBxF;AAqUD,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,CA4BlG"}
|