dsh-perm-gate 5.3.3 → 5.4.0

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/CHANGELOG.ja.md CHANGED
@@ -7,6 +7,12 @@
7
7
 
8
8
  > 注: 2.4.1 から 5.1.2 までは英語版 `CHANGELOG.md` のみに記録されています(ja 版は追随済みではない)。
9
9
 
10
+ ## [5.4.0] - 2026-10-30
11
+
12
+ - 認証情報ファミリーの階段:組み込み7ファミリー(ssh / cloud / package / gitcreds / env / cli / db)、各種類4段 deny / ask(既定)/ readonly / readwrite。段の状態はルール文書自体に保持(`[deny-rule:cred.<family>]` 行 + 対になる `credWriteExemptFamilies` リスト)。設定カードは `GET/POST /api/dsh-perm-gate/cred` 経由で両ストアを単一 update で対書き込みし、ローカルミラーを持たない。readwrite はインライン確認を要求し、P0 の一条(credential-store 書き込み)のみ退く;ルートディスク・保護パス・.dsh・外部送信はどの段でも動かさない。
13
+ - エンジン:`decide()` は READ ツールに対し規則層へ先行照会(名指し命中のみ ask/deny へ;不命中は従来の無音自動通過で確認画面の予算不変)。INTERNAL 調整ツールは先行照会しない。純モジュール `src/cred-families.ts`(族 glob + `familyOfPath`)追加。
14
+ - シード注入:プリセット表 52→59 行;水位キー `presetRulesVersion` でアップグレード後は新規行のみ補完(id 単位幂等、取り消した行は復活しない)。保護ブランチ force push 解除スイッチ `allowProtectedBranchPush`(既定オフ=床維持)とプリセット行 `[deny-rule:rsync.delete]` を追加。
15
+
10
16
  ## [5.3.1] - 2026-10-17
11
17
 
12
18
  ### 追加
package/CHANGELOG.ko.md CHANGED
@@ -7,6 +7,12 @@
7
7
 
8
8
  > 참고: 2.4.1부터 5.1.2까지는 영문 `CHANGELOG.md`에만 기록되어 있습니다 (ko판은 아직 미추적).
9
9
 
10
+ ## [5.4.0] - 2026-10-30
11
+
12
+ - 자격증명 계열 사다리: 내장 7계열(ssh / cloud / package / gitcreds / env / cli / db), 각 유형 4칸 deny / ask(기본) / readonly / readwrite. 칸 상태는 규칙 문서 자체에 저장 — 계열별 `[deny-rule:cred.<family>]` 행 + 짝을 이루는 `credWriteExemptFamilies` 목록. 설정 카드는 `GET/POST /api/dsh-perm-gate/cred`로 두 저장소를 단일 update에 함께 쓰며 지역 사본을 두지 않는다. readwrite는 인라인 확인을 요구하고 P0 판정 중 정확히 하나(credential-store 쓰기)만 물러남; 루트·보호 경로·.dsh·유출은 어떤 칸에서도 움직이지 않는다.
13
+ - 엔진: `decide()`가 READ 도구에서 규칙 계층 선행 조회(이름을 지정한 항목만 ask/deny로 라우팅; 미적중은 기존 무음 자동 통과로 확인 예산 불변). INTERNAL 조율 도구는 선행 조회하지 않는다. 순수 모듈 `src/cred-families.ts`(계열 glob + `familyOfPath`) 추가.
14
+ - 시딩: 프리셋 표 52→59행; 수위 키 `presetRulesVersion`으로 업그레이드 후 신규 행만 보충(id 단위 멱등, 취소한 행은 부활하지 않음). 보호 브랜치 force push 바닥 해제 스위치 `allowProtectedBranchPush`(기본 꺼짐=바닥 유지)와 프리셋 행 `[deny-rule:rsync.delete]` 추가.
15
+
10
16
  ## [5.3.1] - 2026-10-17
11
17
 
