The `readDenyPaths` policy field shipped in the previous commit broke Linux confinement outright. bwrap has to create the `/dev/null` bind's mount point inside a tree its own profile has already made read-only, so it refused the entire confinement whenever the parent directory was absent — every host that has not stored a credential yet, including a fresh install: bwrap: Can't mkdir parents for /home/runner/.dsh/.env: Read-only file system which the executor correctly classifies as SANDBOX_UNAVAILABLE, so every confined bash call failed closed. Landlock cannot subtract from its own `/` read grant, so it reported `partial` enforcement on every confined call for a file it never hid, with no way to switch the denial off (schemastery fills an omitted array with `[]`, so empty and omitted were indistinguishable). A protection that breaks confinement where it works and misreports it where it does not is worse than a documented absence. Revert the field, both expressible backends, the enforcement downgrade, and the policy default; state the residue plainly in the credentials-local READMEs — file mode stops other OS users, not the model — and keep the OS-keychain provider recorded as the real answer. The narrower discipline stands: no surface hoists the credential document into `process.env`, and the model is never handed a resolved path to it.
credentials/
English | 中文
The credential capability seam, as three-package shape dictates (interface / implementation / consumers):
| Package | Role |
|---|---|
credentials/ |
Abstract ctx.credentials: branded CredentialRef references, per-operation resolve, UI-safe describe, fail-loud set/unset, the credentials/updated commit event |
credentials-local/ |
File/environment provider: the live process environment (read-only, wins) layered over $DSH_HOME/.env (writable, byte-preserving line edits, hot-reloaded) |
Configuration files carry references to secrets (apiKeyEnv: DEEPSEEK_API_KEY), never the secrets: the settings document stays safe to sync and render, and rotating a value touches no configuration. The LLM adapters are the first consumers — they resolve their reference once per model request, which is what makes a key stored moments ago reach the very next request without restarting anything.
The seam shape leaves room for keyring-, helper-command-, and KMS-backed providers.