Contributing
September 2, 2026 · View on GitHub
Welcome! dsh-coding-subscription-oauth is an open-source coding-subscription OAuth plugin for DeepSeek Harness. We appreciate issue reports, questions and pull requests. Read docs/00-project-rules.md first — it defines the release loop, versioning, commit/push hygiene and the publish vs local-only document split that every contribution must respect.
Code of Conduct
- Be respectful and constructive in issues, PRs and reviews.
- Only ever use coding subscriptions you own. The project does not support bulk accounts, quota resale, remote relay, paywall bypass or client impersonation — see the compliance note in
README.md.
Getting started
Primary verification is pnpm run check on Node matching .nvmrc (Cursor Cloud or an isolated checkout). Do not install into a shared operator DSH profile; use export DSH_HOME=/tmp/dsh-verify-* (or $HOME/.dsh-cloud) for plugin smoke tests.
Docker sandbox targets remain available for CI and for contributors who prefer a hermetic build. The tracked Dockerfile copies the filtered source into the image (never credentials), downloads dependencies in a dedicated stage, then runs project code with --network=none. Do not use privileged mode, credential or host-directory bind mounts, or the Docker socket. Tests use no published ports. The narrowly controlled interactive Web preview below is the only port-publishing exception; host networking remains prohibited unless its documented fallback conditions are all met.
pnpm install --frozen-lockfile
pnpm run check
Optional Docker:
docker build --target check --build-arg NODE_VERSION=22.19.0 \
--resource memory=3g --resource cpu-quota=200000 \
--tag test-dsh-coding-oauth:check .
docker build --target verify --build-arg NODE_VERSION=22.19.0 \
--resource memory=3g --resource cpu-quota=200000 \
--tag test-dsh-coding-oauth:verify .
The artifacts, package, inspect, and isolated-install targets cover generated lib/, the candidate tarball, release inspection, and a script-disabled consumer install.
Isolated Web preview
docker/run-preview.sh is the only supported interactive preview launcher. It builds web-preview offline from two auditable inputs: this checkout's committed lib/ and a BuildKit named context containing an installed @deepseek-ai/dsh program package (any audited version whose peer tree satisfies this plugin). Point DSH_INSTALL_DIR at that package directory, never at a DSH home/profile or any credential directory:
export DSH_INSTALL_DIR=/path/to/node_modules/@deepseek-ai/dsh
export DSH_PREVIEW_AUTHORITIES=review-host.example:17800
./docker/run-preview.sh
The launcher defaults to Docker bridge networking and 0.0.0.0:17800, checks the allowed high-port ranges, and enforces a non-root user, read-only root filesystem, dropped capabilities, no-new-privileges, CPU/memory/PID limits, isolated named volumes, and tmpfs runtime state. The DSH backend remains on a separate loopback-only high port. It does not mount, modify, restart, or validate against an existing host DSH. If provider endpoints require an outbound proxy, set DSH_PREVIEW_PROXY explicitly.
The launcher prints a command for reading the runtime-generated bootstrap token from the container. Append it to the printed local or allowlisted remote URL as ?preview_token=<token> using a private channel. The proxy exchanges it once for an HttpOnly, SameSite=Strict cookie and redirects to a token-free URL. Treat both the bootstrap URL and the isolated preview volumes as credentials; never paste either into logs, issues, commits, or chat.
Host networking is not a normal preview mode. It may be selected only after a minimal container proves ordinary Docker port publishing unavailable and the maintainer explicitly approves that one run. The explicit guard is:
DSH_PREVIEW_NETWORK=host \
DSH_PREVIEW_HOST_NETWORK_CONFIRMED=yes \
./docker/run-preview.sh
Even then, the launcher permits only the isolated high-port ranges and refuses occupied preview/backend ports. Stop the preview with the exact docker rm -f <container> command printed by the launcher. Remove its named volumes only after confirming they contain no OAuth credentials that need to be retained.
This repo also ships a Grok Build CLI (dsh-coding-oauth, legacy dsh-grok-build), an OAuth settings page, and verification scripts for a live deployment (verify:deployed / smoke:deployed). Those exercise real providers, so they are meant for maintainer/dev workflows, not for CI.
Development flow
- Open an issue describing the change (or link an existing one) so scope is agreed first.
- Branch from the default branch. Keep commits atomic and conventional — see Commits & pushes below.
- When you change a capability or add a doc, update
README.md(and the community translations added indocs/00-project-rules.md§2 if user-facing) and the relevant entries indocs/(public layer), and add a changelog entry underUnreleasedinCHANGELOG.md. - Run
pnpm run checkuntil green (or the Dockercheck/verifytargets if you prefer a hermetic sandbox), then commit that passing slice promptly (do not stack later work on an uncommitted green tree). - Push the branch as a version/milestone checkpoint and open a PR. Describe what changed and how it was verified. Keep the scope of local-only docs (
docs/local/) out of the PR unless you are a maintainer doing internal investigation.
Commits & pushes
History is part of the review. The maintainer counterpart — tags, clean-tree releases, changelog folding — lives in docs/00-project-rules.md §7.
Conventional, atomic commits
- Use Conventional Commits:
type(optional-scope): summaryin the imperative, about 50–72 characters. - Types:
feat:new capability / route / providerfix:bug fixdocs:documentation (publishable layer)test:testsrefactor:behaviour-preserving cleanupbuild:toolchain, packaging, or committedlib/artifactsci:CI workflowchore:process-only (including a release bump)
- Optional scopes such as
M1/M3or a module name are welcome when they help a reviewer. - One coherent concern per commit. Do not mix docs, build/toolchain and feature/fix work unless they are inseparable (a new capability that cannot be reviewed without its README/changelog note, or a source change that must ship with the
lib/it generated). - Do not rewrite published history. Amend or squash only on an unpushed local commit.
Before you commit
- Run
pnpm run check(or the Dockercheckthenverifytargets) and wait until green. Do not commit a failing tree. - Commit promptly once checks pass — do not leave a finished, verified change sitting uncommitted next to later work.
- Generated
lib/is a committed release artifact (git installs + the CIgit diff --exit-code -- libdrift gate). Rebuild it and include it in the same commit as the source or build-script change that produced it. Do not land stalelib/against newersrc/, and do not land alib/-only commit unless the only change is a verified rebuild with no source delta. - Never commit secrets, tokens, credentials, private keys,
.envfiles, host-specific paths, or local-only notes (docs/local/,reference/). Seedocs/00-project-rules.md§0.3.
Pushing
- Push the feature branch as a checkpoint at each version or milestone (for example after an M1/M2/M3 slice, or when a version-ready cut is green), not only when the PR is finished.
- Never force-push (
--force/--force-with-lease) without explicit maintainer approval. Default history is append-only, including on your own feature branch once it has been pushed. - Open the PR from a pushed checkpoint. Describe what changed and how it was verified.
Review & merging
- The maintainer may self-approve and merge; additional review is optional.
- A PR that changes public behaviour must not be merged without its README/changelog updates.
- Do not force-push
mainor a published release tag. Feature-branch force-pushes still need explicit approval (see above). - Maintainers run the release loop (
docs/00-project-rules.md§3–4 and §7) after merging a substantive change: clean working tree, bump version, annotated tagv<version>, publish to npm, and keep the GitHub milestone/release updated.
npm release verification
Maintainers publish the verified candidate manually using the handoff rules in
docs/00-project-rules.md §4.1. Tag pushes run .github/workflows/release.yml,
which only verifies that the tagged version and the latest dist-tag already
exist on the public npm registry before creating or updating the GitHub Release;
the workflow never publishes a second copy. A missing version or mismatched
latest tag fails the workflow and prevents the GitHub Release.
New DSH release smoke checklist
The plugin verifies an exact DeepSeek Harness BOM (compatibility/dsh-bom.json). A new DSH rc/stable is unverified by default, and lifecycle drift has broken activation before (#17), so run this checklist before moving the pin — in order, stopping at the first failure:
- Sandbox or isolated cloud first. Prefer
pnpm run checkon Node matching.nvmrcin Cursor Cloud / an isolatedDSH_HOME. Docker remains optional: edit the hardcoded@deepseek-ai/dsh@0.1.1-rc.2pin inDockerfile(dsh-installed/rc2-compatibilitystages — there is no build-arg) to the candidate DSH version, then build those targets green. This catches activation/lifecycle breakage without touching a real profile. - Real profile install (maintainer machine). Install the candidate tarball into an existing
dsh webprofile and restart that process once; the plugin must activate with onlywebServerrequired and no Cordis injection failures in the logs. - Settings surface. Settings → Coding OAuth renders all four tabs (Accounts / Gateway / Capabilities / About).
- Credentials survive. Every previously signed-in provider card (Grok / Codex / Kimi / Claude) still shows signed-in — an upgrade must never migrate or reset OAuth credential files.
- Live routes.
DSH_WEB_URL=http://127.0.0.1:3080 pnpm run verify:deployed(status route + catalog + registered routes), thensmoke:deployedwithDSH_RESTORE_PROVIDER/DSH_RESTORE_MODELset for one streamed reply per credentialed OAuth route. - Then move the pin. Update
compatibility/dsh-bom.json, thedsh.compatibilityblock inpackage.json, and the README compatibility notes in the same commit.
Reporting security issues
Do not open a public issue for a credential or account-safety problem. Follow the compliance/safety policy in README.md; for anything sensitive, contact a maintainer directly rather than pasting tokens or credentials anywhere.
Document layers reminder
- Publishable: root
README.md+ the community-language READMEs,INSTALL.md,CHANGELOG.md,LICENSE,NOTICE,docs/00-project-rules.md,docs/02-architecture.md+docs/02-architecture.zh-CN.md, and other genericdocs/files. These ship to npm and git — keep them privacy-free. - Local-only:
docs/local/andreference/are git-ignored and never shipped. Do not reference them from publishable docs.
If you are not sure whether a detail is publishable, keep it in the local-only layer or ask a maintainer.