nx-sk 0.3.4 → 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/CHANGELOG.md +47 -1
- package/README.md +62 -4
- package/assets/nx-sk/SKILL.md +31 -2
- package/assets/nx-sk/references/00-design.md +4 -3
- package/assets/nx-sk/references/10-sections-entries.md +10 -2
- package/assets/nx-sk/references/30-export-backup.md +16 -0
- package/assets/nx-sk/references/40-files.md +104 -0
- package/package.json +1 -1
- package/src/core/attachments.js +378 -0
- package/src/core/fields.js +58 -2
- package/src/core/paths.js +5 -0
- package/src/core/render.js +1 -0
- package/src/core/store.js +3 -0
- package/src/modules/backup/index.js +41 -0
- package/src/modules/backup/service.js +283 -0
- package/src/modules/backup/view.jsx +145 -0
- package/src/modules/entries/service.js +35 -2
- package/src/modules/files/index.js +114 -0
- package/src/modules/files/service.js +276 -0
- package/src/modules/files/view.jsx +342 -0
- package/src/modules/sections/index.js +10 -0
- package/src/modules/sections/service.js +55 -2
- package/src/modules/sections/view.jsx +30 -2
- package/src/runtime/api.js +10 -1
- package/src/runtime/registry.js +3 -1
- package/src/web/frontend/App.jsx +36 -18
- package/src/web/frontend/api/files.js +28 -0
- package/src/web/frontend/components/fieldEditor.jsx +72 -1
- package/src/web/frontend/index.html +4 -0
- package/src/web/frontend/public/favicon-16.png +0 -0
- package/src/web/frontend/public/favicon-32.png +0 -0
- package/src/web/frontend/public/favicon-48.png +0 -0
- package/src/web/frontend/public/favicon.ico +0 -0
- package/src/web/frontend/public/logo-rounded.png +0 -0
- package/src/web/frontend/public/logo.png +0 -0
- package/src/web/frontend/registry.js +2 -0
- package/src/web/frontend/styles.css +104 -6
- package/src/web/public/assets/files-BNh48qeo.js +1 -0
- package/src/web/public/assets/{index-BnVuH1lC.js → index-B7CtqgoG.js} +10 -9
- package/src/web/public/assets/index-DLtjhflt.css +1 -0
- package/src/web/public/assets/view-1kwWQYbz.js +7 -0
- package/src/web/public/assets/view-BAYyPWdU.js +1 -0
- package/src/web/public/assets/{view-BvyRxTgX.js → view-BIdVqIGe.js} +1 -1
- package/src/web/public/assets/{view-rvADq3vX.js → view-Bu70Q6GO.js} +1 -1
- package/src/web/public/assets/view-D5LfHr7W.js +1 -0
- package/src/web/public/assets/view-DXqI-4_F.js +3 -0
- package/src/web/public/favicon-16.png +0 -0
- package/src/web/public/favicon-32.png +0 -0
- package/src/web/public/favicon-48.png +0 -0
- package/src/web/public/favicon.ico +0 -0
- package/src/web/public/index.html +6 -2
- package/src/web/public/logo-rounded.png +0 -0
- package/src/web/public/logo.png +0 -0
- package/assets/nx-sk/references/40-extend.md +0 -75
- package/src/web/public/assets/index-CwF5hM2v.css +0 -1
- package/src/web/public/assets/view-CDje4hqZ.js +0 -1
- package/src/web/public/assets/view-DsyplQBh.js +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
本文件格式参考 [Keep a Changelog](https://keepachangelog.com/),中文正文。
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [0.6.0] - 2026-10-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **agent 手册补齐附件域**:随包分发的 `assets/nx-sk/` 新增 `references/40-files.md`(附件库:导入默认移动、`file` 字段值 = 附件 id 的链接、可逆还原、附件中心为什么由栏目驱动、看不到上传字段怎么办),并在 `SKILL.md` 与 `README.md` 的 ref 路由表登记;同步修订 `10-sections-entries`(求职模板 79 字段 / 10 分组、字段类型表补 `file`、栏目命令补 `sync`)与 `00-design`(core 清单补 `attachments`、错误案例补附件组织方式的取舍)。
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **顶栏层级重排**:品牌升为标题(15px / 700),副标题与版本号降为从属元信息并整体右移,超长存储路径自动省略(完整值在 `title`);身份栏与导航栏拉开 padding 差异,并在「内容栏目」与「系统工具」之间加一条分组细线;计数降为等宽小字。
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **默认视图被顶成「栏目」**:`/api/bootstrap` 返回前用静态视图兜底并写回 ui 状态,导致默认视图与头部高亮错位(首屏还会覆盖 `#/job` 这类深链);改用 `booted` 门控——未拿到 bootstrap 就显示「正在装载…」,不兜底、不写入。顺带清理已无定义的 `header.top .meta` 样式,残留处改用已有的 `.muted`。
|
|
18
|
+
- **CI 跨平台单测**:附件单测里 `join('\\')` 拼路径只在 Windows 成立,ubuntu 上 ENOENT——0.5.0 / 0.5.1 因此都没发出去;改为跨平台 `join(...rel.split('/'))`。
|
|
19
|
+
|
|
20
|
+
## [0.5.1] - 2026-10-12
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **加密备份跨机器恢复后密钥栏目无法解开**(原始事故:用户将 A 机 `backup export --password` 出的 `.nxskbak` 文件拷贝到 B 机再 `backup import` 后,B 机 `key get` 报「密钥或密文与写入时不一致」)。原因:原备份包只对整包加密,**包内密文字段仍用 A 机的 `~/.vaultkey` / `NX_SK_PASSPHRASE` 派生 kid**——B 机的本地密钥与其不一致,GCM 校验失败。修法:导出时给每条密文追加一个口令派生的 `reWrapped` 副本;导入时解开 `reWrapped` 拿明文、用 B 机本机 vaultKey 重新加密后写回主字段、`reWrapped` 丢弃——B 机后续 `key get` 走的就是 B 机的本机密钥。备份包不再依赖导出机的本地密钥状态;同时给 smoke 加了「换 vaultkey 后口令导入仍能解出明文」的端到端断言。
|
|
25
|
+
|
|
26
|
+
## [0.5.0] - 2026-10-12
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **统一附件管理(本地文件存储 + 可逆移动)**:新增「附件」模块(CLI `file list|get|add|update|remove|content|restore|open`,Web「附件」工作台,HTTP `/api/files` 一组路由)。
|
|
31
|
+
- 所有附件原件统一落在 `~/nx-sk/files/`,元数据随 `store.json` 落台账;按 sha256 自动去重——同一份原件只存一次,可被多条条目共享。
|
|
32
|
+
- 本机路径导入**默认移动**(提交附件 = 把原件搬进 nx-sk 目录),`--copy` 才保留原件;Web 拖拽 / 选择上传为复制语义(浏览器无法删除任意路径文件)。
|
|
33
|
+
- **可逆**:`file restore` 把附件移回原始位置(或 `--to` 指定目录)并撤销台账;`--copy` 只导出副本、库中保留。
|
|
34
|
+
- 每个附件给出物理路径与浏览器链接(`/api/files/:id/content`,支持内联预览与 `?download=1` 下载,正确的 Content-Type 与 UTF-8 文件名)。
|
|
35
|
+
- 新增 `file` 字段类型,**值 = 附件 id**:id 全局唯一 → 各条目的附件空间天然隔离;去重后同一原件又可被多条条目引用。求职模板新增「附件资料」组:**简历附件 / 头像图片 / 成绩单 / 证书扫描件(不必填)**。
|
|
36
|
+
- **上传 / 选择发生在栏目条目里**:条目表单的 file 字段可直接「上传文件」或从附件库选一个,保存即建立链接;字段里显示附件名 / 缩略图 / 物理路径 / 下载 / 清除。
|
|
37
|
+
- **「附件」中心由栏目驱动、不预定义**:不做指派,也没有预设分类或槽位;筛选片按「哪些栏目在引用附件」动态生成(外加「未引用」),每张卡片显示被哪个栏目 / 条目 / 字段引用(`fileReferences` 反查)。CLI 侧为 `file list --section <栏目|none>`。
|
|
38
|
+
- 修复 `file update` 的结果被误报成「已还原」的渲染 bug(还原与更新的 payload 都带 `path`,现改用独立的 `restored` 标记区分)。
|
|
39
|
+
- HTTP 请求体上限由 4MB 提升至 32MB(base64 上传扫描件 / 照片)。
|
|
40
|
+
|
|
41
|
+
- **`section sync`:按模板补齐栏目字段(只增不改不删)**:栏目字段字典是**持久化数据**(实例化时深拷贝,此后独立演化),模板新增的字段**不会回溯**到已建栏目——于是「模板给求职加了 `file` 的附件字段,老栏目里却看不到上传入口」。新增 `section sync <ref>`(CLI)/ `POST /api/sections/:ref/sync`(HTTP)/ 栏目编辑弹窗的「同步模板字段」按钮,把模板里新增、本栏目还缺的分组与字段补进来,并保持模板顺序;已有字段(含用户改过的 label / hint / fill)与自定义分组原样保留。带快照与 `--dry-run`。顺带修复 `section update --add-field` 引用未声明分组时不补声明、导致面板整组字段消失的隐患。
|
|
42
|
+
|
|
43
|
+
## [0.4.0] - 2026-10-08
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- **口令对称加密的整库备份 / 恢复(导入导出)**:新增「加密备份」模块(CLI `backup export|import`,Web 同名面板,HTTP `POST /api/backup` 与 `POST /api/backup/restore`)。
|
|
48
|
+
- 导出:设置口令 → 整份数据(栏目 / 条目 / 设置)经 **scrypt 口令派生密钥 + AES-256-GCM** 加密为单个 `.nxskbak` 文件并在浏览器下载;文件内含随机盐,**口令不落盘**。
|
|
49
|
+
- 导入:选择备份文件并输入口令 → 解密校验后整份恢复;**恢复前自动给当前数据留安全快照**(可回滚)。
|
|
50
|
+
- 口令错误或文件被篡改:GCM 认证失败、明确报 BLOCKED,且不改动当前数据;两个动作均支持 `--dry-run`(只演练 / 只解密校验)。
|
|
51
|
+
- 口令也可用环境变量 `NX_SK_BACKUP_PASSWORD` 提供;复用 `core/crypto.js` 原语,与字段级密钥库(`core/vault.js`)相互独立。
|
|
6
52
|
|
|
7
53
|
## [0.3.4] - 2026-09-26
|
|
8
54
|
|
package/README.md
CHANGED
|
@@ -113,10 +113,19 @@ CLI 与 API 同源,skill 驱动 agent**。落到具体功能上:
|
|
|
113
113
|
| `nx-sk section list \| get \| add \| update \| remove` | 栏目 CRUD |
|
|
114
114
|
| `nx-sk section dump <id> [--mask]` | **一个栏目的全部信息**:字段台账 + 全部条目 + 每个条目的未填清单 |
|
|
115
115
|
| `nx-sk section templates` | 内置模板(job / secret) |
|
|
116
|
+
| `nx-sk section sync <id> [--dry-run]` | 按模板**补齐**本栏目缺的分组与字段(只增不改不删)——模板演进后让老栏目追上 |
|
|
116
117
|
| `nx-sk entry list \| get \| add \| update \| remove` | 条目 CRUD(PATCH 语义) |
|
|
117
118
|
| `nx-sk entry fields [--section job]` | 字段字典 —— 填之前先看这个,别猜字段名 |
|
|
119
|
+
| `nx-sk file list \| get \| add \| update \| remove` | 附件 CRUD(原件在 `~/nx-sk/files/`,同内容去重) |
|
|
120
|
+
| `nx-sk file add --path <文件> [--copy] [--category C]` | 导入附件:**默认移动原件**,`--copy` 仅复制 |
|
|
121
|
+
| `nx-sk file list [--section <栏目\|none>] [--q 关键字]` | 列附件:按「哪些栏目在引用」筛选(`none` = 未引用);返回栏目汇总与存储目录 |
|
|
122
|
+
| `nx-sk file restore <id> [--to DIR] [--copy]` | **可逆**:移回原始位置并撤销台账;`--copy` 只导出副本 |
|
|
123
|
+
| `nx-sk file content <id>` | 浏览器链接(内联预览 / `?download=1` 下载);CLI 打印物理路径 |
|
|
124
|
+
| `nx-sk file open <id>` | 用系统默认程序打开原件 |
|
|
118
125
|
| `nx-sk export run [--format json\|md\|both] [--section id] [--with-secrets] [--out DIR] [--dry-run]` | 整体导出 |
|
|
119
126
|
| `nx-sk export list` | 历次导出与目录内文件 |
|
|
127
|
+
| `nx-sk backup export [--password 口令] [--out DIR] [--dry-run]` | 口令对称加密整库,导出单个 `.nxskbak`(口令不落盘) |
|
|
128
|
+
| `nx-sk backup import --file <备份> [--password 口令] [--dry-run]` | 输入口令解密、整份恢复(恢复前自动留安全快照) |
|
|
120
129
|
| `nx-sk setting get \| set` | 全局设置 |
|
|
121
130
|
| `nx-sk skill list \| install \| get` | 把内置 skill 装给 agent / 给外部 agent 取上下文 |
|
|
122
131
|
|
|
@@ -154,6 +163,39 @@ nx-sk key remove OPENAI_KEY # 删除,写前自动留快照
|
|
|
154
163
|
状态与栏目一样:`key *` 只是 `entry *` 的语法糖(同模块、同一批 service 函数),
|
|
155
164
|
作用在 `settings.kvSection` 指向的单字段栏目上(默认 `secret`)。
|
|
156
165
|
|
|
166
|
+
统一附件管理(简历、头像、成绩单等原件都收进 `~/nx-sk/files/`):
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
nx-sk file add --path "D:\简历\张三-简历.pdf" # 默认移动原件进库
|
|
170
|
+
nx-sk file list # 台账:按栏目汇总 + 被引用情况
|
|
171
|
+
nx-sk file list --section none # 只看还没有条目引用的
|
|
172
|
+
nx-sk file restore f_xxxx # 可逆:移回原始位置、撤销台账
|
|
173
|
+
nx-sk file restore f_xxxx --to "D:\资料" --copy # 或导出副本到指定目录
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**附件怎么被条目引用**:条目的 `file` 字段存的就是**附件的 id**。id 全局唯一,
|
|
177
|
+
所以每条条目各有各的附件、互不串台;同一份原件也能被多条条目引用(sha256 去重后是同一条)。
|
|
178
|
+
**上传 / 选择发生在栏目条目的字段里**(求职 → 张三 → 「简历附件」直接上传或从库里选),
|
|
179
|
+
不在附件中心做指派:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
FID=$(nx-sk file add --path "D:\简历\张三-简历.pdf" --json | 取 id)
|
|
183
|
+
nx-sk entry update 张三 --set resumeFile=$FID # 字段值就是附件 id
|
|
184
|
+
nx-sk entry get 张三 --section job # 该字段随即显示附件名与物理路径
|
|
185
|
+
nx-sk file get $FID # 反查「被引用:求职 / 张三 / 简历附件」
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**「附件」中心由栏目驱动、不预定义任何分类或槽位**:它只展示当前库里存在的原件,
|
|
189
|
+
筛选片按「哪些栏目在引用附件」生成(外加「未引用」),每张卡片显示被哪个栏目/条目/字段引用。
|
|
190
|
+
工作台支持拖拽 / 点按钮上传、本机路径导入、搜索、图片缩略图、内联预览、下载、复制物理路径 / 链接、
|
|
191
|
+
编辑名称与备注、还原。求职条目表单的「附件资料」组里,
|
|
192
|
+
**简历附件 / 头像图片 / 成绩单 / 证书扫描件** 直接就地「上传文件」或从库里选。
|
|
193
|
+
|
|
194
|
+
> **看不到这些上传框?** 栏目的字段字典是**持久化数据**:栏目在实例化时把模板字段**深拷贝**下来,
|
|
195
|
+
> 此后独立演化,所以**模板后来新增的字段不会自动出现在已建好的栏目里**。
|
|
196
|
+
> 若你的求职栏目是很早建的,跑一次 `nx-sk section sync job`(或面板「栏目 → 编辑 → 同步模板字段」)
|
|
197
|
+
> 就能把模板新增的「附件资料」组与 4 个 `file` 字段补进来,且不改动你已有的字段与数据。
|
|
198
|
+
|
|
157
199
|
整体导出(凭据默认**含明文**——本机自己用;要分享给别人时加 `--no-secrets` 打码):
|
|
158
200
|
|
|
159
201
|
```bash
|
|
@@ -161,6 +203,18 @@ nx-sk export run --format both --out D:/备份/nx-sk
|
|
|
161
203
|
nx-sk export list
|
|
162
204
|
```
|
|
163
205
|
|
|
206
|
+
加密备份 / 恢复(口令对称加密,AES-256-GCM;导出设口令、恢复输口令):
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
nx-sk backup export --password '你的备份口令' # 写成 ~/nx-sk/backup/*.nxskbak
|
|
210
|
+
nx-sk backup import --file ~/nx-sk/backup/xxx.nxskbak --password '你的备份口令' --dry-run # 先只解密校验
|
|
211
|
+
nx-sk backup import --file ~/nx-sk/backup/xxx.nxskbak --password '你的备份口令' # 整份恢复
|
|
212
|
+
# 口令也可用环境变量 NX_SK_BACKUP_PASSWORD 提供
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Web 面板的「加密备份」页同样支持:导出在浏览器下载 `.nxskbak`,导入选择文件并输入口令;
|
|
216
|
+
口令错误或文件损坏会明确报错、不改动当前数据。
|
|
217
|
+
|
|
164
218
|
## 数据与安全
|
|
165
219
|
|
|
166
220
|
| 项 | 位置 / 做法 |
|
|
@@ -170,6 +224,8 @@ nx-sk export list
|
|
|
170
224
|
| 密文密钥 | 环境变量 `NX_SK_PASSPHRASE`(scrypt 派生 + 盐)优先,否则 `~/nx-sk/.vaultkey`(32 字节随机,0600) |
|
|
171
225
|
| 快照 | 每次破坏性写入前整库备份到 `~/nx-sk/backup/`(最多 20 份),拷回即回滚 |
|
|
172
226
|
| 导出 | `~/nx-sk/export/`,默认不含凭据明文 |
|
|
227
|
+
| 附件 | `~/nx-sk/files/` 存二进制原件,元数据在 `store.json` 的 `files`(sha256 去重;条目 `file` 字段存附件 id 即建立链接;`file restore` 可逆) |
|
|
228
|
+
| 加密备份 | `.nxskbak`:整库经 scrypt(口令)+AES-256-GCM 加密,口令不落盘;恢复前自动留安全快照 |
|
|
173
229
|
| 服务绑定 | 默认 `127.0.0.1`,不暴露到局域网;写操作校验 `Origin` |
|
|
174
230
|
| 数据损坏 | `store.json` 解析失败会先被改名为 `.corrupt-<时间戳>.json`,不会静默覆盖 |
|
|
175
231
|
|
|
@@ -197,25 +253,27 @@ nx-sk skill get nx-sk 10-sections-entries # 裸名 → references/10-sections-
|
|
|
197
253
|
| `10-sections-entries` | 填/改信息的完整命令与 AI 补全流程 |
|
|
198
254
|
| `20-secrets` | 密文机制、密钥来源、排查「解不开」 |
|
|
199
255
|
| `30-export-backup` | 导出、快照与回滚 |
|
|
200
|
-
| `40-
|
|
256
|
+
| `40-files` | 附件库:导入(默认移动)与还原、`file` 字段与条目的链接、附件中心由栏目驱动 |
|
|
201
257
|
|
|
202
258
|
## 开发
|
|
203
259
|
|
|
204
260
|
```bash
|
|
205
|
-
pnpm test # = lint + build + 冒烟(
|
|
261
|
+
pnpm test # = lint + build + 冒烟(98 项断言) + 单测(116 项)
|
|
206
262
|
```
|
|
207
263
|
|
|
208
264
|
| 目录 | 职责 |
|
|
209
265
|
| --- | --- |
|
|
210
266
|
| `bin/nx-sk.mjs` | 唯一入口,只转发 argv + 兜异常 |
|
|
211
|
-
| `src/core/` | 零业务语义:paths / errors / store / fsx / crypto / vault / fields / render / ids / open |
|
|
267
|
+
| `src/core/` | 零业务语义:paths / errors / store / fsx / crypto / vault / fields / attachments / render / ids / open |
|
|
212
268
|
| `src/modules/<域>/` | `index.js`(action 声明) + `service.js`(业务) + `view.jsx`(面板) |
|
|
213
269
|
| `src/runtime/` | registry / spec / cli / api / server —— 装配层,不写业务 |
|
|
214
270
|
| `src/web/frontend/` | React 壳 + 组件 + 视图注册表 |
|
|
215
271
|
| `assets/nx-sk/` | 随包分发的 skill(SKILL.md + references/) |
|
|
216
272
|
| `tests/unit/` · `tests/smoke.mjs` | 一致性断言 + 端到端冒烟 |
|
|
217
273
|
|
|
218
|
-
**加一个功能域要碰的 12 处**(其中 3
|
|
274
|
+
**加一个功能域要碰的 12 处**(其中 3 处没有任何断言会替你发现)属于**开发规范、不属于随包分发的
|
|
275
|
+
agent 手册** —— 它写在创建本项目的脚手架 skill `server-cli-web-scaffold` 的
|
|
276
|
+
`references/A07-extension-loop.md`,`assets/nx-sk/` 里只放「怎么用 nx-sk」。
|
|
219
277
|
|
|
220
278
|
## License
|
|
221
279
|
|
package/assets/nx-sk/SKILL.md
CHANGED
|
@@ -11,7 +11,7 @@ description: 本机个人资源管理器——栏目化存储个人信息(求
|
|
|
11
11
|
|
|
12
12
|
| 栏目 | id | 内容 |
|
|
13
13
|
| --- | --- | --- |
|
|
14
|
-
| 求职 | `job` |
|
|
14
|
+
| 求职 | `job` | 求职用的个人信息档案(姓名/学历/求职意向/简历头像成绩单附件…约 80 个字段) |
|
|
15
15
|
| 密钥 | `secret` | **一张 KV 表**(`kv: true`):一行一个键值对。面板渲染成表格,值以 AES-256-GCM 密文落盘 |
|
|
16
16
|
|
|
17
17
|
## 核心不变量
|
|
@@ -65,6 +65,34 @@ nx-sk key remove OPENAI_KEY # 删除,写前自动留快照
|
|
|
65
65
|
**KV 栏目不许加字段**:它的形状就是一行一个键值对。想加东西就用 `key set <名称> <值>`
|
|
66
66
|
(在 KV 栏目里 `entry update --set 新键=值` 会被拒绝并告诉你该用哪条命令)。
|
|
67
67
|
|
|
68
|
+
附件(简历、头像、成绩单等二进制原件)走统一附件库,物理文件在 `~/nx-sk/files/`:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
nx-sk file add --path "D:\简历\张三-简历.pdf" # 默认把原件移动进库(--copy 仅复制)
|
|
72
|
+
nx-sk file list # 台账:按栏目汇总 + 被引用情况
|
|
73
|
+
nx-sk file list --section none # 只看还没有条目引用的
|
|
74
|
+
nx-sk file restore f_xxxx # 可逆:移回原始位置并撤销台账
|
|
75
|
+
nx-sk file restore f_xxxx --to DIR --copy # 或导出副本、库中保留
|
|
76
|
+
nx-sk file open f_xxxx # 系统默认程序打开原件
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
求职条目里的「简历附件 / 头像图片 / 成绩单 / 证书扫描件」是 `file` 字段,
|
|
80
|
+
它的值就是**附件 id**(全局唯一 → 各条目互不串台;同内容去重后是同一条,可被多条条目共享):
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
nx-sk entry update 张三 --set resumeFile=f_xxxx # 字段值 = 附件 id
|
|
84
|
+
nx-sk entry get 张三 --section job # 字段随即显示附件名与物理路径
|
|
85
|
+
nx-sk file get f_xxxx # 反查「被引用:求职 / 张三 / 简历附件」
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**上传 / 选择发生在栏目条目里**(Web 的表单字段可直接「上传文件」或从库里选);
|
|
89
|
+
「附件」中心只负责**统一展示与库存管理**,由栏目驱动(筛选片 = 哪些栏目在引用附件 + 未引用),
|
|
90
|
+
**不预定义任何分类或槽位**,也不做指派。相同内容(sha256)自动去重,不重复占空间。
|
|
91
|
+
|
|
92
|
+
**看不到 `file` 上传字段?** 栏目字段台账是**持久化数据**——栏目实例化时深拷贝模板字段,此后独立演化,
|
|
93
|
+
所以模板**后来**新增的字段不会自动出现在已建好的栏目里。用 `nx-sk section sync <栏目>`(可先 `--dry-run`)
|
|
94
|
+
把模板新增的分组与字段补进来(只增不改不删);面板侧是「栏目 → 编辑 → 同步模板字段」。
|
|
95
|
+
|
|
68
96
|
## ref 路由表(按需加载)
|
|
69
97
|
|
|
70
98
|
| ref | 何时读取 |
|
|
@@ -73,13 +101,14 @@ nx-sk key remove OPENAI_KEY # 删除,写前自动留快照
|
|
|
73
101
|
| `10-sections-entries` | **动手填/改信息时必读**——栏目与条目的完整命令、AI 补全个人信息的推荐流程、字段字典怎么扩、读命令与写命令的参数陷阱 |
|
|
74
102
|
| `20-secrets` | 存/读大模型 key、密文机制、密钥来源(环境变量 vs 本机密钥文件)、什么时候会解不开 |
|
|
75
103
|
| `30-export-backup` | 整体导出、只导出某个栏目、快照与回滚、明文密钥的取舍 |
|
|
76
|
-
| `40-
|
|
104
|
+
| `40-files` | **传/换简历头像成绩单等二进制原件时读**——附件库台账、导入(默认移动)与还原、`file` 字段怎么和条目建立链接、附件中心为什么由栏目驱动、看不到上传字段怎么办 |
|
|
77
105
|
|
|
78
106
|
取 ref 全文(外部 agent 用这条,不必进终端翻文件):
|
|
79
107
|
|
|
80
108
|
```bash
|
|
81
109
|
nx-sk skill get nx-sk # SKILL.md 全文
|
|
82
110
|
nx-sk skill get nx-sk 10-sections-entries # 裸名 → references/10-sections-entries.md
|
|
111
|
+
nx-sk skill get nx-sk 40-files # 附件库:导入 / 链接 / 还原
|
|
83
112
|
nx-sk skill get nx-sk references/20-secrets.md # 也可写完整路径
|
|
84
113
|
nx-sk skill get nx-sk --json # 四元 JSON:{skillName, ref, content, contentBytes, install}
|
|
85
114
|
```
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
▼ ▼
|
|
19
19
|
service 层(业务) CLI(同一条链)
|
|
20
20
|
▼ │
|
|
21
|
-
core(存储 / 密文 / 字段字典 / 渲染)
|
|
21
|
+
core(存储 / 密文 / 字段字典 / 附件 / 渲染) │
|
|
22
22
|
▼
|
|
23
23
|
skill install ──► ~/.claude/skills ──► agent
|
|
24
24
|
```
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
## 二、分层与依赖方向
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
core/ 零业务语义:paths / errors / store / fsx / crypto / vault / fields / render / ids / open
|
|
34
|
+
core/ 零业务语义:paths / errors / store / fsx / crypto / vault / fields / attachments / render / ids / open
|
|
35
35
|
modules/ 功能域,每个自包含:index.js(声明) + service.js(业务) + view.jsx(面板)
|
|
36
36
|
runtime/ 装配层:registry / spec / cli / api / server —— 不写业务
|
|
37
37
|
web/frontend/ React 壳,只 import 各模块的 view.jsx
|
|
@@ -112,5 +112,6 @@ CLI 侧这四个取值分别渲染成不同的可读提示,退出码只有「
|
|
|
112
112
|
| 删条目/栏目不留快照 | 误删即不可逆;这是用户的**唯一一份**个人信息 | 所有破坏性写操作先 `snapshotStore()` 到 `~/nx-sk/backup/` |
|
|
113
113
|
| store.json 解析失败就当空库继续 | 下一次写入把用户数据永久覆盖 | 先把损坏文件改名为 `store.json.corrupt-<时间>.json`,再降级返回空结构 |
|
|
114
114
|
| 前端 import 了 `node:*` 或 `core/` | Vite 把 Node 侧代码打进浏览器包,dev 模式白屏 | lint 的 `files` 同时覆盖 `view.jsx`,禁掉 `node:*` / `core` / `runtime` / `service.js` |
|
|
115
|
-
| 新增模块忘了往 eslint 互依禁列里补一行 | **静默**:新模块变成「谁都可以依赖」,且规则随模块数增加持续衰减 |
|
|
115
|
+
| 新增模块忘了往 eslint 互依禁列里补一行 | **静默**:新模块变成「谁都可以依赖」,且规则随模块数增加持续衰减 | 在禁列旁留注释说明它是**逐模块枚举**的、漏补是静默的;加模块前先读 `eslint.config.js` |
|
|
116
116
|
| 代理前缀 `/api` 与前端源码目录 `api/` 撞车 | 只在 dev 模式整页白屏,报错却是 404 / ECONNREFUSED,离根因很远 | vite 代理加 `bypass`,按「是不是前端资源」分流;并用测试钉住 `shouldServeLocally` |
|
|
117
|
+
| 把附件的「上传 / 选择」放到附件中心,再让条目去引用 | 条目里看不到上传入口,用户不知道该在哪儿加文件;附件中心还被迫预定义分类与槽位,跟栏目脱节 | **上传 / 选择发生在栏目条目里**(`file` 字段的值 = 附件 id);附件中心由栏目驱动、只做统一展示与库存管理,**不预定义分类、不做指派** |
|
|
@@ -25,13 +25,18 @@ store.json(~/nx-sk/store.json 或 $NX_SK_STORE)
|
|
|
25
25
|
| 修改 | `nx-sk section update <id> [--title …] [--add-field '{…}'] [--remove-field a --remove-field b]` | `PATCH /api/sections/:ref` |
|
|
26
26
|
| 删除 | `nx-sk section remove <id> [--force]` | `DELETE /api/sections/:ref` |
|
|
27
27
|
| **全量** | `nx-sk section dump <id> [--mask]` | `GET /api/sections/:ref/dump` |
|
|
28
|
+
| **同步模板** | `nx-sk section sync <id> [--dry-run]` | `POST /api/sections/:ref/sync` |
|
|
28
29
|
| 模板 | `nx-sk section templates` | `GET /api/sections/templates` |
|
|
29
30
|
|
|
30
31
|
- **`remove` 在栏目非空时会被 `blocked` 挡住**(除非 `--force`)——防止一键抹掉全部档案。
|
|
31
32
|
- `remove` 目标不存在时**报 `NOT_FOUND`**(不静默成功),就是为了让「打错一个字」当场暴露。
|
|
32
33
|
- `dump` 是「快速获得一个栏目的全部信息」的正解:字段字典 + 全部条目 + 每个条目的完整度与**未填清单**。
|
|
34
|
+
- **`sync` 按模板补齐字段**:栏目字段字典是**持久化数据**——实例化时深拷贝模板字段,此后独立演化,
|
|
35
|
+
所以模板**后来**新增的分组与字段不会自动出现在老栏目里(典型症状:求职没显示附件上传框)。
|
|
36
|
+
`section sync <id>` 把模板有、本栏目还缺的分组与字段补进来(**只增不改不删**,保持模板顺序;
|
|
37
|
+
已有字段含改过的 label / hint / fill 原样保留),带快照与 `--dry-run`;面板侧是「栏目 → 编辑 → 同步模板字段」。
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
内置模板 5 个:`job`(求职 / 个人信息,79 字段 / 10 分组——含「附件资料」组:简历附件 / 头像图片 / 成绩单 / 证书扫描件)、`projects`(项目经历)、`internships`(实习/工作经历)、`campus`(校内职务/实践)、`secret`(密钥,**单字段 KV**——细节见 `20-secrets`)。三类经历栏目(projects / internships / campus)**一个项目 / 一段经历 = 一个条目**,角色、时间、技术栈都是独立字段——不要往 job 栏目里塞经历。
|
|
35
40
|
|
|
36
41
|
## 三、条目命令
|
|
37
42
|
|
|
@@ -110,10 +115,13 @@ nx-sk section update job --remove-field blog
|
|
|
110
115
|
nx-sk section update job --fields @fields.json
|
|
111
116
|
```
|
|
112
117
|
|
|
113
|
-
字段定义支持:`key`(字母开头)、`label`、`type`(`text|textarea|number|date|month|bool|select|tags|secret`)、
|
|
118
|
+
字段定义支持:`key`(字母开头)、`label`、`type`(`text|textarea|number|date|month|bool|select|tags|secret|file`)、
|
|
114
119
|
`group`、`hint`、`options`(候选项)、`sensitive`(true 则密文落盘)、`maxItems`(tags 上限)、
|
|
115
120
|
`fill`(填写策略,见下)。
|
|
116
121
|
|
|
122
|
+
> `type: 'file'` 是**附件字段**:值存的是一个**附件 id**(不是路径),导入原件、附件库台账、
|
|
123
|
+
> 以及「文件统一放 `~/nx-sk/files/`」的完整口径见 `40-files`。
|
|
124
|
+
|
|
117
125
|
> `select` 的 `options` 是**候选项不是白名单**:真实值(如某个少数民族)不在候选里也允许写入。
|
|
118
126
|
|
|
119
127
|
### 填写策略 `fill`:有些格子填了反而减分
|
|
@@ -78,3 +78,19 @@ cp ~/nx-sk/backup/20260924-144238-entry-remove-e_xxx.json ~/nx-sk/store.json
|
|
|
78
78
|
| 内容 | 结构化 + 可读的 Markdown;凭据默认含明文(`--no-secrets` 可打码) | 原样的整库 JSON(含密文) |
|
|
79
79
|
| 位置 | `~/nx-sk/export/`(可改) | `~/nx-sk/backup/`(固定) |
|
|
80
80
|
| 回滚用 | 不能直接回滚(形状不同) | 能,拷回 store.json 即可 |
|
|
81
|
+
|
|
82
|
+
## 五、口令加密备份 / 恢复(导入导出)
|
|
83
|
+
|
|
84
|
+
整份数据用**口令派生密钥 + AES-256-GCM** 对称加密为单个 `.nxskbak` 文件;口令不落盘。
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
nx-sk backup export --password '备份口令' # → ~/nx-sk/backup/nx-sk-backup-<时间>.nxskbak
|
|
88
|
+
nx-sk backup export --password '备份口令' --out D:/备份 # 指定输出目录
|
|
89
|
+
nx-sk backup import --file <备份>.nxskbak --password '备份口令' --dry-run # 只解密校验,不改动
|
|
90
|
+
nx-sk backup import --file <备份>.nxskbak --password '备份口令' # 整份恢复
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- 导出时文件内写入**随机盐**,密钥由 `scrypt(口令, 盐)` 派生;恢复时用同一口令派生同一把密钥。
|
|
94
|
+
- **口令错误 / 文件被篡改**:GCM 认证失败、明确报 BLOCKED,且不改动当前数据。
|
|
95
|
+
- 恢复(整份替换)前会**自动给当前数据另留一份安全快照**(`…-before-restore.json`),可回滚。
|
|
96
|
+
- 口令也可用环境变量 `NX_SK_BACKUP_PASSWORD` 提供;Web「加密备份」页提供同样能力(浏览器下载 / 选择文件导入)。
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# 40 · 附件库
|
|
2
|
+
|
|
3
|
+
> 归属 `nx-sk` skill 主文档。要把「简历 / 头像 / 成绩单 / 证书扫描件」这类**二进制原件**收进库、
|
|
4
|
+
> 挂到条目上、或还原拿走时读这篇。
|
|
5
|
+
> 栏目与条目的通用命令见 `10-sections-entries`;这篇只讲「文件」这一块。
|
|
6
|
+
|
|
7
|
+
## 一、数据模型
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
~/nx-sk/files/<分类>/ 二进制原件(真实文件,移动/复制进来的)
|
|
11
|
+
~/nx-sk/store.json 的 files[] 台账:id / name / rel / ext / bytes / sha256 / 标签 / 备注
|
|
12
|
+
~/nx-sk/store.json 的 entries[].values[<file字段>] = f_xxxx ← 链接:字段值就是附件 id
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- 一个**附件** = 一次导入的原件 + 一条台账记录。物理文件永远以台账 `rel` 为准。
|
|
16
|
+
- 条目里的 `file` 字段(如 `resumeFile` / `avatar`),**值就是附件 id**(形如 `f_xxxx`)。
|
|
17
|
+
id 全局唯一 → 各条目的附件空间天然隔离;同一个原件(sha256 相同)**去重**后是同一条,
|
|
18
|
+
可被多条条目共享,不重复占空间。
|
|
19
|
+
- **上传 / 选择发生在栏目条目里**;「附件」中心只负责统一展示与库存管理,不做指派。
|
|
20
|
+
|
|
21
|
+
## 二、命令
|
|
22
|
+
|
|
23
|
+
| 操作 | 命令 | 接口 |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| 列表 | `nx-sk file list [--section job] [--q 关键字]` | `GET /api/files` |
|
|
26
|
+
| 单条 | `nx-sk file get <id>` | `GET /api/files/:ref` |
|
|
27
|
+
| 导入 | `nx-sk file add --path <本机文件>` | `POST /api/files` |
|
|
28
|
+
| 改属性 | `nx-sk file update <id> [--name …] [--tags …] [--note …]` | `PATCH /api/files/:ref` |
|
|
29
|
+
| 取本体 | `nx-sk file content <id> [--download]` | `GET /api/files/:ref/content` |
|
|
30
|
+
| 打开 | `nx-sk file open <id>`(本机默认程序) | 无(纯 CLI) |
|
|
31
|
+
| 还原 | `nx-sk file restore <id> [--to DIR] [--copy]` | `POST /api/files/:ref/restore` |
|
|
32
|
+
| 删除 | `nx-sk file remove <id>` | `DELETE /api/files/:ref` |
|
|
33
|
+
|
|
34
|
+
- `file list --section <栏目>` 只看「被某栏目引用」的附件;`--section none` 只看**还没有任何条目引用**的。
|
|
35
|
+
- `file content` 是浏览器链接:内联预览,加 `--download` 强制下载;CLI 侧打印物理路径与链接。
|
|
36
|
+
- 所有写命令都支持 `--dry-run`;`file remove` 连物理原件一起删并自动留台账快照——
|
|
37
|
+
只想「拿出原件、库里留着」应该用 `file restore --copy`。
|
|
38
|
+
|
|
39
|
+
## 三、导入:默认移动,`--copy` 才复制
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
nx-sk file add --path "D:\简历\张三-简历.pdf" # 默认把原件**移动**进库(原件不再留在原地)
|
|
43
|
+
nx-sk file add --path "D:\简历\张三-简历.pdf" --copy # 只复制一份进库,原文件留着
|
|
44
|
+
nx-sk file add --path C:\扫描\成绩单.pdf --tags 成绩单 --note "教务处盖章版"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- **默认移动**是本工具的取舍:提交附件 = 把原件搬进 `~/nx-sk/files/` 统一管理。
|
|
48
|
+
想保留原地那份就显式 `--copy`。
|
|
49
|
+
- 同 sha256 的文件直接复用已有记录(返回 `duplicated`),不会重复占空间。
|
|
50
|
+
- `file add --dry-run` 只计算落点与校验,不移动、不写台账。
|
|
51
|
+
|
|
52
|
+
## 四、链接:`file` 字段值 = 附件 id
|
|
53
|
+
|
|
54
|
+
条目**不复制文件**,只存一个附件 id。把 id 写进栏目里 `file` 类型的字段,链接就建立了:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# 先拿到附件的 id(file add 的输出 / file list --json 里的 files[].id)
|
|
58
|
+
nx-sk file add --path "D:\简历\张三-简历.pdf" --category resume
|
|
59
|
+
|
|
60
|
+
nx-sk entry update 张三 --set resumeFile=f_xxxx # 字段值 = 附件 id
|
|
61
|
+
nx-sk entry get 张三 --section job # 该字段随即显示附件名与物理路径
|
|
62
|
+
|
|
63
|
+
# 反查:这个附件被哪些栏目 / 条目 / 字段引用
|
|
64
|
+
nx-sk file get f_xxxx
|
|
65
|
+
# 被引用: 求职 / 张三 / 简历附件
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
求职条目里的「简历附件 / 头像图片 / 成绩单 / 证书扫描件」就是 `file` 字段。
|
|
69
|
+
**别用文件名或路径去填** —— 值只认附件 id;填了别的东西条目侧会显示成「未解析」。
|
|
70
|
+
|
|
71
|
+
## 五、还原(可逆)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
nx-sk file restore f_xxxx # 移回**原始位置**并撤销台账(默认)
|
|
75
|
+
nx-sk file restore f_xxxx --to "D:\资料" --copy # 或导出副本到指定目录,库里保留原件与台账
|
|
76
|
+
nx-sk file restore f_xxxx --to "D:\资料" # Web 上传件没有原始位置时,必须用 --to 指定目录
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| 形态 | 效果 |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `restore`(移动) | 物理原件移回原始位置(或 `--to` 目录),**台账记录撤销** |
|
|
82
|
+
| `restore --copy` | 只**导出副本**到目标目录,库中原件与台账**都保留** |
|
|
83
|
+
|
|
84
|
+
- Web 上传进来的附件没有「原始位置」,还原时必须给 `--to`。
|
|
85
|
+
- 还原/删除都会先留快照(`~/nx-sk/backup/`),可回滚——见 `30-export-backup`。
|
|
86
|
+
|
|
87
|
+
## 六、Web 面板
|
|
88
|
+
|
|
89
|
+
`nx-sk serve` → 顶部「附件」页:
|
|
90
|
+
|
|
91
|
+
- 上传(拖拽 / 选文件)、本机路径导入、搜索、图片缩略图、内联预览、下载、复制物理路径 / 链接;
|
|
92
|
+
- **组织方式由栏目驱动、不预定义分类**:筛选片按「哪些栏目在引用附件」动态生成(外加「未引用」),
|
|
93
|
+
每张卡片显示被哪个栏目 / 条目 / 字段引用;
|
|
94
|
+
- 编辑弹窗可改名称 / 分类 / 标签 / 备注(改分类或文件名时物理原件随之移动);
|
|
95
|
+
- 条目表单里的 `file` 字段可直接「上传文件」或从库里选一个,保存即建立链接。
|
|
96
|
+
|
|
97
|
+
## 七、看不到 `file` 上传字段 / 条目里解析不到附件
|
|
98
|
+
|
|
99
|
+
1. **栏目里没有这类字段** —— 栏目字段台账是**持久化数据**:栏目实例化时深拷贝模板字段,
|
|
100
|
+
此后独立演化,模板**后来**新增的字段不会自动回溯到已建栏目。用
|
|
101
|
+
`nx-sk section sync <栏目>`(可先 `--dry-run`)把模板新增的分组与字段补进来(只增不改不删);
|
|
102
|
+
面板侧是「栏目 → 编辑 → 同步模板字段」。
|
|
103
|
+
2. **字段值不是有效的附件 id** —— `file get` 确认那个 id 存在;字段值必须是被导入过的附件 id,
|
|
104
|
+
不是文件名、不是路径。
|