@furongjun1999/dsh-memory 0.5.0 → 0.6.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/README.md +572 -465
- package/docs/README.md +1 -0
- package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225v2_/345/217/202/350/200/203dsh-TUI_v1.0.md +248 -0
- package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225/346/225/210/346/236/234/351/252/214/350/257/201_v1.0.md +209 -0
- package/docs/eval/DSH/347/253/257/347/274/272/351/231/267/344/270/223/351/241/271_v1.0.md +254 -0
- package/docs/eval/P1b2_/350/257/273/351/235/242/344/273/243/351/231/205/344/277/256/345/244/215_v1.0.md +124 -0
- package/docs/eval/bench_lingshu_self/bench_self.py +140 -0
- package/docs/eval/bench_lingshu_self/self_bench_result.json +404 -0
- package/docs/eval/bench_lingshu_self//347/201/265/346/236/242/350/207/252/345/272/223/347/253/257/345/210/260/347/253/257/346/243/200/347/264/242/345/256/236/346/265/213_v1.0.md +38 -0
- package/docs/eval//344/270/215/345/217/257/351/235/240/346/200/247/350/220/275/345/234/260_P0_v1.0.md +185 -0
- package/docs/eval//345/217/221/345/270/20306_/344/270/200/351/224/256/351/205/215/347/275/256/344/270/216DSH0172_v1.0.md +171 -0
- package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +422 -0
- package/docs/eval//347/253/257/345/210/260/347/253/257LoCoMoQA/345/220/214/345/217/243/345/276/204/345/257/271/347/205/247_v1.0.md +100 -0
- package/docs/eval//347/253/257/345/210/260/347/253/257/345/271/262/346/211/260/346/261/240/350/257/204/346/265/213_/347/241/256/345/256/232/346/200/247/350/243/201/345/206/263vsLLM_judge_v1.1.md +197 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v1.md +156 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v10.md +210 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v11.md +227 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v12.md +203 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v13.md +233 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v14.md +191 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v15.md +213 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v16.md +214 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v17.md +199 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v18.md +183 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v19.md +207 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v2.md +156 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v3.md +152 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v4.md +128 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v5.md +114 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v6.md +192 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v7.md +187 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v8.md +207 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v9.md +203 -0
- package/docs/hive//345/256/211/345/205/250/345/256/241/350/256/241/345/256/236/351/224/232_v0.1.md +202 -0
- package/docs/hive//350/234/202/345/267/242/345/217/214/345/256/236/344/276/213/344/272/222/351/252/214_/350/256/276/350/256/241/345/256/232/347/250/277.md +19 -3
- package/docs/images/lingshu-moonlight-covenant-poster-preview.jpg +0 -0
- package/docs/images/lingshu-moonlight-covenant-poster.png +0 -0
- package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
- package/docs/theory//344/270/215/345/217/257/351/235/240/345/256/232/347/220/206/344/270/216/345/244/261/346/225/210/344/274/230/345/205/210/346/241/206/346/236/266_v0.3.md +365 -0
- package/docs//344/270/215/345/217/257/351/235/240/346/200/247/347/220/206/350/256/272_v0.1.md +343 -0
- package/dsh/cordis-patch-profile-web.example.yml +35 -0
- package/lib/bridge.d.ts +9 -0
- package/lib/bridge.js +35 -0
- package/lib/cli.d.ts +3 -0
- package/lib/cli.js +66 -0
- package/lib/index.js +7 -1
- package/lib/init.d.ts +88 -0
- package/lib/init.js +287 -0
- package/lib/lib/roleplay_web.js +530 -443
- package/lib/lib/token_store.d.ts +7 -1
- package/lib/lib/token_store.js +12 -3
- package/md_cg/audit.py +12 -1
- package/md_cg/backfill.py +16 -15
- package/md_cg/backfill_bucket_zh.py +35 -0
- package/md_cg/bench_e2e_judge.py +532 -0
- package/md_cg/bench_e2e_locomo_qa.py +368 -0
- package/md_cg/bench_e2e_qa.py +256 -0
- package/md_cg/branches.py +18 -2
- package/md_cg/ccgc.py +3 -2
- package/md_cg/chain.py +19 -4
- package/md_cg/consolidate.py +7 -6
- package/md_cg/crosscheck.py +4 -3
- package/md_cg/crypto.py +439 -437
- package/md_cg/datapath.py +395 -335
- package/md_cg/evidence.py +8 -3
- package/md_cg/export.py +3 -1
- package/md_cg/forgetting.py +2 -2
- package/md_cg/fsutil.py +48 -0
- package/md_cg/hotcache.py +255 -238
- package/md_cg/interop.py +161 -22
- package/md_cg/judgment_manifest.py +177 -0
- package/md_cg/links.py +655 -622
- package/md_cg/mcp_server.py +282 -31
- package/md_cg/mdcg.py +702 -126
- package/md_cg/mdcos.py +454 -68
- package/md_cg/mreview/govern.py +5 -4
- package/md_cg/postings.py +4 -2
- package/md_cg/readcache.py +76 -18
- package/md_cg/reconcile.py +228 -0
- package/md_cg/review_cli.py +215 -0
- package/md_cg/routing.py +28 -0
- package/md_cg/run_tests.py +211 -0
- package/md_cg/scrub.py +862 -852
- package/md_cg/security.py +385 -275
- package/md_cg/selfreport.py +3 -2
- package/md_cg/signer.py +565 -562
- package/md_cg/sources.py +3 -2
- package/md_cg/stg.py +6 -0
- package/md_cg/sustain.py +1168 -1138
- package/md_cg/test_access_hints.py +147 -0
- package/md_cg/test_branch_discard_tombstone.py +136 -0
- package/md_cg/test_branches.py +259 -249
- package/md_cg/test_chain_read_isolate.py +168 -0
- package/md_cg/test_datapath_device_name.py +203 -0
- package/md_cg/test_emit_negtail_cache.py +156 -0
- package/md_cg/test_en_pipeline.py +186 -166
- package/md_cg/test_govern_directread.py +421 -0
- package/md_cg/test_i32_hotcache_env_key.py +218 -0
- package/md_cg/test_identity_attribution.py +228 -147
- package/md_cg/test_index_crossprocess_reload.py +301 -0
- package/md_cg/test_index_durability.py +238 -224
- package/md_cg/test_interop.py +4 -2
- package/md_cg/test_interop_judgment.py +228 -0
- package/md_cg/test_issue39_utf8_stdio.py +273 -0
- package/md_cg/test_links_concurrent_write.py +188 -0
- package/md_cg/test_merge_upsert.py +168 -0
- package/md_cg/test_n123_derive_expiry_chain.py +205 -0
- package/md_cg/test_n130_verify_falsified_protect.py +185 -0
- package/md_cg/test_n131_merge_gate.py +205 -0
- package/md_cg/test_none_id_write_guard.py +165 -0
- package/md_cg/test_p1x_ref_root.py +160 -0
- package/md_cg/test_p27_docindex.py +774 -765
- package/md_cg/test_p2_mcp.py +3 -0
- package/md_cg/test_p32_backfill.py +304 -298
- package/md_cg/test_p39_verify_flow.py +90 -50
- package/md_cg/test_p47_session_view.py +60 -25
- package/md_cg/test_propose_tail_index.py +157 -0
- package/md_cg/test_read_scope_b27.py +277 -0
- package/md_cg/test_readcache_default_on.py +168 -0
- package/md_cg/test_readcache_precise_inval.py +270 -0
- package/md_cg/test_readcache_prodpath.py +55 -7
- package/md_cg/test_reconcile_v0.py +294 -0
- package/md_cg/test_retr_s1.py +6 -2
- package/md_cg/test_retr_s1b.py +67 -0
- package/md_cg/test_retr_s7.py +8 -0
- package/md_cg/test_retr_s9_entity_ctx.py +181 -175
- package/md_cg/test_retr_score_once.py +208 -0
- package/md_cg/test_review_cli_attribution.py +177 -0
- package/md_cg/test_review_cli_visibility.py +235 -0
- package/md_cg/test_review_onepass.py +170 -0
- package/md_cg/test_rrf_graph_seed_cache.py +154 -0
- package/md_cg/test_security_audit.py +155 -0
- package/md_cg/test_security_audit_b26.py +161 -0
- package/md_cg/test_security_audit_v21.py +250 -0
- package/md_cg/test_semantic_canonical.py +255 -241
- package/md_cg/test_session_isolation.py +168 -0
- package/md_cg/test_snapshot_autoclose.py +187 -0
- package/md_cg/test_tail_watermark_race.py +208 -0
- package/md_cg/test_tenant_env_override_warn.py +139 -0
- package/md_cg/test_tenant_registry_corrupt_warn.py +151 -0
- package/md_cg/test_v14_fixes.py +415 -397
- package/md_cg/test_verify_dirty_reconcile.py +157 -0
- package/md_cg/theory.py +276 -273
- package/md_cg/tokens.py +734 -677
- package/md_cg/units.py +3 -2
- package/md_cg/vision_evidence.py +4 -3
- package/md_cg/whitebox_kb/wisdom/code_solidified.json +6195 -6195
- package/md_cg/whitebox_kb/wisdom/multilang_ir.py +128 -124
- package/md_cg/writepipe.py +554 -550
- package/package.json +11 -2
- package/src/bridge.ts +434 -401
- package/src/cli.ts +65 -0
- package/src/index.ts +526 -518
- package/src/init.ts +347 -0
- package/src/lib/roleplay_web.ts +1019 -932
- package/src/lib/token_store.ts +202 -192
package/src/lib/token_store.ts
CHANGED
|
@@ -1,192 +1,202 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* token_store.ts —— 灵枢写入凭据的**密钥环**(默认 `~/.mdcg/token`)
|
|
3
|
-
*
|
|
4
|
-
* 要解决的问题(首启静默失效)
|
|
5
|
-
* ------------------------------------------------
|
|
6
|
-
* 灵枢大脑(md_cg)用令牌做身份与权限判定:**无令牌即降级只读 guest**,
|
|
7
|
-
* 此时自动记忆 / 对话转录 / 角色落图**全部不落盘**(`_build_principal` 的
|
|
8
|
-
* guest 分支,且启动会告警)。对「不知道需要签发令牌」的用户,这表现为
|
|
9
|
-
* **「装好了插件,但记忆永远是空的」**——一种没有任何报错的失效形态。
|
|
10
|
-
*
|
|
11
|
-
* 本模块把这条路径补齐,解析顺序(高 → 低):
|
|
12
|
-
* ① `config.env.MDCG_TOKEN` —— 显式配置,原样尊重,**完全不介入**;
|
|
13
|
-
* ② 进程 env `MDCG_TOKEN` —— 同上;
|
|
14
|
-
* ③ 密钥环 `~/.mdcg/token`(0600)—— 已签发过则复用;
|
|
15
|
-
* ④ 都没有 → **首启自动签发**一枚 designer 令牌并写入密钥环。
|
|
16
|
-
*
|
|
17
|
-
* 为什么密钥环可以自动签发(安全论证)
|
|
18
|
-
* ------------------------------------------------
|
|
19
|
-
* 能读到该文件的进程,本就以该用户身份运行,也就本就能读写该用户的全部文件
|
|
20
|
-
* ——自动签发**不降低实际安全强度**。真正需要显式管理令牌的场景(多用户机 /
|
|
21
|
-
* 想要权职分离 / 审计要求)用 `MDCG_AUTO_ISSUE=0` 关闭,改走手工签发。
|
|
22
|
-
*
|
|
23
|
-
* 与 `md_cg/tokens.py` 的对应
|
|
24
|
-
* ------------------------------------------------
|
|
25
|
-
* 密钥环与 `tokens.py` 的 `~/.mdcg/_tokens.json`(令牌记录)同目录,但**职责不同**:
|
|
26
|
-
* 密钥环存**明文令牌**(给本机客户端用),`_tokens.json` 存**哈希与元数据**(校验用)。
|
|
27
|
-
* 二者格式不做任何修改——本模块只是 `python -m md_cg.tokens issue` 的一层封装。
|
|
28
|
-
*/
|
|
29
|
-
import { spawnSync } from 'node:child_process'
|
|
30
|
-
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
31
|
-
import { homedir } from 'node:os'
|
|
32
|
-
import { dirname, join } from 'node:path'
|
|
33
|
-
import { pythonPathValue, runRoot } from './datapath.js'
|
|
34
|
-
|
|
35
|
-
/** 凭据来源(用于启动日志与故障定位)。 */
|
|
36
|
-
export type TokenSource =
|
|
37
|
-
| 'config' // config.env.MDCG_TOKEN(显式配置,原样尊重)
|
|
38
|
-
| 'process-env' // 插件进程 env 的 MDCG_TOKEN
|
|
39
|
-
| 'keyring' // 密钥环 ~/.mdcg/token
|
|
40
|
-
| 'issued' // 首启自动签发并写入密钥环
|
|
41
|
-
| 'disabled' // 显式关闭自动签发,且无既有凭据
|
|
42
|
-
| 'none' // 签发不可用(如 Python 不可执行),md_cg 侧将降级只读 guest
|
|
43
|
-
|
|
44
|
-
export interface TokenResolution {
|
|
45
|
-
/** 明文令牌;未解析到时为 undefined(md_cg 侧降级只读 guest)。 */
|
|
46
|
-
token?: string
|
|
47
|
-
source: TokenSource
|
|
48
|
-
/** 人类可读的补充说明(写启动日志用,含关闭 / 吊销方式)。 */
|
|
49
|
-
note?: string
|
|
50
|
-
/** 密钥环路径(诊断用)。 */
|
|
51
|
-
keyringPath: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface ResolveTokenOptions {
|
|
55
|
-
/** Python 可执行文件(与 md_cg 子进程同源,保证 import 环境一致)。 */
|
|
56
|
-
python: string
|
|
57
|
-
/** 显式配置的令牌(config.env.MDCG_TOKEN)。 */
|
|
58
|
-
configured?: string
|
|
59
|
-
/** 签发主体标识(写入令牌记录,默认 dsh-memory)。 */
|
|
60
|
-
actor?: string
|
|
61
|
-
/** 签发角色(默认 designer = 设计者载体;其它角色见 tokens.ROLE_SPECS)。 */
|
|
62
|
-
role?: string
|
|
63
|
-
/** 签发密级上限(默认 internal,与 md_cg 的 DEFAULT_SENSITIVITY 对齐)。 */
|
|
64
|
-
clearance?: string
|
|
65
|
-
/** 是否允许首启自动签发(默认 true;legacy env 认证场景应传 false)。 */
|
|
66
|
-
autoIssue?: boolean
|
|
67
|
-
/** 密钥环路径覆盖(默认 ~/.mdcg/token)。 */
|
|
68
|
-
keyringPath?: string
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
1
|
+
/**
|
|
2
|
+
* token_store.ts —— 灵枢写入凭据的**密钥环**(默认 `~/.mdcg/token`)
|
|
3
|
+
*
|
|
4
|
+
* 要解决的问题(首启静默失效)
|
|
5
|
+
* ------------------------------------------------
|
|
6
|
+
* 灵枢大脑(md_cg)用令牌做身份与权限判定:**无令牌即降级只读 guest**,
|
|
7
|
+
* 此时自动记忆 / 对话转录 / 角色落图**全部不落盘**(`_build_principal` 的
|
|
8
|
+
* guest 分支,且启动会告警)。对「不知道需要签发令牌」的用户,这表现为
|
|
9
|
+
* **「装好了插件,但记忆永远是空的」**——一种没有任何报错的失效形态。
|
|
10
|
+
*
|
|
11
|
+
* 本模块把这条路径补齐,解析顺序(高 → 低):
|
|
12
|
+
* ① `config.env.MDCG_TOKEN` —— 显式配置,原样尊重,**完全不介入**;
|
|
13
|
+
* ② 进程 env `MDCG_TOKEN` —— 同上;
|
|
14
|
+
* ③ 密钥环 `~/.mdcg/token`(0600)—— 已签发过则复用;
|
|
15
|
+
* ④ 都没有 → **首启自动签发**一枚 designer 令牌并写入密钥环。
|
|
16
|
+
*
|
|
17
|
+
* 为什么密钥环可以自动签发(安全论证)
|
|
18
|
+
* ------------------------------------------------
|
|
19
|
+
* 能读到该文件的进程,本就以该用户身份运行,也就本就能读写该用户的全部文件
|
|
20
|
+
* ——自动签发**不降低实际安全强度**。真正需要显式管理令牌的场景(多用户机 /
|
|
21
|
+
* 想要权职分离 / 审计要求)用 `MDCG_AUTO_ISSUE=0` 关闭,改走手工签发。
|
|
22
|
+
*
|
|
23
|
+
* 与 `md_cg/tokens.py` 的对应
|
|
24
|
+
* ------------------------------------------------
|
|
25
|
+
* 密钥环与 `tokens.py` 的 `~/.mdcg/_tokens.json`(令牌记录)同目录,但**职责不同**:
|
|
26
|
+
* 密钥环存**明文令牌**(给本机客户端用),`_tokens.json` 存**哈希与元数据**(校验用)。
|
|
27
|
+
* 二者格式不做任何修改——本模块只是 `python -m md_cg.tokens issue` 的一层封装。
|
|
28
|
+
*/
|
|
29
|
+
import { spawnSync } from 'node:child_process'
|
|
30
|
+
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
31
|
+
import { homedir } from 'node:os'
|
|
32
|
+
import { dirname, join, resolve } from 'node:path'
|
|
33
|
+
import { pythonPathValue, runRoot } from './datapath.js'
|
|
34
|
+
|
|
35
|
+
/** 凭据来源(用于启动日志与故障定位)。 */
|
|
36
|
+
export type TokenSource =
|
|
37
|
+
| 'config' // config.env.MDCG_TOKEN(显式配置,原样尊重)
|
|
38
|
+
| 'process-env' // 插件进程 env 的 MDCG_TOKEN
|
|
39
|
+
| 'keyring' // 密钥环 ~/.mdcg/token
|
|
40
|
+
| 'issued' // 首启自动签发并写入密钥环
|
|
41
|
+
| 'disabled' // 显式关闭自动签发,且无既有凭据
|
|
42
|
+
| 'none' // 签发不可用(如 Python 不可执行),md_cg 侧将降级只读 guest
|
|
43
|
+
|
|
44
|
+
export interface TokenResolution {
|
|
45
|
+
/** 明文令牌;未解析到时为 undefined(md_cg 侧降级只读 guest)。 */
|
|
46
|
+
token?: string
|
|
47
|
+
source: TokenSource
|
|
48
|
+
/** 人类可读的补充说明(写启动日志用,含关闭 / 吊销方式)。 */
|
|
49
|
+
note?: string
|
|
50
|
+
/** 密钥环路径(诊断用)。 */
|
|
51
|
+
keyringPath: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ResolveTokenOptions {
|
|
55
|
+
/** Python 可执行文件(与 md_cg 子进程同源,保证 import 环境一致)。 */
|
|
56
|
+
python: string
|
|
57
|
+
/** 显式配置的令牌(config.env.MDCG_TOKEN)。 */
|
|
58
|
+
configured?: string
|
|
59
|
+
/** 签发主体标识(写入令牌记录,默认 dsh-memory)。 */
|
|
60
|
+
actor?: string
|
|
61
|
+
/** 签发角色(默认 designer = 设计者载体;其它角色见 tokens.ROLE_SPECS)。 */
|
|
62
|
+
role?: string
|
|
63
|
+
/** 签发密级上限(默认 internal,与 md_cg 的 DEFAULT_SENSITIVITY 对齐)。 */
|
|
64
|
+
clearance?: string
|
|
65
|
+
/** 是否允许首启自动签发(默认 true;legacy env 认证场景应传 false)。 */
|
|
66
|
+
autoIssue?: boolean
|
|
67
|
+
/** 密钥环路径覆盖(默认 ~/.mdcg/token)。 */
|
|
68
|
+
keyringPath?: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** 辅助存储根(密钥/令牌/信任/理论/心跳):与 md_cg 的 `datapath.aux_root()` 同口径。
|
|
72
|
+
*
|
|
73
|
+
* 默认 `~/.mdcg`(历史值,**逐字保留**——改默认会让存量密钥/令牌失联);
|
|
74
|
+
* `MDCG_AUX_ROOT` 可把它们整体搬走(沙箱/多用户/与记忆真源同处的场景)。
|
|
75
|
+
* 与 `config.mdcg.root`(记忆真源)有意分离:身份与信任不随认知图迁移。 */
|
|
76
|
+
export function auxRoot(): string {
|
|
77
|
+
const env = (process.env.MDCG_AUX_ROOT ?? '').trim()
|
|
78
|
+
return env ? resolve(env) : join(homedir(), '.mdcg')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** 默认密钥环路径:与 md_cg 的 `_tokens.json` 同目录(aux 根下,见 auxRoot())。 */
|
|
82
|
+
export function defaultKeyringPath(): string {
|
|
83
|
+
return join(auxRoot(), 'token')
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** 读取密钥环;不存在 / 不可读 / 空文件一律返回 undefined(不抛异常)。 */
|
|
87
|
+
function readKeyring(path: string): string | undefined {
|
|
88
|
+
try {
|
|
89
|
+
const t = readFileSync(path, 'utf-8').trim()
|
|
90
|
+
return t || undefined
|
|
91
|
+
} catch {
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** 写入密钥环并尽力收紧权限。 */
|
|
97
|
+
function writeKeyring(path: string, token: string): void {
|
|
98
|
+
mkdirSync(dirname(path), { recursive: true })
|
|
99
|
+
writeFileSync(path, token + '\n', { encoding: 'utf-8', mode: 0o600 })
|
|
100
|
+
try {
|
|
101
|
+
// Windows 上 chmod 仅能置只读位(真实保护来自用户目录 ACL),
|
|
102
|
+
// 与 md_cg tokens._save 同策略:不可设则忽略,不因此中断签发。
|
|
103
|
+
chmodSync(path, 0o600)
|
|
104
|
+
} catch { /* 平台不支持则忽略 */ }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface IssueOutcome {
|
|
108
|
+
token?: string
|
|
109
|
+
tokenId?: string
|
|
110
|
+
error?: string
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** 调 `python -m md_cg.tokens issue` 签一枚令牌(同步,仅首启一次)。 */
|
|
114
|
+
function issueToken(python: string, role: string, actor: string, clearance: string): IssueOutcome {
|
|
115
|
+
let r
|
|
116
|
+
try {
|
|
117
|
+
r = spawnSync(
|
|
118
|
+
python,
|
|
119
|
+
['-m', 'md_cg.tokens', 'issue',
|
|
120
|
+
'--role', role, '--actor', actor, '--clearance', clearance],
|
|
121
|
+
{
|
|
122
|
+
encoding: 'utf-8',
|
|
123
|
+
windowsHide: true,
|
|
124
|
+
timeout: 15_000,
|
|
125
|
+
// 与工作纪律第 15 条同源:显式 UTF-8 + PYTHONUTF8,规避 Windows GBK 解码异常。
|
|
126
|
+
// 模块解析靠 PYTHONPATH 锚定随包 md_cg(不依赖 cwd);cwd 取包外目录,
|
|
127
|
+
// 否则 pnpm 更新本插件时 rmdir 包目录必报 ERR_PNPM_EBUSY。见 datapath.runRoot()。
|
|
128
|
+
cwd: runRoot(),
|
|
129
|
+
env: {
|
|
130
|
+
...process.env,
|
|
131
|
+
PYTHONPATH: pythonPathValue(),
|
|
132
|
+
PYTHONUTF8: '1',
|
|
133
|
+
PYTHONIOENCODING: 'utf-8',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
} catch (e) {
|
|
138
|
+
return { error: `无法执行 ${python}:${e instanceof Error ? e.message : String(e)}` }
|
|
139
|
+
}
|
|
140
|
+
if (r.error) return { error: `无法执行 ${python}:${r.error.message}` }
|
|
141
|
+
if (r.status !== 0) {
|
|
142
|
+
const detail = (r.stderr || r.stdout || '').trim().replace(/\s+/g, ' ').slice(0, 200)
|
|
143
|
+
return { error: `md_cg.tokens issue 退出码 ${r.status}${detail ? `:${detail}` : ''}` }
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const out = JSON.parse(r.stdout || '{}') as { token?: string; token_id?: string }
|
|
147
|
+
if (!out.token) return { error: '签发输出缺少 token 字段' }
|
|
148
|
+
return { token: out.token, tokenId: out.token_id }
|
|
149
|
+
} catch (e) {
|
|
150
|
+
return { error: `签发输出不是合法 JSON:${e instanceof Error ? e.message : String(e)}` }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** `MDCG_AUTO_ISSUE` 是否显式关闭(0/false/no/off,忽略大小写)。 */
|
|
155
|
+
function autoIssueDisabledByEnv(): boolean {
|
|
156
|
+
const v = (process.env.MDCG_AUTO_ISSUE ?? '').trim().toLowerCase()
|
|
157
|
+
return v === '0' || v === 'false' || v === 'no' || v === 'off'
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 解析写入凭据:显式配置 → 进程 env → 密钥环 → 首启自动签发。
|
|
162
|
+
*
|
|
163
|
+
* 纯函数式(无模块级缓存):一次插件激活只调用一次,且返回值须与当下磁盘
|
|
164
|
+
* 状态一致,缓存反而会让「用户刚删了密钥环」的修复动作不生效。
|
|
165
|
+
*/
|
|
166
|
+
export function resolveToken(opts: ResolveTokenOptions): TokenResolution {
|
|
167
|
+
const keyringPath = opts.keyringPath ?? defaultKeyringPath()
|
|
168
|
+
|
|
169
|
+
const configured = (opts.configured ?? '').trim()
|
|
170
|
+
if (configured) return { token: configured, source: 'config', keyringPath }
|
|
171
|
+
|
|
172
|
+
const fromEnv = (process.env.MDCG_TOKEN ?? '').trim()
|
|
173
|
+
if (fromEnv) return { token: fromEnv, source: 'process-env', keyringPath }
|
|
174
|
+
|
|
175
|
+
const fromRing = readKeyring(keyringPath)
|
|
176
|
+
if (fromRing) return { token: fromRing, source: 'keyring', keyringPath }
|
|
177
|
+
|
|
178
|
+
if (opts.autoIssue === false) {
|
|
179
|
+
return { source: 'disabled', keyringPath, note: '本场景未启用自动签发(autoIssue=false)' }
|
|
180
|
+
}
|
|
181
|
+
if (autoIssueDisabledByEnv()) {
|
|
182
|
+
return { source: 'disabled', keyringPath, note: 'MDCG_AUTO_ISSUE 已关闭自动签发' }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const role = opts.role ?? 'designer'
|
|
186
|
+
const actor = opts.actor ?? 'dsh-memory'
|
|
187
|
+
const clearance = opts.clearance ?? 'internal'
|
|
188
|
+
const r = issueToken(opts.python, role, actor, clearance)
|
|
189
|
+
if (!r.token) {
|
|
190
|
+
return { source: 'none', keyringPath, note: r.error }
|
|
191
|
+
}
|
|
192
|
+
writeKeyring(keyringPath, r.token)
|
|
193
|
+
return {
|
|
194
|
+
token: r.token,
|
|
195
|
+
source: 'issued',
|
|
196
|
+
keyringPath,
|
|
197
|
+
note: `已自动签发认知图写入凭据(role=${role}, actor=${actor}, `
|
|
198
|
+
+ `clearance=${clearance}, token_id=${r.tokenId}),明文存于 ${keyringPath}。`
|
|
199
|
+
+ '关闭自动签发:设 MDCG_AUTO_ISSUE=0;'
|
|
200
|
+
+ `吊销:python -m md_cg.tokens revoke --token-id ${r.tokenId}。`,
|
|
201
|
+
}
|
|
202
|
+
}
|