Bundle
@perrylink/dsh-plugin-kit
Shared zero-runtime-dependency toolkit for PerryLink DSH plugins: a pluggable Provider registry seam, fail-closed approval and adaptive session-event gates, mechanical verify scripts, shared sanitize/pricing/judge modules, and a new-plugin skeleton.
- Source
- PerryLink
- License
- Apache-2.0
- Updated
- Updated 2 days ago
Readme
# @perrylink/dsh-plugin-kit
- **1024 store channel**: `npm i -g dsh1024` once, then `dsh1024 plugin --profile web add @perrylink/dsh-plugin-kit` (counts toward the [deepseek1024.com](https://deepseek1024.com) install ranking).
[](https://www.npmjs.com/package/@perrylink/dsh-plugin-kit)
[](LICENSE)
Shared **zero-runtime-dependency** toolkit for the PerryLink DSH plugin
repositories. The per-project audit found 20+ of the 33 plugins hand-rolling
the same Provider seam and duplicating the same sanitize/pricing/verdict
shapes, so this package extracts all of it — the pluggable Provider seam, the
fail-closed approval and adaptive session-event gates, the mechanical verify
scripts, and the shared sanitize/pricing/judge pure modules — into one
ESM + TypeScript package.
## Compatibility
- **DSH harness**: the kit imports nothing from `@deepseek-ai/*` at runtime.
`@deepseek-ai/cordis` (`^4.0.2`), `@deepseek-ai/schemastery` (`^3.18.2`),
and the `@deepseek-ai/dsh-*` packages are **optional** peer dependencies in
the `>=0.1.2-rc.1 <0.2.0` band the PerryLink plugin repos share; they exist only for type
interop. Verified 2026-09-06 against the dsh-v0.1.3-alpha.1 master checkout
(full gate chain + profile install smoke).
- **Node**: `^22.19.0 || >=24.0.0`, ESM only.
- **Wire compatibility**: names and shapes mirror `dsh-mask` (sanitize),
`dsh-budget` (pricing), and `dsh-auto-review` (judge and the
`fallbackPolicy` vocabulary), so migration is mechanical.
## What you get
- **Zero runtime dependencies** — the pure core (`seam`, `gates`, `shared`)
is browser-safe.
- **ESM + strict TypeScript** — JSDoc contracts on every module; `strict`,
`noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`.
- **Fail-closed and adaptive gates** — approval never defaults to a grant;
session-event appends degrade gracefully on hosts that reject unknown event
types.
- **A new-plugin skeleton** — `template/` with `cordis.yml`, a three-role
`src/index.ts` (Service Definition / Provider / Consumer), a test, and the
shared Renovate preset.
## Quick start
From npm:
```sh
pnpm add @perrylink/dsh-plugin-kit
```
From git (the `prepare` script builds `lib/` using only production
dependencies):
```sh
pnpm add github:PerryLink/dsh-plugin-kit
```
Replace a hand-rolled registry in one step:
```ts
import { ProviderRegistry } from '@perrylink/dsh-plugin-kit/seam'
const registry = new ProviderRegistry<Detector>({
default: { name: 'regex', impl: new RegexDetector() },
})
ctx.effect(() => registry.register('ner', new NerDetector()))
const active = registry.use('ner') ?? registry.use()
```
## Install & uninstall
Install is `pnpm add` (see Quick start). Remove with:
```sh
pnpm remove @perrylink/dsh-plugin-kit
```
Nothing registers global state: uninstall is exactly the reverse of install.
## Configuration
No runtime configuration: the gates and helpers are pure functions. The only
configuration surface is `cordis.patch.yml`, the bundle-patch layer shipped
for harness profile composition; it mounts no plugin row (the kit is a
library) and documents how consuming plugins add their own rows.
## Tools & surfaces
| Subpath | Purpose |
|---|---|
| `seam` | `ProviderRegistry<T>` — reversible, fail-loud named provider registry. |
| `gates` | `applyFailClosed`; `makeEventGate` / `maybeAppendSessionEvent` / `probeIgnorableAppend`. |
| `shared` | `sanitize` (`Stripper`, `redactText`, `redactMapping`, `sanitizeText`, `sanitizeUrl`), `pricing` (`BUILTIN_PRICES`, `estimateUsageCost`, `tokenCarbon`, `latencyStats`, `formatMoney`, `formatTokens`), `judge` (`parseVerdict`, `VERDICT_SCHEMA`, `riskExceeds`). |
| `verify` | Mechanical CI gates (`verify-license`, `verify-readme-languages`, `verify-seam`) with a `VerifyReport` and a non-zero-exit CLI: `node lib/verify/cli.js all .` |
| `template/` | New-plugin skeleton (`cordis.yml`, three-role plugin, test, README, `renovate.json5`). |
| root barrel | Re-exports all of the above. |
## Permissions & data
The kit performs no I/O, no network access, and no subprocess spawns on its
own. `Stripper` keeps placeholder→original mappings in memory only, and
`stats()`/`redactMapping()` never emit plaintext; a consumer that persists a
mapping owns that decision and its storage permissions.
## Security boundaries
- `sanitize`/`redact*` are **display hygiene**, not a security boundary: they
reduce leakage into logs and results, they do not authenticate or authorize.
- Approval gates are fail closed by default (`rejected`); the only grant path
is an explicit `allow-once` opt-in.
- Session-event appends the host refuses are skipped, never retried in a way
that could break session resume.
- Report vulnerabilities via GitHub Security Advisories — see `SECURITY.md`.
## Known limitations
- Hosts whose `Session.append` third argument is a `SurfaceIntent`
(`0.1.2-rc.1`) throw `validateNext` on the ignorable-envelope probe; the
gate degrades to skip-unknown, so audit events are dropped (fail closed)
rather than logged on those hosts.
- 0.1.2-rc.1 (adapted 2026-09-02): the session envelope keeps its ignorable field for stored-log read compatibility only - Session.append still cannot stamp it, so audit-gate behavior is unchanged.
- The kit ships no browser UI half; it is a library consumed by the Host (and
optionally Client) halves of other plugins.
## Development
```sh
pnpm install
pnpm run typecheck # tsc --noEmit
pnpm run typecheck:ci # CI face: tsc -p tsconfig.ci.json --noEmit
pnpm test # vitest unit tests
pnpm run build # emit lib/ + declarations (also run by prepare)
pnpm run verify:self-contained
pnpm run verify:artifacts
```
## Topics
This repository is also the maintenance hub for the 33 plugin repos:
`scripts/sync-peer-range.mjs` re-pins the shared peer band across all repos in
one command, `renovate/default.json5` is the shared Renovate preset every repo
extends, `.github/workflows/npm-publish.yml` is a reusable tag-triggered
publish workflow (needs only an `NPM_TOKEN` secret), and `data/repos.json` is
the ecosystem registry consumed by the portal. See
[docs/ecosystem-tooling.md](docs/ecosystem-tooling.md).
Keywords: dsh, dsh-plugin, deepseek-harness, deepseek, cordis, perrylink,
provider, seam, approval, sanitize, pricing, judge.
## Contributors
Maintained by [PerryLink](https://github.com/PerryLink) with contributions
from the DSH plugin ecosystem.
## License
Apache-2.0 — see [LICENSE](LICENSE).
Install
dsh plugin --profile web add github:PerryLink/dsh-plugin-kit
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install perrylink-dsh-plugin-kit from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.