GuoMonth/dsh-multi-tenant--packages-multi-tenant10

dsh-multi-tenant

One-command local DeepSeek Harness workbench and SDK for Principal-isolated native DSH Hosts.

包名
dsh-multi-tenant
版本
0.8.0
许可证
MIT
最近更新
2026年9月12日

安装

此插件尚未提供可验证的 bundle,或兼容性检查未通过。请先阅读仓库说明。 阅读完整 README ↗

dsh-multi-tenant

简体中文 · Releases · Changelog

Give each signed-in user their own native DeepSeek Harness environment. Users keep DSH's chat, workspaces, files, presets and subagents, while the platform separates their data and execution from other users.

Use the CLI to try a complete local workbench, or the SDK to connect independent DSH Hosts to your existing authentication system. This project starts and manages DSH; it is not a multi-user plugin installed inside a shared DSH Host.

Try it with one command

Requires Node 22.19 or newer 22.x, or Node 24+, and running local Docker with Linux containers. No manual DSH installation, image build or API key is needed.

npx -y dsh-multi-tenant@0.8.0 start

This guide targets 0.8.0. Check availability with npm view dsh-multi-tenant@0.8.0 version; if unavailable, use the source verification flow. Older 0.7.1 has no CLI. After publication, @latest also selects the current stable release.

Choose Alice or Bob in the browser to enter their own native DSH workbench. The deterministic demo model reads samples, creates files and delegates to subagents; real AI requires provider credentials in native Settings. Ctrl-C stops the workbench and retains data. Linux amd64/arm64 have recorded native verification; macOS/Windows Docker Desktop remains experimental.

Startup, management and troubleshooting

Use with an AI coding agent

Give your coding agent this prompt:

Read https://raw.githubusercontent.com/GuoMonth/dsh-multi-tenant/main/packages/multi-tenant/AI.md,
check the current npm version and my local environment, then help me start and verify dsh-multi-tenant.
Before changing repository code, read the root AGENTS.md and identify the relevant checks.

The AI project guide covers evaluation, SDK integration, source navigation and troubleshooting. AGENTS.md provides repository development instructions. The npm package includes AI.md; prefer the bundled guide when working with an installed version.

Where it fits

ScenarioWhat you gainWhat your platform supplies
Internal developer workbenchEach employee uses native DSH with their own history, files and MCP configurationCompany login, TLS, private storage and runtime deployment
Multi-tenant applicationUsers with the same name in different tenants still receive separate environmentsTrusted tenant/user identity, domain hostnames and resource policy
Native DSH integration and evaluationReuse the official Web and preset/subagent behavior without maintaining a second chat UIA pinned DSH runtime, reviewed profiles and your chosen runtime provider

A typical visit is: sign in → resolve the user's domain → start or reuse its DSH Host → open native DSH Web. A browser reconnect returns to the same domain; it does not create a new Host for every request or session.

What the platform SDK provides

  • A domain directory keyed by (tenantId, principalId), keeping identity and desired state across platform restarts.
  • Deduplicated Host startup, generation checks, suspension/revocation, bounded shutdown and verified recovery after a coordinator crash.
  • Authenticated HTTP/WebSocket ingress for native Web, preserving native messages, tools and file transport. Native login cookies remain private to the platform.
  • A constrained Linux Docker reference provider and a trusted-development local process provider, plus public interfaces for deployment-specific runtimes.
  • Native preset/MCP/subagent composition, exercised through installed-package integration tests rather than a custom Agent facade.

Decide whether this version suits your deployment

This is a developer integration package. Docker uses bridge networking by default, allowing external model APIs and remote MCP. Set network: 'none' when offline operation is needed. Starting with 0.7.1, bridge replaces the offline default in 0.7.0. Login/SSO, TLS, domain provisioning, quotas and operational monitoring are responsibilities of the embedding platform; the CLI’s local demo identities do not provide account management or a hosted service.

The security boundary is the user within a tenant, not each project or conversation. Two workspaces belonging to one Principal are not promised to be mutually confidential. Native permissions, tool filters, stop/archive/delete and preset selection retain native semantics. Team-shared domains, project ACLs, cross-user session sharing, automatic idle eviction and multi-machine scheduling are outside this version.

Independent Hosts have a fixed memory and startup cost; an inactive browser can still have background work. Choose resource limits and when to stop domains from your workload. Platform administration, authentication secrets and the Docker socket must stay outside every native Host.

Upgrading from 0.7.1 to 0.8.0: Existing SDK APIs are unchanged. The new CLI uses separate control state and image-pinned Docker volumes; it does not import platform data automatically.

