dsh-config-manager 0.1.2 โ†’ 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/README.md CHANGED
@@ -1,250 +1,290 @@
1
- # DSH Config Manager
1
+ # ๐ŸŽ’ DSH Config Manager
2
2
 
3
- **Backup ยท Export ยท Import ยท Migrate ยท Restore** โ€” A configuration backup / export / import / migration manager for DSH.
3
+ **Pack up your DSH configuration and take it anywhere โ€” restore your whole environment on a new machine with one click.**
4
4
 
5
- [English](README.md) | [็ฎ€ไฝ“ไธญๆ–‡](README.zh-CN.md)
5
+ [English](README.md) ยท [็ฎ€ไฝ“ไธญๆ–‡](README.zh-CN.md)
6
6
 
7
- One-click export of your main DSH configuration to a ZIP file, import it on another DSH, and restore your working environment as completely as possible.
7
+ ---
8
+
9
+ ## What is this? ๐Ÿค”
10
+
11
+ DSH is your AI assistant workbench โ€” it holds your settings: model configs, plugins, skills, workspacesโ€ฆ
12
+
13
+ **DSH Config Manager is its "moving service"**:
14
+
15
+ ```
16
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ‘  one-click โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ‘ก one-click โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
17
+ โ”‚ Machine A โ”‚ โ”€โ”€โ”€โ”€ export โ”€โ”€โ”€โ–บ โ”‚ dsh-config.zip โ”‚ โ”€โ”€โ”€โ”€ import โ”€โ”€โ”€โ–บ โ”‚ Machine B โ”‚
18
+ โ”‚ my config โ”‚ โ”‚ (one file) โ”‚ โ”‚ all restored โ”‚
19
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
20
+ ```
21
+
22
+ > โš ๏ธ **Security first**: no secrets (API Key / Token / Password) are exported by default. See [Security](#-security).
8
23
 
9
- > โš ๏ธ **Security first: no Secret (API Key / Token / Password) is exported by default.** See [Security](#security).
24
+ ---
25
+
26
+ ## โœจ Highlights
27
+
28
+ | Icon | Feature | In one line |
29
+ |:---:|---|---|
30
+ | ๐Ÿš€ | **One-click Export** | Package your recommended config into a ZIP |
31
+ | ๐Ÿ“ฆ | **One-click Import** | Restore your environment on another machine |
32
+ | ๐Ÿ‘€ | **Preview before import** | Full preview first โ€” **never touches your config silently** |
33
+ | โš”๏ธ | **Conflict handling** | Keep Current / Use Imported / Review โ€” you decide |
34
+ | ๐Ÿ—บ๏ธ | **Path auto-mapping** | Detects dead absolute paths and lets you remap them |
35
+ | ๐Ÿ”’ | **Secret safety** | API Keys are never exported; re-enter them after import |
36
+ | โ†ฉ๏ธ | **Automatic rollback** | Failed import restores everything automatically |
37
+ | ๐Ÿ—‚๏ธ | **Profiles** | Save multiple setups (Work / Personal) and switch anytime |
10
38
 
11
39
  ---
12
40
 
13
- ## What it does
41
+ ## ๐Ÿ”„ How it works?
14
42
 
15
- DSH configuration is a hybrid model โ€” one central `settings.yaml` plus multiple standalone files plus plugin-owned files (see `Docs/research/dsh-architecture.md`).
16
- This plugin does **not** copy `~/.dsh` wholesale. Instead it collects configuration by real config categories, packages them into a ZIP backup with a manifest and checksums, and runs a safe import flow on the target side:
43
+ ### Export (pack it up)
17
44
 
18
45
  ```
19
- Analyze โ†’ Preview โ†’ Snapshot โ†’ Apply โ†’ Validate โ†’ Rollback(if needed)
46
+ Read your config โ†’ strip secrets (safe) โ†’ build manifest โ†’ compute checksums โ†’ pack into ZIP
20
47
  ```
21
48
 
22
- ## Features
49
+ ### Import (restore the environment)
50
+
51
+ Every step confirms and backs up first โ€” **it never modifies your config directly**:
23
52
 
24
- - **Export**: Quick Export (one-click recommended config) and per-section custom export.
25
- - **Import**: ZIP validation โ†’ manifest read โ†’ integrity check โ†’ schema check โ†’ compatibility check โ†’ content scan โ†’ import-plan preview โ†’ user confirmation โ†’ automatic snapshot โ†’ apply โ†’ validate โ†’ result (automatic rollback on failure).
26
- - **Dry Run / Preview**: `analyzeImport()` + `createImportPlan()` are pure computation with zero writes โ€” full preview before importing.
27
- - **Conflict handling**: global strategies `merge` (default) / `replace` / `skipExisting` plus per-item `Keep Current / Use Imported / Review`.
28
- - **Path mapping**: cross-device absolute-path detection and batch prefix mapping (workspace paths / MCP cwd / plugin config paths).
29
- - **Secret safety**: all sensitive fields are stripped by default; encrypted full backup (scrypt + AES-256-GCM) is an opt-in advanced feature.
30
- - **Automatic snapshot & rollback**: backs up the target state before import and restores it in reverse order on failure.
31
- - **Schema versioning & migration**: independent `schemaVersion`, migration logic centralized in `src/migrations/`.
32
- - **Idempotency**: re-importing the same ZIP creates no duplicates (keyed by Plugin ID / MCP serverName / Prompt name / Workspace id / Credential ref).
33
- - **Compatibility score**: Excellent / Good / Partial / Unsupported (rule-driven).
34
- - **Profiles**: save current config as a Profile / switch / duplicate / rename / export / import / delete; switching includes Preview + snapshot + rollback (`src/profiles/`).
53
+ ```
54
+ Select ZIP โ†’ validate file โ†’ check integrity โ†’ check schema โ†’ compatibility check
55
+ โ†’ scan contents โ†’ build import plan โ†’ preview & confirm
56
+ โ†’ auto-backup current config โ†’ apply โ†’ validate โ†’ done
57
+ โ”‚
58
+ โ””โ”€ failed midway? โ†’ automatically restored (rollback)
59
+ ```
35
60
 
36
- ## Installation
61
+ ---
37
62
 
38
- This plugin is a standard **DSH bundle plugin** (mirrors the dsh-ssh engineering pattern, research report ยง5.1): `package.json` declares
39
- `dsh.bundle.patch` (pointing to `cordis.patch.yml`, the CLI bundle hard criterion) and `dsh.client` (browser-half declaration);
40
- `npm run build` produces both halves (`lib/index.js` host half + `lib/client.js` browser half, the latter loaded into the Web GUI via
41
- `window.__ModuleLoader__.load(...)`).
63
+ ## ๐Ÿ“ฅ Installation
42
64
 
43
- Two install options (choose one):
65
+ It's a standard **DSH plugin** โ€” two steps:
44
66
 
45
67
  ```bash
46
- # โ‘  Recommended โ€” install from the npm registry
68
+ # โ‘  Install the plugin
47
69
  dsh plugin --profile web add dsh-config-manager --config.auto-install-peers=false
48
70
 
49
- # โ‘ก Alternative โ€” local tgz / directory (development & testing)
50
- npm run build
51
- npm pack # produces dsh-config-manager-0.1.0.tgz
52
- dsh plugin --profile web add file:/absolute/path/to/dsh-config-manager-0.1.0.tgz
71
+ # โ‘ก Restart DSH (a "Backup & Migration" entry appears in Settings)
53
72
  ```
54
73
 
55
- > **`--legacy-peer-deps` note**: some DSH core packages in peerDependencies (e.g.
56
- > `@deepseek-ai/dsh-plugin-marketplace`, `dsh-host-plugin-inventory`) are not published to the public npm registry
57
- > and only exist in a local DSH profile. If npm/pnpm fails while resolving peer dependencies, skip automatic peer installation:
58
- > - Direct npm install: `npm install --legacy-peer-deps`
59
- > - `dsh plugin add` (forwards to pnpm internally): `dsh plugin --profile web add <spec> --config.auto-install-peers=false`
60
- >
61
- > At runtime these packages are provided by the DSH profile itself (peerDependencies semantics); the plugin never reinstalls them.
74
+ > ๐Ÿ’ก **Why the flag?** `--config.auto-install-peers=false` skips a few DSH core packages that aren't on the public registry yet (the DSH runtime provides them). Just copy-paste it.
75
+
76
+ **From source / local package** (for developers):
62
77
 
63
- > **Local verification tip**: isolate testing with the `$DSH_HOME` environment variable โ€” never touches `~/.dsh`:
78
+ ```bash
79
+ npm run build && npm pack # produces dsh-config-manager-0.1.2.tgz
80
+ dsh plugin --profile web add file:/absolute/path/dsh-config-manager-0.1.2.tgz
81
+ ```
82
+
83
+ > ๐Ÿงช **Try it without touching your real environment?** Use an isolated `DSH_HOME`:
64
84
  > ```bash
65
- > $env:DSH_HOME = "D:\tmp\dsh-home" # Windows PowerShell
66
- > dsh plugin --profile test add file:<tgz> --config.auto-install-peers=false
67
- > dsh --profile test --dump-config | Select-String config-manager # should show the mount line
85
+ > $env:DSH_HOME = "D:\tmp\dsh-home" # Windows PowerShell
86
+ > dsh plugin --profile test add dsh-config-manager --config.auto-install-peers=false
87
+ > dsh --profile test --dump-config | Select-String config-manager
68
88
  > ```
69
89
 
70
- ## Export
90
+ ---
71
91
 
72
- Two modes:
92
+ ## ๐Ÿš€ Quick start (3-minute tour)
73
93
 
74
- - **Quick Export**: one-click export of the recommended sections (settings / ui / providers / plugins / mcp / prompts / skills / agentPresets / workspaces / credentialsStatus).
75
- - **Custom Export**: choose sections individually (`pluginFiles` and `sessions` are opt-in; `sessions` is off by default).
94
+ ```
95
+ Machine A (export)
96
+ 1. Open DSH โ†’ Settings โ†’ "Backup & Migration"
97
+ 2. Click "Export Configuration" โ†’ choose "Quick Export"
98
+ 3. You get dsh-config-2026-08-14.zip (the report confirms no secrets inside)
99
+
100
+ Copy the ZIP to Machine B (import)
101
+ 1. Open DSH โ†’ "Backup & Migration" โ†’ "Import Configuration"
102
+ 2. Select the ZIP โ†’ wait for analysis โ†’ review the "Import Preview"
103
+ 3. Path issues? โ†’ choose new paths (batch mapping supported)
104
+ 4. Conflicts? โ†’ choose Keep Current / Use Imported
105
+ 5. Confirm import โ†’ wait
106
+ 6. Re-enter any missing API Keys as prompted
107
+ 7. โœ… Settings / plugins / MCP / skills / workspaces are back
108
+ ```
76
109
 
77
- Output: `dsh-config-<yyyy-MM-dd>.zip` containing `manifest.json` + per-section data + `integrity/checksums.json` (SHA-256).
110
+ ---
78
111
 
79
- ## Import
112
+ ## ๐Ÿงฉ Features
80
113
 
81
- ```
82
- Select ZIP โ†’ Validate ZIP โ†’ Read Manifest โ†’ Check Integrity โ†’ Check Schema
83
- โ†’ Check Compatibility โ†’ Scan Contents โ†’ Generate Import Plan โ†’ Show Preview
84
- โ†’ User Confirms โ†’ Create Backup (Snapshot) โ†’ Import โ†’ Validate โ†’ Show Result
85
- ```
114
+ ### ๐Ÿ“ค Export (two modes)
86
115
 
87
- Import flow is enforced: **no writes happen before confirmation**; **a snapshot is always created before importing**; on failure `rollbackOnError` decides between full rollback or per-item honest reporting.
116
+ | Mode | Description |
117
+ |---|---|
118
+ | **Quick Export** (recommended) | One-click: settings / UI / models / plugins / MCP / skills / workspacesโ€ฆ |
119
+ | **Custom Export** | Tick the categories you want |
88
120
 
89
- ## Security
121
+ > Output: `dsh-config-<date>.zip` with manifest + per-category data + SHA-256 checksums.
90
122
 
91
- > **The default backup contains no Secret values.** This is a hard security invariant, enforced by the `Exporter`:
123
+ ### ๐Ÿ“ฅ Import (safe flow)
92
124
 
93
- - All structured section data passes a sensitive-field scan before being written to the ZIP (field-name blacklist: password / token / apiKey / secret / credential / authorization / cookie / privateKey / clientSecret etc., case-insensitive); matches are stripped.
94
- - `ctx.settings.describe({ redactSecrets: true })` is the first line of defense for DSH-known secrets; the sensitive-field scanner is the second line of defense for plugin-defined fields.
95
- - Credentials (`.credentials.yaml`) **never export values**, only state (`{ref, required, configured, hasValue:false}`); after import a "N credentials need attention" list is generated.
96
- - **Encrypted full backup (optional)**: when "Include secrets" is explicitly checked, a backup password is required; `node:crypto` (scrypt KDF + AES-256-GCM) is used, **the password is never written to the manifest**; `secrets.enc` is only written back via `ctx.credentials.set()` after decryption.
97
- - Without an encryption provider, `includeSecrets: true` is rejected (secrets are never leaked in plaintext).
98
- - Logging is fully redacted โ€” Secret values never reach logs.
99
- - A ZIP is untrusted input: defends against Zip Slip / absolute paths / symlinks / zip bombs (entry count / compressed size / uncompressed size / compression-ratio limits) / malformed ZIPs / checksum mismatch โ€” any trigger rejects the whole archive.
125
+ - **Nothing is written before confirmation** โ€” analyze & preview are zero-write
126
+ - **Backup before applying** โ€” the target config is snapshotted automatically
127
+ - **Automatic rollback on failure** โ€” full rollback or skip-and-continue, your choice
100
128
 
101
- ## What is NOT exported
129
+ ### ๐Ÿ‘€ Import Preview (dry run)
102
130
 
103
- By default **not** exported (spec ยง34.19/20):
131
+ Shown fully before importing:
104
132
 
105
- - API Key / Password / Token / Cookie / Session / auth credentials (values)
106
- - `~/.dsh/.anonymous-user-id` (device unique ID)
107
- - Conversation history (`sessions/`, off by default; v1 supports file-level copy only)
108
- - Logs / Cache / temp files
109
- - Browser localStorage UI state (no host-side channel; only `uiMigrationNotes` is exported)
110
- - Plugin binaries (never packaged โ€” only the manifest is migrated, install goes through the official mechanism)
133
+ ```
134
+ โœ“ 18 settings will be updated โœ“ 6 plugins already installed
135
+ โš  2 plugins need installation โš  3 secrets need re-entry
136
+ โš  1 path needs mapping โš  2 conflicts need attention
137
+ ```
111
138
 
112
- ## Secrets
139
+ ### โš”๏ธ Conflict handling
113
140
 
114
- | Backup type | Import behavior |
141
+ When the target already has a same-named item, you choose:
142
+
143
+ | Option | Meaning |
115
144
  |---|---|
116
- | Normal backup (no secrets.enc) | All credentials โ†’ `MissingSecret`, filled in by the user after import |
117
- | Encrypted backup + correct password | Auto-decrypted and restored via `credentials.set()` (per-item confirmation in preview) |
118
- | Encrypted backup + no password | Same as normal backup: state-only, user fills in |
145
+ | **Keep Current** | Leave the target's config untouched |
146
+ | **Use Imported** | Overwrite with the backup's value |
147
+ | **Review** | Skip for now, handle later |
148
+
149
+ ### ๐Ÿ—บ๏ธ Path mapping
150
+
151
+ `C:\Users\alice\projects` doesn't exist on the new machine? The plugin:
152
+ 1. Detects the dead absolute paths automatically
153
+ 2. Lets you pick new paths
154
+ 3. Supports **batch prefix mapping** (`C:\Users\alice\` โ†’ `/Users/bob/` in one shot)
119
155
 
120
- ## Compatibility
156
+ ### ๐Ÿ”’ Secrets
121
157
 
122
- | Status | Rule |
158
+ | Scenario | Behavior |
123
159
  |---|---|
124
- | Excellent | Same platform, no missing sections, supported schema |
125
- | Good | Backup from an older DSH (target is backward compatible) |
126
- | Partial | Cross-platform / missing sections / backup newer than target |
127
- | Unsupported | Schema beyond the supported range |
160
+ | Default backup | **No secret values at all** โ€” only records which keys are needed |
161
+ | Encrypted backup (optional) | AES-256-GCM with a password; the password is **never written to the file** |
162
+ | After import | "3 secrets need re-entry" โ€” values stay in memory only |
128
163
 
129
- ## Backup format
164
+ ### ๐Ÿ—‚๏ธ Profiles
165
+
166
+ Save multiple configurations (Work / Personal) and switch anytime; switching includes preview + auto-backup + rollback.
167
+
168
+ ---
169
+
170
+ ## ๐Ÿ“ฆ What's inside a backup?
130
171
 
131
172
  ```
132
173
  dsh-config-2026-08-14.zip
133
- โ”œโ”€โ”€ manifest.json # schemaVersion / exporter / source / sections / security
134
- โ”œโ”€โ”€ config/settings.json # non-UI settings namespaces (redacted + revision)
135
- โ”œโ”€โ”€ config/ui.json # UI namespaces + uiMigrationNotes
136
- โ”œโ”€โ”€ ai/providers.json # llm-* providers/models (same section, not split)
137
- โ”œโ”€โ”€ plugins/plugins.json + patch.json
138
- โ”œโ”€โ”€ mcp/servers.json # dsh-mcp-client entries extracted from the composed patch
139
- โ”œโ”€โ”€ custom/prompts.json + skills/
140
- โ”œโ”€โ”€ agents/presets/
141
- โ”œโ”€โ”€ workspaces/workspaces.json
142
- โ”œโ”€โ”€ plugin-files/ # optional
143
- โ”œโ”€โ”€ security/credentials.json # credential state (never contains values)
144
- โ”œโ”€โ”€ security/secrets.enc # encrypted backups only
145
- โ””โ”€โ”€ integrity/checksums.json # SHA-256
146
- ```
147
-
148
- ## Development
149
-
150
- ```bash
151
- npm install --legacy-peer-deps # peers include DSH core packages not on the public registry, see Installation
152
- npm run typecheck # tsc --noEmit
153
- npm run build # tsc -p tsconfig.build.json (host half lib/) + tsdown (client bundle lib/client.js)
154
- npm run bundle # rebuild the client bundle only (tsdown)
155
- npm test # node --test "src/**/*.test.ts" "tests/**/*.test.ts"
174
+ โ”œโ”€โ”€ manifest.json # backup manifest: version / source / time / sections
175
+ โ”œโ”€โ”€ config/
176
+ โ”‚ โ”œโ”€โ”€ settings.json # settings (redacted)
177
+ โ”‚ โ””โ”€โ”€ ui.json # UI preferences
178
+ โ”œโ”€โ”€ ai/providers.json # AI providers / models
179
+ โ”œโ”€โ”€ plugins/ # plugin manifest (binaries are never packaged)
180
+ โ”œโ”€โ”€ mcp/servers.json # MCP server configs
181
+ โ”œโ”€โ”€ custom/ # prompts / skills
182
+ โ”œโ”€โ”€ agents/presets/ # agent presets
183
+ โ”œโ”€โ”€ workspaces/ # workspaces
184
+ โ”œโ”€โ”€ security/credentials.json # credential state (no values)
185
+ โ”œโ”€โ”€ security/secrets.enc # encrypted backups only
186
+ โ””โ”€โ”€ integrity/checksums.json # SHA-256 checksums
156
187
  ```
157
188
 
158
- Architecture: the core engine (`src/core`) depends only on the `ConfigAdapter` / `HostContext` interfaces (decoupled from the DSH runtime, testable with in-memory mocks); `src/adapters` implements each config category; `src/security` provides secret scanning / encryption / integrity / ZIP safety / redaction; `src/migrations` centralizes schema migration.
189
+ ---
190
+
191
+ ## ๐Ÿ›ก๏ธ Security
192
+
193
+ - **The default backup contains no secret values** โ€” a hard invariant, enforced at export
194
+ - **Not exported**: API Keys / passwords / tokens / cookies / sessions / device unique ID / logs & cache / plugin binaries
195
+ - **A ZIP is untrusted input**: defends against Zip Slip, malicious paths, zip bombs, corrupt archives โ€” any trigger rejects the whole file
196
+ - **Logs are fully redacted** โ€” secret values never reach logs
197
+ - **Encrypted backup**: scrypt + AES-256-GCM; the password lives in memory only
198
+
199
+ ---
200
+
201
+ ## ๐Ÿค Compatibility
202
+
203
+ | Status | Meaning |
204
+ |---|---|
205
+ | โœ… Excellent | Same platform, complete sections, supported schema |
206
+ | ๐Ÿ‘ Good | Backup from an older DSH |
207
+ | โš ๏ธ Partial | Cross-platform / missing sections / backup newer than target |
208
+ | โŒ Unsupported | Schema beyond the supported range (cannot import) |
209
+
210
+ ---
159
211
 
160
- ## Publishing (GitHub Actions ยท npm trusted publishing / OIDC)
212
+ ## โ“ FAQ
161
213
 
162
- Pushing a version tag triggers the CI pipeline in `.github/workflows/publish.yml`, which typechecks, runs the tests, builds, and publishes the package to npm. Publishing uses **npm trusted publishing (OIDC)** โ€” no long-lived token is stored in the repository; the npm CLI exchanges a short-lived identity with the registry via GitHub Actions.
214
+ **Q: Will my API Key be in the backup?**
215
+ No. The default backup **never contains any secret value** โ€” only records which keys you'll need to re-enter.
216
+
217
+ **Q: Will importing overwrite my existing config?**
218
+ Not silently. Conflicts ask you to choose (Keep Current / Use Imported); the target is auto-backed-up and can roll back.
219
+
220
+ **Q: Does it work across platforms (Windows โ†’ macOS)?**
221
+ Yes. Dead absolute paths are detected and remapped (batch replacement supported).
222
+
223
+ **Q: Can a corrupted ZIP still be imported?**
224
+ No. A checksum mismatch rejects the import outright (protects against corruption or tampering).
225
+
226
+ **Q: Will re-importing duplicate things?**
227
+ No. Items are deduplicated by stable IDs (plugin ID / MCP name / skill nameโ€ฆ); existing items are skipped.
228
+
229
+ ---
230
+
231
+ ## ๐Ÿ‘จโ€๐Ÿ’ป For developers
163
232
 
164
233
  ```bash
165
- npm version patch # 0.1.0 โ†’ 0.1.1 (also creates the tag)
166
- git push origin main --tags
234
+ npm install --legacy-peer-deps # install dependencies
235
+ npm run typecheck # type checking
236
+ npm run build # build (host lib/ + client bundle)
237
+ npm test # run tests (192)
238
+ npm run bundle # rebuild the client bundle only
167
239
  ```
168
240
 
169
- One-time setup on npmjs.com (required before the first OIDC publish):
241
+ **Architecture**: the core engine is decoupled from the DSH runtime (mock-testable) โ†’ per-category adapters โ†’ security modules โ†’ centralized schema migrations.
170
242
 
171
- **Option A โ€” website** (scoped packages / where the UI is available):
172
- 1. Open the package page: https://www.npmjs.com/package/dsh-config-manager โ†’ **Settings โ†’ Publishing access**.
173
- 2. **Add trusted publisher**: Provider **GitHub Actions** ยท owner `xiajiajun516` ยท repository `dsh-config-manager` ยท workflow filename `publish.yml`.
243
+ **Auto-publish**: push a tag โ†’ automatically published to npm (GitHub Actions + OIDC, no stored secrets):
174
244
 
175
- **Option B โ€” CLI** (recommended; works for unscoped packages where the UI section is missing):
176
245
  ```bash
177
- npm logout
178
- npm login # web OAuth + 2FA code
179
- npm trust github dsh-config-manager \
180
- --file publish.yml \
181
- --repo xiajiajun516/dsh-config-manager \
182
- --allow-publish # first run asks for a 2FA code
183
- npm trust list dsh-config-manager # verify
246
+ npm version patch # 0.1.2 โ†’ 0.1.3
247
+ git push origin main --tags # CI: test โ†’ build โ†’ publish
184
248
  ```
185
249
 
186
- No `NPM_TOKEN` repository secret is needed โ€” a previously configured token can be revoked (npm is deprecating bypass-2FA tokens anyway).
250
+ > One-time OIDC trusted-publisher setup:
251
+ > ```bash
252
+ > npm login
253
+ > npm trust github dsh-config-manager --file publish.yml --repo xiajiajun516/dsh-config-manager --allow-publish
254
+ > ```
255
+ > Or add the GitHub Actions trusted publisher on the package page (Settings โ†’ Publishing access).
187
256
 
188
- Notes:
257
+ ---
189
258
 
190
- - The version in `package.json` must match the tag (`npm version` keeps them in sync automatically).
191
- - The workflow upgrades npm (`npm install -g npm@latest`) because OIDC publishing requires npm โ‰ฅ 11.5.1.
192
- - The workflow can also be triggered manually via **Run workflow** on the Actions page.
259
+ ## ๐Ÿงช Testing
193
260
 
194
- ## Testing
261
+ **All 192 tests pass** (Node's built-in test runner, zero extra dependencies), covering:
195
262
 
196
- Test framework: **node:test (Node built-in, zero dependency)**, following the choice made in the core module (no vitest). Tests live in `src/**/*.test.ts` and `tests/**/*.test.ts`.
263
+ | Category | Coverage |
264
+ |---|---|
265
+ | Export | normal / empty / large / Unicode & special chars / secret filtering |
266
+ | Import | normal / merge / replace / skip / conflict / missing plugin / missing dependency / missing secret |
267
+ | Rollback | mid-flight failure โ†’ everything restored |
268
+ | Security | malicious ZIP / corrupt archive / checksum mismatch / path traversal |
269
+ | Cross-platform | Windows โ†” macOS โ†” Linux path handling |
270
+ | Migration | schema upgrade mechanism |
197
271
 
198
- Coverage matrix (spec ยง33 + acceptance scenarios Aโ€“G):
272
+ ---
199
273
 
200
- | Group | Coverage |
201
- |---|---|
202
- | Export | normal / empty / large (1MB+) / Unicode / special characters / secret filtering |
203
- | Import | normal / Merge / Replace / Skip (never deletes target-only items, ยง32) / Conflict / Missing plugin / Missing dependency / Missing secret / unconfirmed rejection |
204
- | Rollback (scenario E) | multi-adapter mid-flight failure โ†’ full restore (settings / file blobs / workspace / patch lines); `rollbackOnError=false` comparison; honest partial-rollback report |
205
- | Migration (scenario G) | `migrateToCurrent` mechanism-level: same version / too new / below minimum / no path / registry overlap / chained progression (**honest note: v1 is current, no real v2 exists for end-to-end verification**) |
206
- | Security (scenario F) | malformed ZIP / oversized entry count / checksum mismatch & missing / Zip Slip / absolute paths |
207
- | Cross-platform (scenario B) | win32โ†’darwin / darwinโ†’win32 / linuxโ†’win32 batch prefix mapping |
208
- | Redaction | log messages / meta / full pipeline never leaks secret values |
209
- | Schema | manifest structure validation / version predicate functions |
210
-
211
- Current test results: **186 tests, all passing** (`npm test`); `npm run typecheck` and `npm run build` both pass.
212
-
213
- ## Known limitations
214
-
215
- 1. **Workspace: create/rename title only**: DSH's workspace service has no "overwrite whole" write channel โ€” import can create workspaces and update titles; paths and session lists are maintained by DSH itself from the real directory, cross-device paths are adapted via path mapping.
216
- 2. **Some DSH core packages are not on the public npm registry** (e.g. `@deepseek-ai/dsh-plugin-marketplace`, `dsh-host-plugin-inventory`): features depending on their APIs only work in a local profile; installing this plugin requires skipping automatic peer installation (see the `--legacy-peer-deps` note in [Installation](#installation)).
217
- 3. **No MCP management API** (research report ยง4.3): MCP is imported as composed patch lines and takes effect after restarting DSH; no add/remove/update API.
218
- 4. **Plugin installation requires a restart**: `pluginMarketplace.installPlugin` only returns `needsRestart`; restarting depends on DSH Desktop.
219
- 5. **Browser localStorage UI state is not migrated** (task board data, panel widths, etc.): no host channel.
220
- 6. **keybindings / workflow configs / commands / rules files**: DSH currently has no such concepts; no sections are implemented (nothing invented).
221
- 7. **Credential values cannot be rolled back**: DSH never reads credential values back; credentials overwritten during import can only be marked `manualHint` for manual re-entry on rollback.
222
- 8. **Newly created items cannot be rollback-deleted**: DSH settings have no delete semantics; namespaces newly created by import can only be handled manually on rollback (honestly reported as partial).
223
- 9. **Schema migration**: v1โ†’v2 is a placeholder (current `CURRENT_SCHEMA_VERSION=1`); the mechanism is ready but no real v2 exists to verify.
224
- 10. **History/session migration**: off by default; v1 supports file-level copy only.
225
- 11. **Encrypted backups**: depend on a strong user-set password; a lost password makes `secrets.enc` undecryptable (by design).
226
-
227
- ## Manual Test (shortest manual flow)
228
-
229
- > Prerequisites: two DSH instances (or two config directories on one machine); this plugin built and installed per [Installation](#installation).
230
-
231
- ```
232
- DSH A
233
- โ†’ open Config Manager โ†’ Export Configuration
234
- โ†’ choose Quick Export โ†’ export dsh-config-<date>.zip (confirm in the report that Secrets are all excluded)
235
- โ†’ copy the ZIP to DSH B
236
-
237
- DSH B
238
- โ†’ open Config Manager โ†’ Import Configuration
239
- โ†’ select the ZIP โ†’ wait for Analyzing... โ†’ review the Import Preview (sections/plugins/path mapping/credential re-entry list)
240
- โ†’ if there are path issues โ†’ choose mapping directories (batch prefix mapping)
241
- โ†’ resolve conflicts (Keep Current / Use Imported / Review)
242
- โ†’ confirm Import โ†’ watch progress โ†’ review the result report
243
- โ†’ fill in missing credentials (N credentials need attention)
244
- โ†’ Verify: settings / plugins / MCP / Prompts / Skills / Workspaces are restored;
245
- if the import failed midway โ†’ confirm it rolled back automatically and the original config still works
246
- ```
274
+ ## ๐Ÿ“‹ Known limitations
275
+
276
+ 1. **Workspace: create/rename title only** โ€” DSH has no whole-overwrite write channel; paths & session lists are maintained by DSH itself (path mapping adapts cross-device)
277
+ 2. **Some DSH core packages are not public** โ€” features depending on their APIs only work in a local DSH; install needs `--config.auto-install-peers=false`
278
+ 3. **No MCP management API** โ€” MCP is imported as config lines and takes effect after restarting DSH
279
+ 4. **Plugin install requires a restart**
280
+ 5. **Browser UI state (localStorage) is not migrated** โ€” e.g. task board data, panel widths
281
+ 6. **keybindings / workflows / commands / rules** โ€” DSH has no such concepts; no fake sections
282
+ 7. **Credential values can't be rolled back** โ€” re-enter manually after a rollback that touched them
283
+ 8. **Newly created items can't be rollback-deleted** โ€” DSH settings have no delete semantics
284
+ 9. **Schema migration** โ€” the mechanism is ready; the v1โ†’v2 chain is a placeholder (v1 is current)
285
+ 10. **History/session migration is off by default** โ€” v1 copies files only
286
+ 11. **Encrypted backups** โ€” a lost password means the `secrets.enc` can't be decrypted (by design)
247
287
 
248
288
  ---
249
289
 
250
- **Product principles**: better to migrate one config less than to break a user's existing config. Every Import follows `Analyze โ†’ Preview โ†’ Backup โ†’ Modify โ†’ Validate โ†’ Rollback`; every Secret follows `never export by default / never log / never expose / never silently transfer`.
290
+ **Product principles**: better to migrate one config less than to break your existing config. Every import follows `Analyze โ†’ Preview โ†’ Backup โ†’ Apply โ†’ Validate โ†’ Rollback(if needed)`; every secret follows `never export by default / never log / never expose / never silently transfer`.