12
18
  ### 추가
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.4.0 (2026-10-30)
4
+
5
+ - 凭据类型阶梯:七个内置族(ssh / cloud / package / gitcreds / env / cli / db),每类四档 deny / ask(默认)/ readonly / readwrite。档位状态就住在规则文档本身——每类一条 `[deny-rule:cred.<family>]` 行(分区 + enabled)加成对的 volatile `credWriteExemptFamilies` 清单;设置卡经 `GET/POST /api/dsh-perm-gate/cred` 一条 update 成对读写,无本地镜像、无半态。readwrite 需卡内二次确认,且只退让 P0 的一条判据(凭据 store 写);根盘、受保护路径、.dsh、外发在任何档位不让;自定义 credentialPaths 永不参与写豁免。
6
+ - 引擎:`decide()` 对 READ 工具先问规则层(被具名 ask/deny 命中的文件读才会被路由;未命中保持原静默自动放行,弹窗预算不变);INTERNAL 协调工具永不预询。新增纯模块 `src/cred-families.ts`(族 glob + `familyOfPath`)。
7
+ - 播种:预设表 52→59 行;新 volatile 水位键 `presetRulesVersion`——升级后只补新增行(按 id 幂等,用户撤销的行永不复活)。
8
+ - 保护分支强推地板开关 `allowProtectedBranchPush`(volatile,默认关=地板立;开则地板让位、落入预设 git.push-force 的逐次 ask,并同步豁免黑名单三条扁平 push 词)。
9
+ - 预设表新增 `[deny-rule:rsync.delete]`(rsync --delete 默认 deny,附 dry-run 建议)。
10
+
3
11
  5.3.3: host enumeration addendum for DSH 0.2.1-rc.3 (declaration-only bump; contract plane zero diff).
4
12
 
5
13
  ## 5.3.2 (2026-10-18)
package/README.ja.md CHANGED
@@ -63,7 +63,7 @@ fail-closed を徹底します:P0 の判定は、grant・ルール・分類器
63
63
  上書きされません。
64
64
 
65
65
  <!-- host-compat:begin — generated by scripts/sync-hosts.mjs from scripts/hosts.mjs; DO NOT EDIT -->
66
- - **対応する DSH ホスト:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3`(0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 の 18 rc)
66
+ - **対応する DSH ホスト:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3` `0.2.1-rc.4`(0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 の 19 rc)
67
67
  - **ランタイム検証済み:** `0.2.0-rc.2`(証跡は `.compat-results/`)
68
68
  <!-- host-compat:end -->
69
69
 
@@ -396,6 +396,30 @@ DSH の組み込み表から、後者はインストールガイドに書かれ
396
396
  受けません。
397
397
 
398
398
 
399
+ ## 認証情報ファミリーの階段(`deny / ask / readonly / readwrite`)
400
+
401
+ 認証情報の床は以前一本の判定でした。今は7ファミリー × 4段です——「`.env` を読む前に聞いて」
402
+ と「agent にもう一度 `npm login` をさせる」は別のニーズだからです。
403
+
404
+ | 段 | ファイルツールの読み / 閲覧 | 書き・削除 |
405
+ | --- | --- | --- |
406
+ | `deny` | 規則層で遮断 | P0 で遮断 |
407
+ | `ask`(既定) | 都度人間確認 | P0 で遮断 |
408
+ | `readonly` | 無音通過 | P0 で遮断 |
409
+ | `readwrite` | 無音通過 | 認証情報 store の**書き**判定のみ退く(npm login 系) |
410
+
411
+ - 状態はプラグイン自身の2ストアに住みます:ルール文書の `[deny-rule:cred.<family>]` 行(節 + `enabled`)
412
+ と対になる `credWriteExemptFamilies` リスト。設定カードは `GET/POST /api/dsh-perm-gate/cred`
413
+ で**一回の update** に対で書き戻します。
414
+ - 読み面は「ファイル読み工具が先に規則層へ問う」方式:`decide()` は ruleset に先に問い、
415
+ **名指し命中のみ**採用;不命中は従来の無音自動通過(確認画面の予算不変)。セッション/調整用の
416
+ 内部工具は決して先行照会しません。
417
+ - **`readwrite` が退かすのは一条だけ**——認証情報 store の書き判定。ルート盤・保護パス・
418
+ `.dsh`・外部送信・読みの床はどの段でも効いたまま;適用前にカードが二次確認を求めます。
419
+ カスタム `credentialPaths` は族を持たず、書き免除に参加しません。
420
+ - 7行はプリセット表**バージョン1**として出荷:`presetRulesVersion` 水位で不足行だけを補い、
421
+ 取り消した行は復活しません。
422
+
399
423
  ## CLI(スタンドアロン dry-run)
