Skip to content

Releases: GooDAnDReaDY/dsh-key-rotation

v0.8.72 [DSH v0.2.1-rc.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 23 Oct 12:35

Release v0.8.72 [DSH v0.2.1-rc.2]

Security release resolving issue #516.

Why this release

Addresses a security vulnerability where LAN/Tailscale clients proxied to loopback by dsh-lanmode without an Origin header could bypass source authorization on mutating endpoints, and makes /auto-import fail closed on invalid body payloads.

What changed

  • Fail-closed write-origin guard (#516): Mutating HTTP methods (POST, PUT, PATCH, DELETE) without an Origin header are rejected with 403 Forbidden unless positively identified as the Desktop shell (@deepseek-ai/dsh-desktop/ in User-Agent AND dsh-auth- in Cookie) or a matching same-origin Referer.
  • Fail-closed /auto-import (#516): Invalid JSON returns 400 Bad Request instead of defaulting to importing all discovered keys. Auto-import requires an explicit refs array or all: true. The Settings card client explicitly sends { all: true }.
  • Desktop Shell identification: Extracted isDesktopShellRequest(req) in lib/pool.js matching official Desktop renderer forwardWebRequest behavior.
  • Test suite: Full regression coverage added (test/issue-516-write-origin-guard.test.mjs, 958/958 passing tests).

Verification

  • npm test: 958/958 pass, 0 fail
  • npm run check: 205 JS files syntax clean
  • preflight.sh: FAIL=0
  • Package size: 232 kB packed (limit 262 kB)

Commit correspondence

  • Gitea commit: 5dcfbc0
  • GitHub mirror commit: 2e8cfe6cb867ff5040caee38f9767bcc2b6ae15d

v0.8.68

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 19 Oct 09:32

Release v0.8.68

v0.8.67 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 19 Oct 09:03

Features

  • Full Pool Configuration Export & Import (#504):
    • Masked export: exports topology and pools with masked credentials (sk-...cdef) and hidden webhook secrets, safe for bug reports and sharing.
    • Full backup export with AES-256-GCM encryption: optional passphrase encrypts configuration with PBKDF2 (100,000 iterations) using standard node:crypto.
    • Config import route POST /dsh-key-rotation/config-import: supports file upload, raw JSON, or encrypted payload with passphrase decryption.
    • Diff preview mode: dryRun: true returns summary of created/updated/removed providers and keys count before applying.
    • Interactive UI in Settings card: modal drawers for Export (masked vs full, optional passphrase) and Import (file upload, merge vs replace modes, diff preview, apply).
  • Quick Key Actions in Chat Header Popover (#499):
    • Extended KeyRotationHeaderChip popover: displays active provider and key tail (...abcd) for each configured pool.
    • Interactive inline action buttons:
      • ⏭️ Skip: advances active key cursor to the next healthy candidate in the pool without leaving chat.
      • 🔄 Reset: immediately resets failure counts, cooldowns, and circuit breaker for the active provider.
      • ⏸️ Pause: toggles pause state on the currently active key for immediate fault isolation.
    • Endpoint POST /dsh-key-rotation/quick-action: secure loopback-validated operational route executing skip, reset, and pause commands with audit telemetry events.

Commits & Verification

  • Gitea commit: 1f85ba151805607a79bef510eff7b2b6d8c698e8
  • GitHub mirror: e8a92cf40ead95030cf7d7e16764f471c37a8040
  • Tests: 934 passing, Preflight: FAIL=0 WARN=3.

v0.8.66 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 19 Oct 08:22

Features

  • Dynamic Reset Scheduler Based on Rate-Limit Headers (#498):
    • Exact cooldown alignment: parses upstream retry-after, x-ratelimit-reset-*, and anthropic-ratelimit-*-reset headers upon rate-limit failures, setting precise cooldown failedUntil = now + dynamicCooldownMs (+250ms safety jitter, bounded by maxCooldownMs) with resetReason = 'header'.
    • Immediate unref recovery timer: schedules an exact unref setTimeout wake-up for the penalised key right when the upstream window rolls over.
    • Exposes resetReason and headerResetMs in /dsh-key-rotation/status and WebUI countdown badge.
  • Upstream Balance Inspector & Credit Tracking (#495):
    • Multi-provider balance checker (lib/balance-inspector.js): queries live account balances and remaining credits for DeepSeek, SiliconFlow, OpenRouter, and OpenAI.
    • Balance ops route GET/POST /dsh-key-rotation/balance (lib/ops-balance.js): queries cached balances or triggers immediate live balance inspection across provider keys.
    • Pre-emptive empty balance protection: keys with confirmed zero balance enter a soft pause (EMPTY_BALANCE_PAUSED), auto-resuming when refreshed with positive balance.
    • Persistent balance state: cached in pool.state.balances and persisted via lib/persistence.js.
    • WebUI integration: interactive Check Balances action button in provider footer and real-time balance badge pills on key cards.

Commits & Verification

  • Gitea commit: 933589eee5d59d794b770fbeea72d5b26833bbde
  • GitHub mirror: 94259fcf4ce58391790ec2edf78409296e42d07c
  • Tests: 927 passing, Preflight: FAIL=0 WARN=3.

v0.8.64 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 18 Oct 16:24

What's Changed

  • Permanent Auth Pause & Granular Error Policies (#501):
    • Differentiated error actions: upstream authentication failures (HTTP 401, 403, invalid_api_key, unauthorized) immediately place the failing key into a permanent auth pause state (pausedRefs.add, pauseReasons.set('AUTH_FAILURE_PAUSED'), failedUntil: Infinity, KEY_AUTH_PAUSED).
    • Dead or unauthorized keys are stopped from waking up repeatedly every 60s cooldown, preventing repetitive broken dispatches.
    • Granular soft error handling: transient infrastructure drops (HTTP 502, 503, 504, TIMEOUT, socket drops) receive a short flat cooldown (<=10s) without doubling exponential penalty counters or incrementing toward recoverable quarantine.
    • Successful Test Matrix / manual re-test probe automatically unpauses the key.
  • Automatic Model Capabilities Discovery & Routing (#500):
    • In lib/sandbox.js (probeModels), parse and return array of supported model IDs from upstream /models (body.data.map(m => m.id)).
    • Discovered model capabilities are cached per key (pool.state.modelCapabilities: Map<ref, Set<modelId>>).
    • In lib/resolver.js and lib/rotate.js, filter candidate keys for a requested model so prompts are never dispatched to a key that doesn't support that model (e.g., DeepSeek-R1 vs DeepSeek-Chat V3). Keys not yet probed are optimistically allowed.
    • Atomic persistence across restarts: pausedRefs, pauseReasons, and modelCapabilities serialize and restore atomically via lib/persistence.js.
    • Settings Card UI: Display Auth Paused (401/403) status badge and discovered model count badges (🤖 Nm) on configured keys.

Full Changelog: v0.8.63...v0.8.64

v0.8.63 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 16 Oct 13:27

What's Changed

  • feat(ui): add configurable switch to disable chat header status chip (#493 / GitHub #25)
    • Adds showChatHeaderChip boolean setting (default true) in SettingsSchema and runtime configuration.
    • Adds user-facing toggle in Settings card ("Chat Header Status Chip" / "聊天头部状态按钮") under rotation settings.
    • KeyRotationHeaderChip (conversation.session.header.utilities) dynamically checks settings snapshot and health status, cleanly returning null when disabled to free up conversational header toolbar space.
    • Additive field showChatHeaderChip exposed in /dsh-key-rotation/status and /dsh-key-rotation/health.

Full Changelog: v0.8.62...v0.8.63

v0.8.62 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 16 Oct 11:57

Summary

Release v0.8.62 adds session-aware sticky routing affinity to protect prompt cache hit rates across parallel chat sessions and subagents (#489), a 1-click Test Matrix dashboard for batch probing all configured keys (#490), and zero-config pool auto-discovery from ~/.dsh/.credentials.yaml and environment variables (#491).

What Changed

  • Session-Aware Sticky Routing Affinity for Prompt Caching (#489):
    • Enhanced sticky routing strategy with LRU session affinity (pool.state.sessionSticky, capped at 500 active sessions).
    • Parallel DSH chat sessions or multi-agent subtasks retain dedicated sticky keys based on sessionId (options.sessionId / options.session / options.metadata.sessionId), preventing cross-session cache evictions and maximizing prompt prefix cache hit rates for Anthropic, DeepSeek, and OpenAI.
    • Graceful failover to the next healthy candidate if a session's pinned key is in cooldown or quota-exhausted; automatic eviction from session map on error.
  • 1-Click Test Matrix Dashboard (#490):
    • Added /dsh-key-rotation/test-matrix endpoint in lib/ops-test.js supporting batch validation of all configured keys across all pools with bounded concurrency (5 workers) and latency tracking.
    • Added "⚡ Test All Keys" action button in the WebUI Settings Card with an interactive results modal displaying operational key status, latency in milliseconds, and error details.
  • Zero-Config Pool Auto-Discovery & 1-Click Import (#491):
    • Added /dsh-key-rotation/discover and /dsh-key-rotation/auto-import endpoints in lib/ops-keys.js.
    • Automatically scans ~/.dsh/.credentials.yaml and environment variables for unconfigured provider keys matching standard patterns (DEEPSEEK_API_KEY, OPENCODE_GO_API_KEY_*, OPENAI_API_KEY, GROQ_API_KEY, etc.), excluding keys already assigned to rotation pools.
    • Added smart auto-discovery banner to the Settings Card with 1-click import into provider pools.
  • Verification:
    • Added dedicated test suite test/features-0862.test.mjs.
    • All 897 tests passing (pass 897, fail 0), preflight FAIL=0 WARN=3.

Artifacts & Correspondence

  • npm: @goodandready/dsh-key-rotation@0.8.62
  • Gitea SHA: a6aa2aaf7c284a2ff4c0142a8c57ecee158df75a
  • GitHub mirror commit: 3a16cd9583e7d5c08ac6133112ffb224b25a4cf0

v0.8.61 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 15 Oct 18:05

Summary

Release v0.8.61 fixes false calendar quota lockouts triggered by transient upstream rate limiting/RPM/TPM throttling (#24), introduces the new sticky key routing strategy to preserve prompt cache hit rates on LLM providers (#23), and enhances self-healing for quarantined keys.

What Changed

  • Prevent Transient Rate Limit Deadlocks from Calendar Quota Locks (#24):
    • Upstream errors returning transient 429, RPM/TPM exhaustion, or concurrency limits (such as SenseNova {"message":"rpm exhausted","type":"quota_exceeded_error"} or {"message":"inference exceeds tpm/rpm limit","code":"insufficient_quota"}) are now classified as isRateThrottling and excluded from isQuota.
    • Transient rate limits receive standard short backoff (cooldownMs with jitter) rather than being locked out until next UTC midnight.
    • Cleared pool.state.quotaWindows in recordSuccess upon first successful request.
    • Extended background autoUnbreakBrokenKeys and proactive health probing to probe keys with calendar quota locks, restoring healthy keys immediately upon receiving 200 OK from upstream.
    • Added INSUFFICIENT_QUOTA and present-tense regex matches to switchable error classification.
  • Sticky Key Routing Strategy to Preserve Prompt Caching (#23):
    • Added 'sticky' routing strategy option in settings and provider configurations.
    • In sticky mode, the resolver retains the same active key across consecutive requests as long as it remains healthy, maximizing prefix prompt cache hit rate on providers that cache per API key (Anthropic, DeepSeek, OpenAI).
    • Automatically fails over to the next healthy key in the pool if the sticky key experiences an error or cooldown, then sticks to the new key.
    • Added UI dropdown selection in the Key Rotation Settings Card with English and Chinese localizations.
  • Verification:
    • Added dedicated test suite test/issues-23-24.test.mjs verifying sticky key persistence, failover, quota lock avoidance, and self-healing.
    • All 891 tests passing (pass 891, fail 0), preflight FAIL=0.

Artifacts & Correspondence

  • npm: @goodandready/dsh-key-rotation@0.8.61
  • Gitea SHA: f3e06e3090b63de1d5555cff9bca623013de9c5e
  • GitHub mirror commit: e6adae9d5401eeed02432031f5256cecf68cc374

v0.8.60 [DSH v0.2.1-alpha.2]

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 14 Oct 18:19

Summary

Release v0.8.60 expands the @deepseek-ai/dsh-llm peerDependency range to admit DSH Core 0.2.1-alpha.2, allowing the harness to load and run key rotation without skipping the plugin.

What Changed

  • PeerDependencies Expanded for DSH Core 0.2.1-alpha.2:
    • Range updated to ^0.1.7-rc.2 || >=0.2.0-rc.1 <0.2.1-0 || >=0.2.1-alpha.1 <0.2.2-0.
    • Fixes plugin skip during DSH core startup where evaluatePluginCompatibility marked the plugin disabled due to the <0.2.1-0 prerelease boundary.
    • Verified backward compatibility with 0.2.0-rc.2, 0.2.0, and 0.1.7-rc.2.
    • Upper bound <0.2.2-0 guards against untested 0.2.2 line.
  • Acceptance Verification:
    • Added dedicated test suite test/dsh-llm-021-alpha2.test.mjs verifying compatibility rules, service launch on 0.2.1-alpha.2 runtime, 429 key failover rotation, and pool status reporting.
    • All 885 unit and integration tests passing (FAIL=0).

Artifacts & Correspondence

  • npm: @goodandready/dsh-key-rotation@0.8.60
  • Gitea SHA: a7582d56dd08eb1cdd0fbb74e6f8e661c646039b
  • GitHub mirror commit: 65b5f41fb5cabf6d090df2a8124e344b56430384

v0.8.59

Choose a tag to compare

@GooDAnDReaDY GooDAnDReaDY released this 14 Oct 17:33

Refactored & Cleaned

  • Legacy Settings Registration Removed (#482):
    • Deleted dead legacy settings.register branch in lib/index.js, standardizing configuration liveness on createConfigReader.
  • Dead Subscriptions & Settings Fallbacks Removed (#482):
    • Removed dead ctx.on('config') subscription in lib/config-compat.js.
    • Removed unreachable legacy settings.get fallback in createProviderProfilesReader in favor of standard settings.describe.
  • Test Harness Synchronization (#482):
    • Updated test fixtures for modern descriptor caching and multi-listener lifecycle events.

Gitea commit: d88675dde4b6b3e7804f1f8eb2f1ccbba2cb2793
Mirror commit: 8bee2556e5e127a3fc849b962359fefef1aa5315