@goodandready/dsh-tts 0.4.20 → 0.4.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  Notable changes to `@goodandready/dsh-tts`.
4
4
 
5
+ ## 0.4.22
6
+
7
+ ### Fixed
8
+ - Enforce fail-closed `isTrustedSettingsRequest(req)` validation on `/stream`, `/pending`, and `/speak` HTTP handlers to reject untrusted cross-site requests with 403 Forbidden (#136).
9
+
10
+ ## 0.4.21
11
+
12
+ ### Fixed
13
+ - Settings no longer wait on the removed settingsScope service. The client uses configForms (#137).
14
+
5
15
  ## 0.4.19
6
16
 
7
17
  ### Fixed
@@ -15,10 +15,10 @@
15
15
 
16
16
  const ctx = props && props.ctx
17
17
  const scope = React.useMemo(() => {
18
- const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.settingsScope)
19
- if (!s || !s.bind) return null
18
+ const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.configForms)
19
+ if (!s || !s.get) return null
20
20
  try {
21
- return s.bind({ namespace: NS })
21
+ return s.get(NS)
22
22
  } catch (_) { /* settings scope binding failed */
23
23
  return null
24
24
  }
@@ -206,7 +206,7 @@
206
206
  ))
207
207
  }
208
208
 
209
- exports.inject = ['slots', 'settingsScope', 'locale']
209
+ exports.inject = ['slots', 'configForms', 'locale']
210
210
  exports.apply = function apply(ctx) {
211
211
  registerSettings(ctx)
212
212
  registerSpeaker(ctx)
package/lib/client.js CHANGED
@@ -1379,10 +1379,10 @@ async function pollPending() {
1379
1379
 
1380
1380
  const ctx = props && props.ctx
1381
1381
  const scope = React.useMemo(() => {
1382
- const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.settingsScope)
1383
- if (!s || !s.bind) return null
1382
+ const s = (ctx && ctx.get && ctx.get('lanSettings')) || (ctx && ctx.configForms)
1383
+ if (!s || !s.get) return null
1384
1384
  try {
1385
- return s.bind({ namespace: NS })
1385
+ return s.get(NS)
1386
1386
  } catch (_) { /* settings scope binding failed */
1387
1387
  return null
1388
1388
  }
@@ -1969,7 +1969,7 @@ async function pollPending() {
1969
1969
  ))
1970
1970
  }
1971
1971
 
1972
- exports.inject = ['slots', 'settingsScope', 'locale']
1972
+ exports.inject = ['slots', 'configForms', 'locale']
1973
1973
  exports.apply = function apply(ctx) {
1974
1974
  registerSettings(ctx)
1975
1975
  registerSpeaker(ctx)
package/lib/routes.js CHANGED
@@ -58,6 +58,7 @@ export function registerHttpRoutes(ctx, api) {
58
58
  path: '/dsh-tts/stream',
59
59
  handler: async (req, res) => {
60
60
  if (req.method !== 'GET') { writeJson(res, 405, { ok: false, error: { code: 'method', message: 'GET only' } }); return }
61
+ if (!isTrustedSettingsRequest(req)) { writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } }); return }
61
62
  try {
62
63
  res.writeHead(200, {
63
64
  'Content-Type': 'text/event-stream',
@@ -376,6 +377,7 @@ export function registerHttpRoutes(ctx, api) {
376
377
  path: '/dsh-tts/pending',
377
378
  handler: async (req, res) => {
378
379
  if (req.method !== 'GET') { writeJson(res, 405, { ok: false, error: { code: 'method', message: 'GET only' } }); return }
380
+ if (!isTrustedSettingsRequest(req)) { writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } }); return }
379
381
  const url = new URL(req.url || '/', 'http://127.0.0.1')
380
382
  const after = url.searchParams.get('after') || ''
381
383
  let items = pending.slice()
@@ -392,6 +394,7 @@ export function registerHttpRoutes(ctx, api) {
392
394
  path: '/dsh-tts/speak',
393
395
  handler: async (req, res) => {
394
396
  if (req.method !== 'POST') { writeJson(res, 405, { ok: false, error: { code: 'method', message: 'POST only' } }); return }
397
+ if (!isTrustedSettingsRequest(req)) { writeJson(res, 403, { ok: false, error: { code: 'forbidden', message: 'same-origin only' } }); return }
395
398
  let raw
396
399
  try { raw = await readBody(req, 256 * 1024) } catch (e) {
397
400
  writeJson(res, 400, { ok: false, error: { code: 'body', message: e.message } }); return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-tts",
3
- "version": "0.4.20",
3
+ "version": "0.4.22",
4
4
  "description": "Text-to-speech for DeepSeek Harness: speak agent replies in the Web UI with a provider fallback chain (OpenAI, ElevenLabs, Google, Azure, Groq, Deepgram, OpenRouter, Edge, Piper, eSpeak).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -54,7 +54,9 @@
54
54
  "platform": "web",
55
55
  "inject": [
56
56
  "@deepseek-ai/dsh-client-locale",
57
- "@deepseek-ai/dsh-client-connection"
57
+ "@deepseek-ai/dsh-client-connection",
58
+ "@deepseek-ai/dsh-client-ui-slots",
59
+ "@deepseek-ai/dsh-client-ui-settings"
58
60
  ]
59
61
  }
60
62
  },