400
424
 
401
425
  Harness なしで 1 件の呼び出しをルール ファイルに対して評価できます:
package/README.ko.md CHANGED
@@ -61,7 +61,7 @@ DeepSeek Harness용 단일·자족적·결정론 우선·fail-closed 권한 게
61
61
  덮어써지지 않습니다.
62
62
 
63
63
  <!-- host-compat:begin — generated by scripts/sync-hosts.mjs from scripts/hosts.mjs; DO NOT EDIT -->
64
- - **지원하는 DSH 호스트:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3` (0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 라인의 18개 rc)
64
+ - **지원하는 DSH 호스트:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3` `0.2.1-rc.4` (0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 라인의 19개 rc)
65
65
  - **런타임 검증됨:** `0.2.0-rc.2` (증적은 `.compat-results/`)
66
66
  <!-- host-compat:end -->
67
67
 
@@ -395,6 +395,30 @@ DSH 내장 표에서, 후자는 설치 안내에 적힌 호스트 패치에서
395
395
  티어는 모든 화면에서 텍스트만 표시됩니다. 라벨과 게이트는 영향을 받지 않습니다.
396
396
 
397
397
 
398
+ ## 자격증명 계열 사다리 (`deny / ask / readonly / readwrite`)
399
+
400
+ 자격증명 바닥은 예전엔 한 개의 판정이었습니다. 지금은 7계열 × 4칸입니다——"`.env`를 읽기 전에 물어봐"와
401
+ "agent가 `npm login`을 다시 하게 해줘"는 서로 다른 요구이기 때문입니다.
402
+
403
+ | 칸 | 파일 도구 읽기 / 열람 | 쓰기·삭제 |
404
+ | --- | --- | --- |
405
+ | `deny` | 규칙 계층에서 차단 | P0에서 차단 |
406
+ | `ask`(기본) | 매번 사람 확인 | P0에서 차단 |
407
+ | `readonly` | 무음 통과 | P0에서 차단 |
408
+ | `readwrite` | 무음 통과 | 자격증명 store **쓰기** 판정만 물러남(npm login 계열) |
409
+
410
+ - 상태는 플러그인이 소유한 두 저장소에 삽니다: 규칙 문서의 `[deny-rule:cred.<family>]` 행
411
+ (구역 + `enabled`)과 짝을 이루는 `credWriteExemptFamilies` 목록. 설정 카드는
412
+ `GET/POST /api/dsh-perm-gate/cred`로 **한 번의 update**에 한 쌍으로 씁니다.
413
+ - 읽기 면은 "파일 읽기 도구가 먼저 규칙 계층에 묻는" 방식: `decide()`가 ruleset에 먼저 묻고
414
+ **이름이 지정된 적중만** 채택; 미적중은 기존 무음 자동 통과(확인 예산 불변). 세션/조율용
415
+ 내부 도구는 절대 선행 조회하지 않습니다.
416
+ - **`readwrite`가 물러시키는 것은 정확히 한 조항**——자격증명 store 쓰기 판정. 루트·보호 경로·
417
+ `.dsh`·유출·읽기 바닥은 어떤 칸에서도 효력을 유지하며, 적용 전 카드가 이차 확인을 요구합니다.
418
+ 사용자 지정 `credentialPaths`는 계열이 없어 쓰기 면제에 참여하지 않습니다.
419
+ - 7행은 프리셋 표 **버전 1**로 출하: `presetRulesVersion` 수위로 빠진 행만 보충하고,
420
+ 사용자가 취소한 행은 부활하지 않습니다.
421
+
398
422
  ## CLI(독립 실행 dry-run)
399
423
 
400
424
  Harness 없이 규칙 파일에 대해 호출 하나를 평가할 수 있습니다:
package/README.md CHANGED
@@ -59,7 +59,7 @@ A single, self-sufficient, deterministic-first, fail-closed permission gate for
59
59
  Strictly fail-closed: a P0 decision is never overridden by a grant, a rule, the classifier, or a human.
60
60
 
61
61
  <!-- host-compat:begin — generated by scripts/sync-hosts.mjs from scripts/hosts.mjs; DO NOT EDIT -->
