You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A plugin installed from outside this repo cannot make its settings namespace editable in the web settings page. Even after the plugin registers its namespace (via installSettingsSection / settings.register) and contributes a settings.section cell on the client, web reads/writes are refused with settings-not-exposed unless the namespace is manually appended to WEB_SETTINGS_NAMESPACES in packages/host/apiproxy. That list is a hardcoded const in the shipped package, so the patch is overwritten on every dsh upgrade (npx reinstall / @deepseek-ai/dsh update) — a silent regression for the plugin's users.
Reproduction
Install a third-party plugin, e.g. dsh plugin --profile web add link:/path/to/my-plugin, whose host half calls installSettingsSection(ctx, 'my-ns', schema, entry, hooks) and whose client half registers a settings.section cell (id: 'my-ns').
Open Settings → the plugin's page, change a field, hit Save.
Expected: the write persists (schema validation + revision fencing apply).
Actual: the write is refused before the settings seam is touched:
settings-not-exposed: settings namespace "my-ns" is not exposed to configuration clients
Editing ~/.dsh/settings.yaml directly works fine.
Workaround: append 'my-ns' to WEB_SETTINGS_NAMESPACES in both lib/index.js and lib/types/api-proxy.js of the installed @deepseek-ai/dsh-host-apiproxy, then restart. Fragile: any dsh update wipes it, and the source src/ tree ships without the entry, so the divergence is easy to miss.
Background
The design note .agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.zh.md already records this as a deliberate cost:
deferred because it would change the seam contract, every existing registration point, anti-enumeration semantics, and needs a fail-closed redaction path before plugins may expose arbitrary schemas.
Proposal
Implement the registration-time exposure declaration, e.g. an expose option on settings.register(ns, schema, { expose }) (or a dedicated registration call), addressing the deferred concerns:
Anti-enumeration: only namespaces the owning plugin explicitly marks exposed are served to configuration clients; describe/get for others keep answering settings-not-exposed exactly as today.
Redaction: reuse the existing settings.describe({ redactSecrets: true }) path so an exposed arbitrary schema still never leaks secrets over the wire (the current seam already redacts before views are built).
Migration: default expose: false keeps today's semantics for existing callers; in-repo namespaces flip to expose: true as they're migrated off WEB_SETTINGS_NAMESPACES, which can then be removed.
Until then, at minimum it would help to document the whitelist requirement for third-party plugin authors — the runtime error message already points to the workaround, but the docs don't, and the upgrade-overwrite failure mode is hard to diagnose.
(Encountered with a local third-party plugin dsh-llm-proxy; happy to provide more detail or a minimal repro repo.)
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
A plugin installed from outside this repo cannot make its settings namespace editable in the web settings page. Even after the plugin registers its namespace (via
installSettingsSection/settings.register) and contributes asettings.sectioncell on the client, web reads/writes are refused withsettings-not-exposedunless the namespace is manually appended toWEB_SETTINGS_NAMESPACESinpackages/host/apiproxy. That list is a hardcoded const in the shipped package, so the patch is overwritten on every dsh upgrade (npx reinstall /@deepseek-ai/dshupdate) — a silent regression for the plugin's users.Reproduction
Install a third-party plugin, e.g.
dsh plugin --profile web add link:/path/to/my-plugin, whose host half callsinstallSettingsSection(ctx, 'my-ns', schema, entry, hooks)and whose client half registers asettings.sectioncell (id: 'my-ns').Open Settings → the plugin's page, change a field, hit Save.
Expected: the write persists (schema validation + revision fencing apply).
Actual: the write is refused before the settings seam is touched:
settings-not-exposed: settings namespace "my-ns" is not exposed to configuration clientsEditing
~/.dsh/settings.yamldirectly works fine.Workaround: append
'my-ns'toWEB_SETTINGS_NAMESPACESin bothlib/index.jsandlib/types/api-proxy.jsof the installed@deepseek-ai/dsh-host-apiproxy, then restart. Fragile: any dsh update wipes it, and the sourcesrc/tree ships without the entry, so the divergence is easy to miss.Background
The design note
.agents/notes/implemented/feature/2026-08-10-web-plugin-configuration.zh.mdalready records this as a deliberate cost:and documents the preferred alternative — a registration-time exposure declaration:
deferred because it would change the seam contract, every existing registration point, anti-enumeration semantics, and needs a fail-closed redaction path before plugins may expose arbitrary schemas.
Proposal
Implement the registration-time exposure declaration, e.g. an
exposeoption onsettings.register(ns, schema, { expose })(or a dedicated registration call), addressing the deferred concerns:describe/getfor others keep answeringsettings-not-exposedexactly as today.settings.describe({ redactSecrets: true })path so an exposed arbitrary schema still never leaks secrets over the wire (the current seam already redacts before views are built).expose: falsekeeps today's semantics for existing callers; in-repo namespaces flip toexpose: trueas they're migrated offWEB_SETTINGS_NAMESPACES, which can then be removed.Until then, at minimum it would help to document the whitelist requirement for third-party plugin authors — the runtime error message already points to the workaround, but the docs don't, and the upgrade-overwrite failure mode is hard to diagnose.
(Encountered with a local third-party plugin
dsh-llm-proxy; happy to provide more detail or a minimal repro repo.)All reactions