Upgrading from 0.7.0: Existing domain data and integration APIs retain their structure. The network default changes: explicitly set network: 'none' before upgrading if offline restrictions must remain. To adopt the included Dockerfile, rebuild the image, stop existing Hosts, update the image ID and restart.

Upgrading from 0.5.x or earlier: 0.7.0 changes the integration architecture and public API. The shared-process Cordis plugin, per-Agent resource API and custom panel are removed. Start with a new platform directory, replace the integration code and preserve old data separately; there is no automatic legacy-data migration. The 0.6.0 source milestone was not published to npm.

SDK integration entry

npm install dsh-multi-tenant@0.8.0
# Check the installed platform API without Docker or an external model:
node node_modules/dsh-multi-tenant/examples/native-domains/smoke.mjs

The smoke uses a simulated runtime and starts no native DSH Host. To give users a real workbench:

  1. Prepare the pinned native runtime image and per-domain profile described below.
  2. Connect your login/IdP adapter to trusted tenant/user identity and assign each domain a separate hostname.
  3. Build the included runtime image. Use default bridge networking for model/MCP access, or explicitly select network: 'none' for offline workloads.
  4. Embed the ingress/coordinator, provision private data, and implement shutdown, suspension and recovery in your platform.

For a complete keyless native Web demonstration from source, install the repository and scripts/native-host-probe dependencies, then run pnpm probe:isolated with Docker and Chromium. See the reproducible native proof. This is a verification environment, not a public login service.

Authority contract

  • Different Principals, including the same principal name in different tenants, receive separate data and execution environments.
  • Sessions and workspaces inside a Principal's domain are not independent authorization domains. Native permissions, tool filters, stop/archive/delete and preset selection retain native semantics; they are not root read ACLs.
  • Platform administration, authentication secrets, the domain directory and Docker socket stay outside every native Host. Native settings and credentials belong only to that domain.
  • The platform is trusted code. Do not mount its API in the native Web server or derive domain identity, image, profile paths, runtime endpoints or origins from browser parameters.

SDK installation and prerequisites

npm install dsh-multi-tenant@0.8.0

To test an unreleased checkout, build and install its tarball with pnpm --filter dsh-multi-tenant pack.

The coordinator requires Node 22.19 or Node 24+. The public SDK reference providers target Linux; the CLI uses a separate internal provider. DockerRuntimeProvider requires a local Docker engine and a prebuilt immutable image containing DSH 0.1.5-rc.2, pinned source fb2c4b9e698e30edb738bca4cf0618587db7d203. Run the coordinator as a non-root user with Docker access; the reference runtime UID/GID must match that user so both sides can access the private control files. It does not download DSH into the platform process. TypeScript consumers should install @types/node and include node in compiler types.

Docker defaults to --network bridge; set network: 'none' for --network none. No ports are published and the native server listens on container loopback. Bridge allows access to reachable host/LAN services and other containers on the same bridge; it is not a network tenant boundary. Apply deployment firewall policy when network separation is required. External API credentials remain necessary. The local process provider is for trusted development, not hostile workloads.

Embed in an authenticated server

This is an integration fragment: your application supplies authenticator and trustedDomainOrigins.

import {
  SQLiteDomainRepository, DomainRuntimeCoordinator,
  DockerRuntimeProvider, createDomainIngress, DSH_RUNTIME_VERSION,
} from 'dsh-multi-tenant'

const directory = new SQLiteDomainRepository('/srv/dsh/control')
const runtime = new DomainRuntimeCoordinator(directory,
  new DockerRuntimeProvider({
    directory: '/srv/dsh/runtime',
    image: 'sha256:',
    profileDirectory: domainId => `/srv/dsh/profiles/${domainId}`,
    uid: process.getuid(), gid: process.getgid(),
  }), DSH_RUNTIME_VERSION, 45_000, 20_000)

const ingress = createDomainIngress({
  authenticator, // your trusted login/IdP adapter, implementing DomainAuthenticator
  runtime,
  originFor: owner => trustedDomainOrigins.get(JSON.stringify([owner.tenantId, owner.principalId])),
})
ingress.server.listen(8080, '127.0.0.1')

Provision a profile before ensure(owner) can start its Host. directory.resolve(owner) provides its opaque domain ID. Supply authenticator.authenticate(request, signal) returning { owner, signal } only after authenticating the user; abort the returned signal on logout/expiry to close existing streams. MemoryDomainSessions is an in-memory reference adapter: issue(owner) is a trusted server-side operation, never an unauthenticated login endpoint. Tokens belong in Secure, HttpOnly, host-only cookies with Path=/ and an appropriate SameSite policy; the adapter does not emit cookies or implement an IdP.