62
- - **Supported DSH hosts:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3` (18 rc releases across lines 0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1)
62
+ - **Supported DSH hosts:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3` `0.2.1-rc.4` (19 rc releases across lines 0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1)
63
63
  - **Runtime-verified:** `0.2.0-rc.2` — evidence in `.compat-results/`
64
64
  <!-- host-compat:end -->
65
65
 
@@ -76,6 +76,17 @@ cross-plugin version coupling.
76
76
  with recursive descent into `sh -c`/`bash -c`, pipeline detection, redirect-target
77
77
  checking, and recursive/force (`rm -rf`) recognition.
78
78
  - **Deny priority** — a matching deny rule wins over any allow rule.
79
+ - **Credential family ladder** — seven credential families (`ssh`, `cloud`, `package`, `gitcreds`,
80
+ `env`, `cli`, `db`), each selectable at `deny` / `ask` (default) / `readonly` / `readwrite`.
81
+ The rung lives in the rules document (`[deny-rule:cred.<family>]` row, section + `enabled`)
82
+ plus the paired `credWriteExemptFamilies` list, written in one settings update — no mirror,
83
+ no half-state. `readwrite` is the only rung that steps a piece of P0 aside (the credential-store
84
+ *write* screen, npm-login style) and asks for an inline confirmation; roots, protected paths,
85
+ `.dsh` and egress stay armed at every rung.
86
+ - **Protected-branch push switch** — `allowProtectedBranchPush` (off by default) keeps the P0
87
+ floor on `git push --force/--force-with-lease/--delete` to protected branches; turning it on
88
+ steps that floor aside into the seeded `git.push-force` ask (a person confirms each push) and
89
+ exempts the three flat push keywords from the blacklist.
79
90
  - **Session grants** — precise `(tool, canonical fingerprint)` grants with `TTL` + `maxUses`;
80
91
  re-running with a different target never reuses authority. Sub-agents inherit but cannot mint.
81
92
  - **Pure-function rule engine** — glob/regex compilation with a ReDoS bound, loud fail on
@@ -535,6 +546,37 @@ unrelated rule. A `0 rules loaded` note means the `rulesFile` path resolved to n
535
546
  The panel talks to `POST /api/dsh-perm-gate/dry-run`, which is **read-only by construction** — it
536
547
  has no write form at all, so testing a rule can never change it.
537
548
 
549
+ ## Credential family ladder (`deny / ask / readonly / readwrite`)
550
+
551
+ The credential floor used to be one judgement. It is now seven families × four rungs, because
552
+ "ask me before reading a `.env`" and "let the agent run `npm login` again" are different needs.
553
+
554
+ | Rung | file-tool reads / browsing | writes & deletes |
555
+ | --- | --- | --- |
556
+ | `deny` | blocked by the rule layer | blocked by P0 |
557
+ | `ask` (default) | a person confirms each one | blocked by P0 |
558
+ | `readonly` | pass silently | blocked by P0 |
559
+ | `readwrite` | pass silently | the credential-store **write** clause steps aside (npm-login style) |
560
+
561
+ - **State lives in two stores the plugin owns**: the family's `[deny-rule:cred.<family>]` row in
562
+ the rules document (section + `enabled`) and the paired `credWriteExemptFamilies` list. The
563
+ settings card writes both in ONE update through `GET/POST /api/dsh-perm-gate/cred`.
564
+ - **Read side** is enforced by a rule-layer pre-query for file-read tools: `decide()` asks the
565
+ ruleset first and only a *named* row hit routes the read; a miss keeps the silent auto-allow,
566
+ so the popup budget is unchanged. Session/coordination tools are never pre-queried.
567
+ - **`readwrite` steps exactly one clause aside** — the credential-store write screen. Root/drive
568
+ wipes, protected destructive targets, `.dsh`, egress and the read floor stay armed at every
569
+ rung, and the card asks for an inline confirmation before applying it. Custom `credentialPaths`
570
+ have no family and are never write-exempt.
571
+ - The seven rows ship as preset table **version 1**: upgrades backfill missing rows through the
572
+ `presetRulesVersion` watermark and never re-add a row you revoked.
573
+
574
+ ```
575
+ SSH (~/.ssh) deny ask [readonly] readwrite
576
+ Cloud (.aws/.gcloud/…) deny ask readonly readwrite
577
+ …
578
+ ```
579
+
538
580
  ## CLI
539
581
 
540
582
  Dry-run one call against a rules file (no harness needed):
