# Upgrade

English | [Chinese](UPDATE.zh.md)

> Verified against deepseek-harness **0.2.1-alpha.4** with plugin **0.14.0** (`pnpm run typecheck` clean, `pnpm run build` clean, **15** unit tests passing via `pnpm test`, and the harness's own compatibility check admitting `dsh-kingdee@0.14.0` on runtime `0.2.1-alpha.4`) and adapted for **Kingdee Cloud Starry Sky V9.1 Enterprise Edition** (backward-compatible with V9.0 / V8.x). **No live-tenant verification was performed.**

How to move **dsh-kingdee** to a newer version.

## Before you upgrade

1. **Read the [CHANGELOG.md](./CHANGELOG.md) or [CHANGELOG.zh.md](./CHANGELOG.zh.md)** for the target version. The biggest risk is a **breaking change**, and each release note marks them explicitly.
2. **Back up your configuration.** The connection settings (`baseUrl`, `acctId`, `authMode`, …) live in the profile's `cordis.yml` or settings document; the secrets stay in the environment / credentials store and are not backed up by this plugin.

## Upgrade steps

```sh
# 1. Update the installed bundle to the new version (note --profile comes before the command)
dsh plugin --profile web update dsh-kingdee

# Or pin to the exact version
dsh plugin --profile web add dsh-kingdee@0.14.0

# 2. (Recommended) rebuild / reinstall if you build the host half from source
pnpm install && pnpm run build
```

3. **Restart the DSH host** so the new plugin version is loaded: stop and start the DSH process (relaunch the `dsh` app / your DSH host) — there is no restart verb.

## After you upgrade

- **0.14.0 aligns with DeepSeek Harness 0.2.1-alpha.4 and corrects the license statement — and it is not a mandatory upgrade.** No runtime code, configuration or tool surface change: the plugin behaves exactly as 0.13.0. Every `@deepseek-ai/dsh-*` devDependency moves from `0.2.1-alpha.2` to `0.2.1-alpha.4`, the lockfile is regenerated against 0.2.1-alpha.4, and the workspace supply-chain exemption is refreshed to the 0.2.1-alpha.4 package set. The `@deepseek-ai/dsh-credentials` and `@deepseek-ai/dsh-tools` peers are **unchanged** at `>=0.1.7-alpha.2 <0.3.0`, so `0.13.0` is admitted on 0.2.1-alpha.4 as well and nothing forces this upgrade. The 0.2.1-alpha.3 and 0.2.1-alpha.4 releases changed no seam this plugin consumes. This release also fixes a documentation defect: both README files described the repository as under a proprietary license while `LICENSE` and `package.json.license` have carried MIT since `0.5.0`, and no changelog entry had ever recorded that revert. Upgrade with `dsh plugin --profile web add dsh-kingdee@0.14.0` (or `dsh plugin --profile web update dsh-kingdee`).
- **0.13.0 aligns with DeepSeek Harness 0.2.1-alpha.2 and adds display metadata manifest support.** Every `@deepseek-ai/dsh-*` devDependency moves from `0.2.0-rc.2` to `0.2.1-alpha.2`. This release packages native `icon.svg` artwork and bilingual manifest resources (`locale/en.json`, `locale/zh.json`) conforming to DSH 0.2.1-alpha.2 display conventions for Plugin Manager. A self-contained `prepare` script is configured for git installations. The peer ranges remain unchanged at `>=0.1.7-alpha.2 <0.3.0`, so `0.12.0` and `0.11.1` remain admitted on 0.2.1-alpha.2 as well and this upgrade is not forced.
- **0.12.0 aligns with DeepSeek Harness 0.2.0-rc.2 — and it is not a mandatory upgrade.** No runtime code, configuration or tool surface change: the plugin behaves exactly as 0.11.1. Every `@deepseek-ai/dsh-*` devDependency moves from `0.2.0-rc.1` to `0.2.0-rc.2`, the lockfile is regenerated against 0.2.0-rc.2, and the workspace supply-chain exemption is refreshed to the 0.2.0-rc.2 package set. The `@deepseek-ai/dsh-credentials` and `@deepseek-ai/dsh-tools` peers are **unchanged** at `>=0.1.7-alpha.2 <0.3.0`, so `0.11.1` is admitted on 0.2.0-rc.2 as well and nothing forces this upgrade. 0.12.0 is verified against 0.2.0-rc.2 (typecheck clean, build clean, 15 unit tests passing) and is admitted on `0.2.0-rc.2`, `0.2.0-rc.1`, `0.2.0`, `0.1.7-rc.2` and `0.1.7-alpha.2`, while it is still refused on `0.1.6-alpha.2`; the earlier `0.10.0` (`^0.1.7-alpha.2`) remains **refused on 0.2.0-rc.2**. Upgrade with `dsh plugin --profile web add dsh-kingdee@0.12.0` (or `dsh plugin --profile web update dsh-kingdee`).
- **0.11.1 corrects the documentation; no code, manifest or behavior change.** The package content is identical to 0.11.0 — the same sources, the same peers, the same configuration — so upgrading from 0.11.0 needs no action at all. This release closes five documentation defects found by a full bilingual proofread: the English 0.7.0 changelog entry was missing the third-party `LoginByAppSecret` login, the `app`-mode `KDAuthentication` removal with its new `userNameRef` requirement, and the login-response fix that had made authentication fail on a real tenant; the Chinese 0.6.1 entry carried a heading that did not match the English category and one vague item with no counterpart; the configuration guide used two different placeholder hosts for the same example; the Chinese configuration guide stated the credential-seam contract as prose where English used two bullets; and the Chinese install guide omitted the `172.16.0.0/12` range from the blocked private networks.
- **0.11.0 adapts to DeepSeek Harness 0.2.0-rc.1 — and 0.10.0 is refused on it.** No runtime code, configuration or tool surface change: the manifest edits are the version, the `@deepseek-ai/dsh-*` peer ranges, the pinned devDependencies and the workspace supply-chain exemption. The `@deepseek-ai/dsh-credentials` and `@deepseek-ai/dsh-tools` peers move from `^0.1.7-alpha.2` to `>=0.1.7-alpha.2 <0.3.0`, and every `@deepseek-ai/dsh-*` devDependency is pinned to `0.2.0-rc.1` (`@deepseek-ai/cordis` stays `^4.0.4` and `@deepseek-ai/schemastery` stays `^3.18.4`). DeepSeek Harness 0.2.0-rc.1 enforces a **hard peer-compatibility gate**: before a plugin row loads, the harness checks every `@deepseek-ai/dsh` / `@deepseek-ai/dsh-*` peer entry against the single running runtime version, with prereleases participating in range matching, and refuses an incompatible row (an incompatible bundle is skipped). `engines.dsh` is **not** what the gate reads, so 0.10.0's `^0.1.7-alpha.2` peers — which exclude 0.2.x — make that release **refused on 0.2.0-rc.1**. On 0.2.0-rc.1 upgrade with `dsh plugin --profile web add dsh-kingdee@0.11.0` (or `dsh plugin --profile web update dsh-kingdee`). 0.11.0 is admitted on `0.1.7-alpha.2` through `0.2.x`, and it is still refused on `0.1.6-alpha.2`. `dsh plugin allow-version <package@version> --dsh-version <runtime> --accept-risk` (or the plugin manager) only records an **exact-version exemption** in the profile's `compatibility.json`: a risk acknowledgement rather than a compatibility fix, and neither a plugin upgrade nor a harness upgrade inherits the grant.
- **0.10.0 aligns with DeepSeek Harness 0.1.7-rc.2.** No runtime code, configuration or tool surface change — the plugin behaves exactly as 0.9.1. `devDependencies` are pinned to `0.1.7-rc.2`; the `@deepseek-ai/dsh-*` peer ranges stay `^0.1.7-alpha.2`, so the plugin stays installable on every `0.1.7` prerelease from `0.1.7-alpha.2` through `0.1.7-rc.2`. Every seam this plugin consumes is source-identical between `0.1.7-rc.1` and `0.1.7-rc.2`, so no source changed and no configuration field moved. No action required.
- **0.9.1 is a documentation and repository-tooling release.** No runtime code, configuration or tool surface changes — the plugin behaves exactly as 0.9.0. The repository now holds TypeScript sources only: the bilingual-documents gate moved from `scripts/check-docs-language.mjs` to `scripts/check-docs-language.ts`, which Node ≥22.19 runs by stripping the types (still with no dependencies installed, still before CI's install step), and `scripts/**/*.ts` joined the `tsconfig.json` include list. This release also corrects the Tools-table order in the README, the duplicated section numbers in the configuration guide, and restored changelog entries that had lost their text. No action required.
- **0.9.0 raises the harness floor to DeepSeek Harness 0.1.7.** The plugin now requires `0.1.7-alpha.2` or newer and is verified on `0.1.7-rc.1`; `devDependencies` are pinned to `0.1.7-rc.1` and `engines.dsh` is `^0.1.7-alpha.2`. Configuration migrated to the 0.1.7 **volatile schema**: the same twelve fields with the same names, values and defaults, but `apply` now reads one live reference per field and captures them once per operation, so a saved edit and a rotated credential both reach the next operation without a restart. The plugin no longer registers a settings section (`ctx.settings.installSection` is gone) — the Host discovers the exported `Config` schema and renders this entry's form, keyed by the profile row id `kingdee`. **On a `0.1.6` host the plugin is refused at load**: DeepSeek Harness 0.1.7-rc.1 verifies a plugin's declared `@deepseek-ai/dsh*` peers against the running runtime before admitting the row, so upgrade the harness first, or grant the exact-version exemption DSH prints with `dsh plugin allow-version dsh-kingdee@0.9.0 <your-dsh-version>`. **No breaking config change** — `cordis.yml` and `cordis.patch.yml` keep working unchanged.
- **0.8.0 adapts to DeepSeek Harness 0.1.6-alpha.2 client UI.** DSH 0.1.6-alpha.2 retired `settings.plugin.item` and introduced the Plugins manager page (`ui-plugin-manager`). The client configuration card now binds into `plugins.row.config` (`dsh-kingdee#kingdee`) and `plugins.bundle.config` (`dsh-kingdee`), providing both concise summary and full interactive configuration views.
- **0.7.0 rewires authentication and stub URLs — check these first.** `app` mode now performs a real `AuthService.LoginByAppSecret` login and **requires `userNameRef`** (the integration user) alongside `appId` / `appSecret`; it no longer emits a `KDAuthentication` header. Every stub URL now ends with `.common.kdsvc`, and the login/logout stubs live under `AuthService.*` (`ValidateUser` / `LoginByAppSecret` / `LogOut`). `serviceEndpoints.servicePrefix` was removed — use `loginByAppSecretService` + `stubSuffix` instead. `kingdee_invoke`'s `serviceName` now takes the custom-stub path `{namespace}.{class}.{method},{assembly}` (e.g. `GetCust.GetCust.ExecuteService,GetCust`), which replaces the dynamic-form URL segment. This release also fixes authentication itself: the login services answer with their own `{"LoginResultType": 1}` shape, which earlier versions misread as a failed business envelope.
- **Take advantage of Kingdee V9.1 features.** The `kingdee_query` and `kingdee_query_business_data` tools accept `orderString`, `limit`, and `startRow` for stable pagination. Tools such as `kingdee_audit`, `kingdee_unaudit`, `kingdee_delete`, `kingdee_unsubmit`, and `kingdee_delete_draft` support passing `numbers` directly (e.g., `SO-20260901`), removing the need for manual surrogate ID resolution. From product version `9.1.0.20250807` on, `Delete` also returns a correct `Number`.
- **Re-check V9.1 permissions and rate limits.** V9.1 tightened external-user access control, so a missing query permission can surface as an **empty result rather than an error** — run a probe query per `FormId` instead of trusting an empty row set. Because the server now logs WebAPI request bodies, prefer `app` mode over account/password where possible, and put the host's egress IP on the WebAPI rate-limit whitelist.
- **SSRF Safety & Host Configuration.** If your previous configuration used a raw private IP (such as `192.168.x.x`, `10.x.x.x`, or `localhost`), update `baseUrl` to an authorized enterprise domain name (e.g., `https://erp.example.com/K3Cloud`). Direct requests to loopback and private subnets without proper hostname resolution are blocked by default for enterprise security compliance.
- **Re-check the settings card.** A new version may add fields (e.g. the new `lcid`, default `2052`, or the new `app`-mode requirement on `userNameRef`). Confirm the displayed values match what you intend.
- **Re-verify a query.** Run a `kingdee_query` against a known form id to confirm the connection and auth still work.
- **Credentials.** Credentials are re-resolved per operation, so no action is needed unless a reference name changed — in that case update `userNameRef` / `passwordRef` / `appSecretRef` in the settings. `userNameRef` is now required in `app` mode too (it names the integration user).

## Examples of what a breaking change looks like

- A tool name or a required parameter changes (e.g. a tool is renamed).
- A credential reference name changes.
- The config shape changes (a key is renamed or removed).

Each of these is called out explicitly as breaking in the relevant [CHANGELOG.md](./CHANGELOG.md) / [CHANGELOG.zh.md](./CHANGELOG.zh.md) entry.

## Rollback

`dsh plugin update` records versions; roll back to the previous version the same way you installed it:

```sh
dsh plugin --profile web add dsh-kingdee@<previous-version>
```

Then restart and re-verify.