Use distinct hostnames (not only different ports) and trusted TLS termination: browser cookies are not isolated by port. Preserve the validated external Host/Origin through the reverse proxy; the ingress ignores client forwarding headers. All native HTTP and WebSocket paths share admission. An additional CSP limits frame ancestors to the same origin, preserving any native CSP; cross-origin iframe embedding is not supported. Native browser cookies remain inside the platform; response cookies are not exposed. Platform management has no HTTP route here. The embedding application owns graceful shutdown; always attempt both ingress.close() and runtime.close() and retain cleanup errors for repair/retry. A reusable embedding example is in examples/native-domains/platform.mjs.

Runtime image and profile contract

Build the included runtime image

From source (after npm installation, substitute node_modules/dsh-multi-tenant for the package path):

docker build -f packages/multi-tenant/runtime/Dockerfile -t dsh-domain-runtime:local packages/multi-tenant
docker image inspect dsh-domain-runtime:local --format '{{.Id}}'

Pass the resulting sha256:... as the provider image, then provision each domain profile below. The Dockerfile and dependency lock ship in the npm package, with explicitly labeled CLI demo model/MCP assets and no real credentials. SDK profiles do not enable these demo features automatically. The base image digest and npm dependencies are pinned; OS tools take current Debian repository security updates, so use the final image ID as deployment identity.

Includes Bash, Git/SSH client, curl/wget, jq, ripgrep, text/archive utilities, Python 3/venv/pip, C/C++ build tools and the base image's Node/npm. Account-dependent AI CLIs, browsers and additional language SDKs belong in project-specific derived images. The runtime root is read-only: install Python packages into /domain/.venv and Node dependencies into projects under /domain. /tmp is noexec; set TMPDIR to a writable directory under /domain when build/install tools need executable temporary files. The provider overrides the image's default user with the configured non-root UID/GID.

new DockerRuntimeProvider({
  // ...image, directory, profileDirectory, uid, gid
  network: 'none', // Optional offline mode; omitted means bridge.
})

The reference provider launches /opt/dsh/node_modules/@deepseek-ai/dsh/lib/bin.js --profile web --patch /profile/runtime.patch.json with Node --expose-internals for the pinned native Loader, loopback port 3081 and no browser opener. Install the exact native runtime and copy the exported dsh-multi-tenant/native/runtime-control.mjs asset into the image at /opt/dsh/runtime-control.mjs. Add this row through the native profile patch:

[
  { "id": "web-runtime", "config": { "printUrl": false, "openBrowser": false } },
  { "insert": [{
      "id": "domain-runtime-control",
      "name": "/opt/dsh/runtime-control.mjs",
      "config": { "runtimeManifest": "/opt/dsh/node_modules/@deepseek-ai/dsh/package.json" }
  }] }
]

The asset waits for public appReady and uses connection.authenticatedUrl, without private scope rebinding or a replacement controller. It is a native Host asset; do not load it into the platform.

Data mounts at /domain, the trusted profile at /profile read-only, and the narrow readiness/transport directory at /control. The native Host has no platform credentials or management socket. Runtime root is read-only, UID/GID non-root, capabilities dropped, no-new-privileges enabled. Defaults: 1 GiB memory, 1 CPU, 160 PIDs and 128 MiB temporary storage. These are configurable reference limits, not measured production capacity. Existing platform directories must have private ownership/permissions. The original socket pathname must fit Linux's 107-byte limit. Connections use a pinned socket inode, so a workload cannot redirect the platform through a substituted symlink. Readiness refuses symlinks/nonregular files and is bounded to 16 KiB.

Native user settings, user-installed domain plugins and domain credentials are inside this execution boundary. They may affect every session in that Principal. Do not put platform secrets in native environment variables, profiles, credentials or mounts. Image/network updates require a new reviewed runtime and regression tests; full native UI reuse does not grant platform administration.

Stop, revoke, rotate and recover

  • runtime.stop(id) invalidates current connections, stops the Host and leaves the domain enabled. A later admission starts a new generation.
  • runtime.setDesired(id, 'suspended') persists suspension before stopping. New admissions fail until explicitly enabled.
  • runtime.setDesired(id, 'revoked') is terminal and persists across restart. It revokes domain access, not retained data or credentials at an external service. Data retention/deletion is an explicit platform operation after verified stop.
  • For domain capability/credential rotation: suspend, aw