package/README.zh.md CHANGED
@@ -56,7 +56,7 @@
56
56
  严格 fail-closed:P0 永不因 grant / 规则 / 分类器 / 人工而放行。
57
57
 
58
58
  <!-- host-compat:begin — generated by scripts/sync-hosts.mjs from scripts/hosts.mjs; DO NOT EDIT -->
59
- - **支持的 DSH 宿主:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3`(覆盖 0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 七条线共 18 个 rc)
59
+ - **支持的 DSH 宿主:** `0.1.0-rc.2` `0.1.0-rc.3` `0.1.0-rc.6` `0.1.0-rc.7` `0.1.0-rc.8` `0.1.1-rc.1` `0.1.1-rc.2` `0.1.2-rc.1` `0.1.5-rc.1` `0.1.5-rc.2` `0.1.5-rc.3` `0.1.7-rc.1` `0.1.7-rc.2` `0.2.0-rc.1` `0.2.0-rc.2` `0.2.1-rc.1` `0.2.1-rc.2` `0.2.1-rc.3` `0.2.1-rc.4`(覆盖 0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 七条线共 19 个 rc)
60
60
  - **运行时已验证:** `0.2.0-rc.2`(证据见 `.compat-results/`)
61
61
  <!-- host-compat:end -->
62
62
 
@@ -64,6 +64,8 @@
64
64
 
65
65
  - **命令白/黑名单** — 基于 **argv 分解**匹配(非裸字符串),递归下钻 `sh -c`/`bash -c`、识别管道、重定向目标、递归/强制(`rm -rf`)。
66
66
  - **deny 优先** — 命中黑名单即拒绝,胜过任何 allow。
67
+ - **凭据类型阶梯** — 七类凭据(`ssh`、`cloud`、`package`、`gitcreds`、`env`、`cli`、`db`)各自可选 `deny` / `ask`(默认)/ `readonly` / `readwrite` 四档;档位状态存于规则文档的 `[deny-rule:cred.<family>]` 行(分区 + `enabled`)与成对的 `credWriteExemptFamilies` 清单,设置卡一次 update 成对写回,无镜像、无半态。`readwrite` 是唯一会退让部分 P0 的档位(仅凭据 store 的**写**判据,npm login 类工作流)且需卡内二次确认;根盘、受保护路径、`.dsh`、外发在任何档位恒拦。
68
+ - **保护分支强推开关** — `allowProtectedBranchPush`(默认关)保留 P0 对保护分支 `git push --force/--force-with-lease/--delete` 的地板;开启后地板让位、落入预设 `git.push-force` 的逐次人工确认,并同步豁免黑名单三条扁平 push 词。
67
69
  - **会话放行** — 精确的 `(工具, 规范化 fingerprint)` grant,带 `TTL` + `maxUses`;换目标绝不复用。子代理继承但不可自授。
68
70
  - **纯函数规则引擎** — glob/regex 编译 + ReDoS 上限、坏规则 loud fail、按源内容哈希缓存。
69
71
  - **审计** — 每次决策写为 `{ignorable:true}` 事件并带 `callId`;模型可见理由与记录一致。
@@ -354,6 +356,34 @@ LLM 评定为 `safe` 且门禁自动放行的调用因此仍会弹出确认。
354
356
  不受影响。
355
357
 
356
358
 
359
+ ## 凭据类型阶梯(`deny / ask / readonly / readwrite`)
360
+
361
+ 凭据面过去是一条判据。现在是七族 × 四档——“读 `.env` 先问我”和“让 agent 再跑一次 `npm login`”
362
+ 本来就是两种需求。
363
+
364
+ | 档位 | 文件工具直读 / 浏览 | 写与删 |
365
+ | --- | --- | --- |
366
+ | `deny` | 规则层硬拦 | P0 硬拦 |
367
+ | `ask`(默认) | 逐次转人裁 | P0 硬拦 |
368
+ | `readonly` | 静默放行 | P0 硬拦 |
369
+ | `readwrite` | 静默放行 | 凭据 store **写**判据退让(npm login 类) |
370
+
371
+ - **状态就住在插件自己的两个存储里**:规则文档中该族的 `[deny-rule:cred.<family>]` 行
372
+ (分区 + `enabled`)与成对的 `credWriteExemptFamilies` 清单。设置卡经
373
+ `GET/POST /api/dsh-perm-gate/cred` **一次 update** 成对写回。
374
+ - **读面**由“文件工具先问规则层”驱动:`decide()` 先问 ruleset,且只采纳**具名命中**;
375
+ 未命中保持静默自动放行,弹窗预算不变。会话/协调类内部工具永不预询。
376
+ - **`readwrite` 只退让一条判据**——凭据 store 写屏。根盘/系统盘清扫、受保护破坏目标、
377
+ `.dsh`、外发与读地板在任何档位恒拦;应用前卡片要求二次确认。自定义 `credentialPaths`
378
+ 无族归属、永不参与写豁免。
379
+ - 七行随预设表**版本 1** 发布:升级经 `presetRulesVersion` 水位只补缺失行,你撤销过的行永不复活。
380
+
381
+ ```
382
+ SSH (~/.ssh) deny ask [readonly] readwrite
383
+ Cloud (.aws/.gcloud/…) deny ask readonly readwrite
384
+ …
385
+ ```
386
+
357
387
  ## CLI(独立 dry-run)
358
388
 
359
389
  ```sh
package/dsh.plugin.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "id": "dsh-perm-gate",
3
3
  "name": "dsh-perm-gate",
4
- "version": "5.3.3",
4
+ "version": "5.4.0",
5
5
  "description": {
6
- "en": "Deterministic-first, fail-closed permission gate for DeepSeek Harness 0.1.2+: a P0 hard-deny -> P1 precise session grant -> P2 static allow/deny rule chain -> P3 optional LLM classifier -> P4 ask pipeline over the tools/pre-execute waterfall, with a standalone CLI dry-run evaluator and an auditable decision log. It only vetoes with deny/ask and always delegates otherwise, and unknown or malformed rules fail loud instead of silently standing the gate down.",
7
- "zh": "面向 DeepSeek Harness 0.1.2+ 的确定性优先、失败即拒的权限闸门:在 tools/pre-execute 瀑布上串起 P0 硬拒绝 → P1 精确会话授权 → P2 静态 allow/deny 规则链 → P3 可选 LLM 语义分类 → P4 ask,并附带独立 CLI 干跑评估器与可审计的决策日志。只以 deny/ask 否决、其余一律放行,规则未知或非法时直接报错,绝不静默失效。"
6
+ "en": "Deterministic-first, fail-closed permission gate for DeepSeek Harness 0.1.2+: a P0 hard-deny -> P1 precise session grant -> P2 static allow/deny rule chain -> P3 optional LLM classifier -> P4 ask pipeline over the tools/pre-execute waterfall, with a standalone CLI dry-run evaluator and an auditable decision log. Credential handling is a seven-family ladder (ssh/cloud/package/gitcreds/env/cli/db) with deny/ask/readonly/readwrite rungs kept in the rules document plus a paired write-exemption list; a protected-branch push switch keeps the P0 floor by default. It only vetoes with deny/ask and always delegates otherwise, and unknown or malformed rules fail loud instead of silently standing the gate down.",
7
+ "zh": "面向 DeepSeek Harness 0.1.2+ 的确定性优先、失败即拒的权限闸门:在 tools/pre-execute 瀑布上串起 P0 硬拒绝 → P1 精确会话授权 → P2 静态 allow/deny 规则链 → P3 可选 LLM 语义分类 → P4 ask,并附带独立 CLI 干跑评估器与可审计的决策日志。凭据处理为七族阶梯(ssh/cloud/package/gitcreds/env/cli/db)× deny/ask/readonly/readwrite 四档,档位存规则文档 + 成对写豁免清单;保护分支强推开关默认保留 P0 地板。只以 deny/ask 否决、其余一律放行,规则未知或非法时直接报错,绝不静默失效。"
8
8
  },
9
9
  "homepage": "https://github.com/drscrewdriver/dsh-perm-gate",
10
10
  "repository": {
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "license": "MIT",
15
15
  "engines": {
16
- "dsh": "0.1.0-rc.2 || 0.1.0-rc.3 || 0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1-rc.3"
16
+ "dsh": "0.1.0-rc.2 || 0.1.0-rc.3 || 0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1-rc.3 || 0.2.1-rc.4"
17
17
  },
18
18
  "components": {
19
19
  "host": "lib/index.js",