dsh 0.2.0-rc.2: in-container update (experimental channel), path-agnostic compose, upstream patches adapted to 0.1.x/0.2.x

This commit is contained in:
hermes committed 2026-10-01 19:21:19 +00:00
commit e6dcef9bf5
302 files changed
+75178

No files matched your search

@@ -0,0 +1,149 @@
import assert from 'node:assert/strict'
import { createServer, request as httpRequest } from 'node:http'
import { connect as netConnect } from 'node:net'
import { mkdtemp } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import test from 'node:test'
import { parseTrustedHosts } from '../lib/config.mjs'
import { closeGatewayServer, createGatewayServer, HEALTH_PATH } from '../lib/proxy.mjs'
async function listen(server) {
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(0, '127.0.0.1', resolve)
})
return server.address().port
}
async function close(server) {
server.closeAllConnections?.()
await new Promise(resolve => server.close(resolve))
}
function request(port, { path = '/', method = 'GET', headers = {}, body = '' } = {}) {
return new Promise((resolve, reject) => {
const outgoing = httpRequest({ hostname: '127.0.0.1', port, path, method, headers }, response => {
const chunks = []
response.on('data', chunk => chunks.push(chunk))
response.on('end', () => resolve({
status: response.statusCode,
headers: response.headers,
body: Buffer.concat(chunks).toString('utf8'),
}))
})
outgoing.once('error', reject)
outgoing.end(body)
})
}
const initialized = Object.freeze({ status: async () => ({ state: 'initialized' }), handle: async () => false })
test('Gateway fails closed without an authenticated browser session while health remains available', async () => {
let upstreamRequests = 0
const upstream = createServer((_incoming, response) => { upstreamRequests += 1; response.end('upstream') })
const upstreamPort = await listen(upstream)
const gateway = createGatewayServer({ trustedHosts: parseTrustedHosts({}), upstreamPort })
const port = await listen(gateway)
try {
assert.equal((await request(port, { path: HEALTH_PATH, headers: { host: '127.0.0.1' } })).status, 200)
const navigation = await request(port, { headers: { accept: 'text/html', host: '127.0.0.1' } })
assert.equal(navigation.status, 303)
assert.match(navigation.headers.location, /^\/_dsh_platform\/auth\//)
assert.equal((await request(port, { path: '/api/sessions', headers: { host: '127.0.0.1' } })).status, 401)
assert.equal(upstreamRequests, 0)
} finally {
await Promise.all([closeGatewayServer(gateway), close(upstream)])
}
})
test('Gateway reports an unavailable authentication backend as a service failure', async () => {
const unavailable = new Error('access socket unavailable')
unavailable.browserAuthenticationBackend = true
const browserAuthentication = {
status: async () => { throw unavailable },
handle: async () => false,
}
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({}), browserAuthentication, upstreamPort: 1,
})
const port = await listen(gateway)
try {
assert.equal((await request(port, {
path: HEALTH_PATH, headers: { host: '127.0.0.1' },
})).status, 200)
const unavailable = await request(port, { headers: { host: '127.0.0.1', accept: 'text/html' } })
assert.equal(unavailable.status, 503)
assert.match(unavailable.body, /authentication service unavailable/)
} finally { await closeGatewayServer(gateway) }
})
test('DSH and Management sessions authorize only their own route surfaces', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-gateway-session-domains-'))
const socketPath = join(root, 'management.sock')
const management = createServer((incoming, response) => response.end(`management:${incoming.url}`))
await new Promise((resolve, reject) => {
management.once('error', reject)
management.listen(socketPath, resolve)
})
const upstream = createServer((_incoming, response) => response.end('dsh'))
const upstreamPort = await listen(upstream)
const browserAuthentication = {
...initialized,
validateDsh: async request => ({ authenticated: request.headers.cookie === 'dsh=yes' }),
authorizePlugin: async request => request.headers.cookie === 'dsh=yes'
? { authorized: true, capability: { token: 'plugin-capability' } }
: { authorized: false },
validateManagement: async request => ({ authenticated: request.headers.cookie === 'management=yes' }),
enterManagement: async (_request, response) => { response.writeHead(303, { location: '/_dsh_platform/auth/management' }); response.end() },
}
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({}), browserAuthentication,
managementSocketPath: socketPath, upstreamPort,
})
const port = await listen(gateway)
try {
assert.equal((await request(port, { headers: { host: '127.0.0.1', cookie: 'dsh=yes' } })).body, 'dsh')
assert.equal((await request(port, {
path: '/_dsh_platform/plugin-api/v1/status', headers: { host: '127.0.0.1', cookie: 'dsh=yes' },
})).body, 'management:/_dsh_platform/api/v1/status')
assert.equal((await request(port, {
path: '/_dsh_platform/api/v1/status', headers: { host: '127.0.0.1', cookie: 'dsh=yes' },
})).status, 401)
assert.equal((await request(port, {
path: '/_dsh_platform/api/v1/status', headers: { host: '127.0.0.1', cookie: 'management=yes' },
})).body, 'management:/_dsh_platform/api/v1/status')
assert.equal((await request(port, {
path: '/', headers: { host: '127.0.0.1', cookie: 'management=yes' },
})).status, 401)
} finally {
await Promise.all([closeGatewayServer(gateway), close(management), close(upstream)])
}
})
test('terminal WebSocket requires Management rather than DSH authentication', async () => {
const browserAuthentication = {
...initialized,
validateDsh: async () => ({ authenticated: true }),
validateManagement: async () => ({ authenticated: false }),
enterManagement: async () => {},
}
const gateway = createGatewayServer({ trustedHosts: parseTrustedHosts({}), browserAuthentication, upstreamPort: 1 })
const port = await listen(gateway)
const client = netConnect(port, '127.0.0.1')
try {
await new Promise((resolve, reject) => { client.once('connect', resolve); client.once('error', reject) })
client.write([
'GET /_dsh_platform/api/v1/terminal/sessions/123e4567-e89b-42d3-a456-426614174000/stream HTTP/1.1',
'Host: 127.0.0.1', 'Connection: Upgrade', 'Upgrade: websocket', '', '',
].join('\r\n'))
const response = await new Promise((resolve, reject) => {
client.once('data', data => resolve(data.toString('utf8')))
client.once('error', reject)
})
assert.match(response, /^HTTP\/1\.1 401 Unauthorized/)
} finally {
client.destroy()
await closeGatewayServer(gateway)
}
})
@@ -0,0 +1,486 @@
import assert from 'node:assert/strict'
import { createServer, request as httpRequest } from 'node:http'
import { connect as netConnect } from 'node:net'
import test from 'node:test'
import { DshAvailability, availabilityPage, language } from '../lib/availability.mjs'
import { closeGatewayServer, createGatewayServer as createGatewayServerBase, PLUGIN_FAILURE_PATH, READINESS_PATH, WAIT_PATH, safeReturnPath } from '../lib/proxy.mjs'
import { parseTrustedHosts } from '../lib/config.mjs'
const AUTHENTICATED_BROWSER = Object.freeze({
status: async () => ({ state: 'initialized' }),
validateDsh: async () => ({ authenticated: true }),
validateManagement: async () => ({ authenticated: true }),
enterManagement: async () => { throw new Error('unexpected Management login') },
handle: async () => false,
})
const UNAUTHENTICATED_BROWSER = Object.freeze({
status: async () => ({ state: 'initialized' }),
validateDsh: async () => ({ authenticated: false }),
validateManagement: async () => ({ authenticated: false }),
enterManagement: async () => { throw new Error('unexpected Management login') },
handle: async () => false,
})
function createGatewayServer(options) {
return createGatewayServerBase({
...options,
browserAuthentication: options.browserAuthentication ?? AUTHENTICATED_BROWSER,
})
}
const ISOLATED_UNAUTHENTICATED_BROWSER = Object.freeze({
...UNAUTHENTICATED_BROWSER,
status: async () => ({ state: 'initialized', account: {
managementAccess: {
mode: 'isolated',
isolatedEntry: { kind: 'public', managementPublicOrigin: 'https://management.example' },
},
} }),
})
async function listen(server) {
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(0, '127.0.0.1', resolve)
})
return server.address().port
}
function request(port, path = '/', { method = 'GET', accept = 'text/html', headers = {} } = {}) {
return new Promise((resolve, reject) => {
const outgoing = httpRequest({
hostname: '127.0.0.1', port, path, method,
headers: { host: 'dsh.example', accept, ...headers },
}, response => {
const chunks = []
response.on('data', chunk => chunks.push(chunk))
response.on('end', () => resolve({
status: response.statusCode,
headers: response.headers,
body: Buffer.concat(chunks).toString('utf8'),
}))
})
outgoing.once('error', reject)
outgoing.end()
})
}
async function unavailableGateway({ platform = {}, availability = new DshAvailability(), probe = async () => false, report, browserAuthentication } = {}) {
const placeholder = createServer()
const unavailablePort = await listen(placeholder)
await new Promise(resolve => placeholder.close(resolve))
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'dsh.example' }),
upstreamPort: unavailablePort,
platformStatus: async () => platform,
availability,
probe,
browserAuthentication,
report,
probeIntervalMs: 60_000,
})
return { gateway, port: await listen(gateway) }
}
test('authenticated DSH traffic waits for authoritative Bootstrap publication', async t => {
let upstreamRequests = 0
const upstream = createServer((_request, response) => {
upstreamRequests += 1
response.writeHead(200, { 'content-type': 'text/plain' })
response.end('published')
})
const upstreamPort = await listen(upstream)
t.after(() => upstream.close())
let published = false
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'dsh.example' }),
upstreamPort,
platformStatus: async () => ({ dshLifecycle: { state: 'running' } }),
probe: async () => true,
dshUpstreamAuthentication: {
cookie: async () => null,
publicReady: async () => published,
},
probeIntervalMs: 60_000,
})
const port = await listen(gateway)
try {
const socket = netConnect(port, '127.0.0.1')
await new Promise((resolve, reject) => {
socket.once('connect', resolve)
socket.once('error', reject)
})
socket.write('GET /events HTTP/1.1\r\nHost: dsh.example\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n')
const upgrade = await new Promise((resolve, reject) => {
socket.once('data', data => resolve(data.toString('utf8')))
socket.once('error', reject)
})
assert.match(upgrade, /^HTTP\/1\.1 503 Service Unavailable/)
socket.destroy()
const waiting = await request(port)
assert.equal(waiting.status, 200)
assert.match(waiting.body, /DeepSeek Harness is starting/)
assert.equal(upstreamRequests, 0)
assert.deepEqual(JSON.parse((await request(port, READINESS_PATH, { accept: 'application/json' })).body).ready, false)
const dedicatedWaiting = await request(port, `${WAIT_PATH}?return=%2Fsessions%2Fcurrent`)
assert.equal(dedicatedWaiting.status, 200)
assert.match(dedicatedWaiting.body, /DeepSeek Harness is starting/)
assert.match(dedicatedWaiting.body, /\/sessions\/current/)
published = true
const ready = await request(port)
assert.equal(ready.status, 200)
assert.equal(ready.body, 'published')
assert.equal(upstreamRequests, 1)
assert.equal(JSON.parse((await request(port, READINESS_PATH, { accept: 'application/json' })).body).ready, true)
} finally {
await closeGatewayServer(gateway)
}
})
test('an intentional stopped state does not report an upstream proxy failure', async () => {
const reports = []
const context = await unavailableGateway({
platform: { dshLifecycle: { state: 'stopped' } },
report: (message, fields) => { reports.push({ message, fields }) },
})
try {
const response = await request(context.port)
assert.equal(response.status, 200)
assert.match(response.body, /DeepSeek Harness is stopped/)
await new Promise(resolve => setImmediate(resolve))
assert.equal(reports.some(entry => entry.message === 'gateway.upstream.failed'), false)
} finally {
await closeGatewayServer(context.gateway)
}
})
test('an unauthenticated top-level navigation sees classified DSH recovery before the login page', async () => {
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'dsh.example' }),
upstreamPort: 1,
platformStatus: async () => ({ dshLifecycle: { state: 'failed', error: 'private runtime detail' } }),
probe: async () => false,
browserAuthentication: UNAUTHENTICATED_BROWSER,
probeIntervalMs: 60_000,
})
const port = await listen(gateway)
try {
const page = await request(port)
assert.equal(page.status, 200)
assert.match(page.body, /DeepSeek Harness could not start/)
assert.match(page.body, /href="\/_dsh_platform\/console\/"/)
assert.doesNotMatch(page.body, /private runtime detail|autocomplete="current-password"/)
assert.equal((await request(port, '/api/sessions', { accept: 'application/json' })).status, 503)
} finally {
await closeGatewayServer(gateway)
}
})
test('official-style holding page is self-contained and replaces the spinner with platform status', () => {
const page = availabilityPage('switching', { 'accept-language': 'zh-CN' })
assert.match(page, /HARNESS/)
assert.match(page, /正在切换 DeepSeek Harness 运行版本/)
assert.match(page, /href="\/_dsh_platform\/console\/"/)
assert.match(page, /打开 DSH 管理中心进行检查和恢复/)
assert.match(page, new RegExp(READINESS_PATH))
assert.match(page, /prefers-color-scheme:light/)
assert.match(page, /name="viewport"/)
assert.match(page, /html\{height:100%\}body\{min-height:100%;margin:0;display:grid;place-items:center;/)
assert.doesNotMatch(page, /100(?:d|s|l)?vh/)
assert.match(page, /max-width:520px/)
assert.match(page, /management\.href=value\.managementHref/)
assert.doesNotMatch(page, /spinner|Loading plugins/)
assert.doesNotMatch(page, /letter-spacing:-/)
})
test('persistent plugin failure page is terminal, localized, and links to Management', async () => {
const page = availabilityPage('plugin-failed', { 'accept-language': 'zh-CN' }, { poll: false, allowRefresh: true })
assert.match(page, /DeepSeek Harness 插件持续加载失败/)
assert.match(page, /打开 DSH 管理中心进行检查和恢复/)
assert.match(page, /刷新页面/)
assert.doesNotMatch(page, /setTimeout\(check/)
assert.doesNotMatch(availabilityPage('failed', {}, { poll: false }), /Reload page/)
const context = await unavailableGateway()
try {
const response = await request(context.port, PLUGIN_FAILURE_PATH, {
headers: { 'accept-language': 'zh-CN' },
})
assert.equal(response.status, 200)
assert.match(response.body, /DeepSeek Harness 插件持续加载失败/)
assert.equal((await request(context.port, PLUGIN_FAILURE_PATH, { method: 'POST' })).status, 405)
} finally {
await closeGatewayServer(context.gateway)
}
})
test('Gateway temporary DSH pages link to the configured isolated Management entry', async () => {
const context = await unavailableGateway({ browserAuthentication: ISOLATED_UNAUTHENTICATED_BROWSER })
try {
const response = await request(context.port, PLUGIN_FAILURE_PATH)
assert.equal(response.status, 200)
assert.match(response.body, /href="https:\/\/management\.example\/"/)
assert.doesNotMatch(response.body, /href="\/_dsh_platform\/console\/"/)
} finally {
await closeGatewayServer(context.gateway)
}
})
test('Gateway readiness publishes the current Management entry for an already-open temporary page', async () => {
let access = { state: 'initialized', account: { managementAccess: { mode: 'compat' } } }
const browserAuthentication = {
...UNAUTHENTICATED_BROWSER,
status: async () => access,
}
const context = await unavailableGateway({ browserAuthentication })
try {
const compatible = JSON.parse((await request(context.port, READINESS_PATH)).body)
assert.equal(compatible.managementHref, '/_dsh_platform/console/')
access = await ISOLATED_UNAUTHENTICATED_BROWSER.status()
const isolated = JSON.parse((await request(context.port, READINESS_PATH)).body)
assert.equal(isolated.managementHref, 'https://management.example/')
} finally {
await closeGatewayServer(context.gateway)
}
})
test('holding pages prefer the last DSH locale cookie over browser language', () => {
assert.equal(language({ cookie: 'theme=dark; dsh_locale=en', 'accept-language': 'zh-CN' }), 'en')
assert.equal(language({ cookie: 'dsh_locale=zh', 'accept-language': 'en-US' }), 'zh')
assert.equal(language({ cookie: 'dsh_locale=fr', 'accept-language': 'en-US' }), 'en')
assert.equal(language({ 'accept-language': 'fr-FR, zh-CN;q=0.8, en;q=0.5' }), 'zh')
assert.match(availabilityPage('recovering', { cookie: 'dsh_locale=zh', 'accept-language': 'en-US' }), /意外停止/)
assert.match(availabilityPage('recovering', { cookie: 'dsh_locale=en', 'accept-language': 'zh-CN' }), /Open DSH Management Console for diagnostics and recovery/)
})
test('every classified outage page links to the standalone Platform Management console', () => {
for (const state of ['starting', 'stopping', 'stopped', 'restarting', 'switching', 'runtime-recovering', 'recovering', 'failed', 'unavailable']) {
const page = availabilityPage(state, { 'accept-language': 'en-US' })
assert.match(page, /href="\/_dsh_platform\/console\/"/)
}
})
test('intentional DSH restarts have explicit holding and failure states', () => {
const availability = new DshAvailability()
assert.equal(availability.classify({ operation: 'restarting' }), 'restarting')
assert.equal(availability.classify({ operation: 'restart-failed' }), 'failed')
assert.match(availabilityPage('restarting', { 'accept-language': 'zh-CN' }), /正在重新启动/)
assert.equal(availability.classify({ dshLifecycle: { state: 'stopping' } }), 'stopping')
assert.equal(availability.classify({ dshLifecycle: { state: 'stopped' } }), 'stopped')
assert.equal(availability.classify({ dshLifecycle: { state: 'recovering', attempt: 2 } }), 'recovering')
assert.match(availabilityPage('recovering', { 'accept-language': 'zh-CN' }, {
lifecycle: { attempt: 2, maxAttempts: 3 },
}), /第 2 \/ 3 次/)
})
test('holding-page return paths stay same-origin and reject ambiguous inputs', () => {
assert.equal(safeReturnPath('/sessions/current?view=chat#latest'), '/sessions/current?view=chat#latest')
for (const value of [null, '', '//example.com/path', '/\\example.com', 'https://example.com/', '/bad\npath']) {
assert.equal(safeReturnPath(value), '/')
}
const page = availabilityPage('restarting', {}, { returnPath: '/</script><script>alert(1)</script>' })
assert.doesNotMatch(page, /const returnPath="\/<\/script>/)
assert.match(page, /\\u003c\/script>/)
})
test('cold start serves a holding page while API and WebSocket-shaped HTTP requests receive 503', async () => {
const { gateway, port } = await unavailableGateway()
try {
const page = await request(port)
assert.equal(page.status, 200)
assert.match(page.body, /DeepSeek Harness is starting/)
assert.equal(page.headers['cache-control'], 'no-store')
assert.equal((await request(port, '/api/sessions', { accept: 'application/json' })).status, 503)
assert.equal((await request(port, '/', { method: 'POST', accept: 'text/html' })).status, 503)
} finally {
await closeGatewayServer(gateway)
}
})
test('an unresponsive management service does not block the cold-start holding page', async () => {
const placeholder = createServer()
const unavailablePort = await listen(placeholder)
await new Promise(resolve => placeholder.close(resolve))
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'dsh.example' }),
upstreamPort: unavailablePort,
platformStatus: () => new Promise(() => {}),
probe: async () => false,
probeIntervalMs: 60_000,
})
const port = await listen(gateway)
try {
const startedAt = Date.now()
const page = await request(port)
assert.equal(page.status, 200)
assert.match(page.body, /DeepSeek Harness is starting/)
assert.ok(Date.now() - startedAt < 1_000)
} finally {
await closeGatewayServer(gateway)
}
})
test('cold-start management status failures remain diagnostic warnings', async () => {
const reported = []
const gateway = createGatewayServer({
trustedHosts: parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'dsh.example' }),
upstreamPort: 1,
platformStatus: async () => { throw Object.assign(new Error('socket is not ready'), { code: 'ENOENT' }) },
probe: async () => false,
probeIntervalMs: 60_000,
report: async (message, fields) => reported.push({ message, fields }),
})
const port = await listen(gateway)
try {
assert.equal((await request(port)).status, 200)
await new Promise(resolve => setImmediate(resolve))
assert.equal(reported.length, 1)
assert.equal(reported[0].message, 'gateway.platform-status.failed')
assert.equal(reported[0].fields.level, 'warning')
assert.equal(reported[0].fields.error.code, 'ENOENT')
} finally {
await closeGatewayServer(gateway)
}
})
test('platform switching, recovery, and startup failure select distinct page messages', async () => {
for (const [platform, expected] of [
[{ operation: 'switching' }, /Switching the DeepSeek Harness runtime/],
[{ operation: 'recovering' }, /Restoring the DeepSeek Harness runtime/],
[{ recoveryMode: 'candidate failed' }, /DeepSeek Harness could not start/],
]) {
const { gateway, port } = await unavailableGateway({ platform })
try {
const page = await request(port)
assert.equal(page.status, 200)
assert.match(page.body, expected)
assert.equal((await request(port, '/api/status', { accept: 'application/json' })).status, 503)
} finally {
await closeGatewayServer(gateway)
}
}
})
test('dedicated holding route preserves a safe return path and redirects when ready', async () => {
let ready = false
const platform = { dshLifecycle: { state: 'stopping' } }
const context = await unavailableGateway({
platform,
probe: async () => ready,
})
try {
const target = '/sessions/current?view=chat#latest'
const waiting = await request(context.port, `${WAIT_PATH}?return=${encodeURIComponent(target)}`)
assert.equal(waiting.status, 200)
assert.match(waiting.body, /DeepSeek Harness is stopping/)
assert.match(waiting.body, /location\.replace\(returnPath\)/)
assert.match(waiting.body, /\/sessions\/current\?view=chat#latest/)
const invalid = await request(context.port, `${WAIT_PATH}?return=${encodeURIComponent('//example.com/')}`)
assert.equal(invalid.status, 200)
assert.match(invalid.body, /const returnPath="\/"/)
ready = true
const premature = await request(context.port, `${WAIT_PATH}?return=${encodeURIComponent(target)}`)
assert.equal(premature.status, 200)
assert.match(premature.body, /DeepSeek Harness is stopping/)
const prematureReadiness = await request(context.port, READINESS_PATH)
assert.equal(prematureReadiness.status, 503)
assert.equal(JSON.parse(prematureReadiness.body).state, 'stopping')
platform.dshLifecycle.state = 'running'
const redirected = await request(context.port, `${WAIT_PATH}?return=${encodeURIComponent(target)}`)
assert.equal(redirected.status, 302)
assert.equal(redirected.headers.location, target)
assert.deepEqual(JSON.parse((await request(context.port, READINESS_PATH)).body), {
ready: true, state: 'ready', pluginRecoveryEligible: false,
managementHref: '/_dsh_platform/console/',
})
assert.equal((await request(context.port, WAIT_PATH, { method: 'POST' })).status, 405)
} finally {
await closeGatewayServer(context.gateway)
}
})
test('WebSocket receives 503 during a classified DSH outage', async () => {
const reports = []
const { gateway, port } = await unavailableGateway({
platform: { operation: 'switching' },
report: (message, fields) => reports.push({ message, fields }),
})
const socket = netConnect(port, '127.0.0.1')
try {
await new Promise((resolve, reject) => {
socket.once('connect', resolve)
socket.once('error', reject)
})
socket.write('GET /events HTTP/1.1\r\nHost: dsh.example\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n')
const response = await new Promise((resolve, reject) => {
socket.once('data', data => resolve(data.toString('utf8')))
socket.once('error', reject)
})
assert.match(response, /^HTTP\/1\.1 503 Service Unavailable/)
await new Promise(resolve => setImmediate(resolve))
const failure = reports.find(entry => entry.message === 'gateway.websocket.failed')
assert.equal(failure?.fields.level, 'warning')
assert.equal(failure?.fields.upstream, 'dsh')
} finally {
socket.destroy()
await closeGatewayServer(gateway)
}
})
test('one unexpected local failure remains 502 until repeated probes confirm unavailability', async () => {
let now = 0
const availability = new DshAvailability({ now: () => now, failures: 3, failureWindowMs: 1_500 })
availability.observe(true)
const context = await unavailableGateway({ availability })
try {
assert.equal((await request(context.port)).status, 502)
availability.observe(false)
now = 1_600
availability.observe(false)
const recovered = await request(context.port)
assert.equal(recovered.status, 200)
assert.match(recovered.body, /temporarily unavailable/)
} finally {
await closeGatewayServer(context.gateway)
}
})
test('a Bootstrap candidate handoff serves the switching page instead of a bare 502', async () => {
const context = await unavailableGateway({ platform: { update: { status: 'building-candidate' } } })
try {
const response = await request(context.port)
assert.equal(response.status, 200)
assert.match(response.body, /Switching the DeepSeek Harness runtime/)
} finally {
await closeGatewayServer(context.gateway)
}
})
test('readiness immediately reports ready and clears confirmed failure state', async () => {
let ready = false
let now = 0
const availability = new DshAvailability({ now: () => now, failures: 1, failureWindowMs: 0 })
availability.observe(true)
availability.observe(false)
const context = await unavailableGateway({ availability, probe: async () => ready })
try {
const unavailable = await request(context.port, READINESS_PATH, { accept: 'application/json' })
assert.equal(unavailable.status, 503)
assert.equal(JSON.parse(unavailable.body).state, 'unavailable')
ready = true
const healthy = await request(context.port, READINESS_PATH, { accept: 'application/json' })
assert.equal(healthy.status, 200)
assert.deepEqual(JSON.parse(healthy.body), {
ready: true, state: 'ready', pluginRecoveryEligible: false,
managementHref: '/_dsh_platform/console/',
})
assert.equal(availability.classify({}), 'unknown')
} finally {
await closeGatewayServer(context.gateway)
}
})
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,40 @@
import assert from 'node:assert/strict'
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import test from 'node:test'
import { patchBrowserLoopback } from '../../../../environment/resources/patches/browser-loopback.mjs'
const BEFORE = 'isLoopback: pageLocation === void 0 || isLoopbackHostname(pageLocation.hostname),'
const BEFORE_WITH_TRANSPORT = 'isLoopback: transport?.ownsHost === true || pageLocation === void 0 || isLoopbackHostname(pageLocation.hostname),'
test('browser loopback patch changes exactly one connection classification', async () => {
const directory = await mkdtemp(join(tmpdir(), 'dsh-browser-loopback-patch-'))
const target = join(directory, 'client.js')
try {
await writeFile(target, `before;${BEFORE}after;`)
patchBrowserLoopback(target)
assert.equal(await readFile(target, 'utf8'), 'before;isLoopback: true,after;')
assert.throws(() => patchBrowserLoopback(target), /found 0/)
await writeFile(target, `${BEFORE}${BEFORE}`)
assert.throws(() => patchBrowserLoopback(target), /found 2/)
} finally {
await rm(directory, { recursive: true })
}
})
test('browser loopback patch accepts the transport-owned Host classification', async () => {
const directory = await mkdtemp(join(tmpdir(), 'dsh-browser-loopback-patch-'))
const target = join(directory, 'client.js')
try {
await writeFile(target, `before;${BEFORE_WITH_TRANSPORT}after;`)
patchBrowserLoopback(target)
assert.equal(await readFile(target, 'utf8'), 'before;isLoopback: true,after;')
await writeFile(target, `${BEFORE}${BEFORE_WITH_TRANSPORT}`)
assert.throws(() => patchBrowserLoopback(target), /found 2/)
} finally {
await rm(directory, { recursive: true })
}
})
@@ -0,0 +1,85 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import {
loadConfig,
parseBoolean,
parseTrustedAuthority,
parseTrustedHosts,
} from '../lib/config.mjs'
import { UsageError } from '../lib/errors.mjs'
test('parseBoolean accepts only explicit Compose booleans', () => {
assert.equal(parseBoolean('FLAG', undefined, true), true)
assert.equal(parseBoolean('FLAG', 'false', true), false)
assert.throws(() => parseBoolean('FLAG', '1', true), UsageError)
})
test('parseTrustedAuthority accepts canonical host authorities', () => {
assert.deepEqual(parseTrustedAuthority('Example.COM'), {
hostname: 'example.com',
authority: 'example.com',
anyPort: true,
matchAuthority: 'example.com',
})
assert.deepEqual(parseTrustedAuthority('example.com:8443'), {
hostname: 'example.com',
authority: 'example.com:8443',
anyPort: false,
matchAuthority: 'example.com:8443',
})
assert.deepEqual(parseTrustedAuthority('[fd00::1]:3080'), {
hostname: '[fd00::1]',
authority: '[fd00::1]:3080',
anyPort: false,
matchAuthority: '[fd00::1]:3080',
})
})
test('parseTrustedAuthority rejects URL-like and noncanonical entries', () => {
for (const value of [
'https://example.com',
'example.com/path',
'user@example.com',
'example.com:',
'*.example.com',
' example.com',
]) {
assert.throws(() => parseTrustedAuthority(value), UsageError, value)
}
})
test('parseTrustedHosts supports empty, lists, deduplication, and wildcard', () => {
assert.deepEqual(parseTrustedHosts({}), { wildcard: false, authorities: [] })
const list = parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'a.example, b.example:8443,a.example' })
assert.equal(list.wildcard, false)
assert.equal(list.authorities.length, 2)
assert.deepEqual(parseTrustedHosts({ DSH_TRUSTED_HOSTS: '*' }), {
wildcard: true,
authorities: [],
})
})
test('parseTrustedHosts rejects malformed lists', () => {
assert.throws(() => parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'a.example,,b.example' }), UsageError)
assert.throws(() => parseTrustedHosts({ DSH_TRUSTED_HOSTS: '*,a.example' }), UsageError)
})
test('loadConfig owns only Gateway settings', async () => {
const config = await loadConfig({
DSH_DEFAULT_WORKSPACE: 'not-a-gateway-setting',
DSH_TELEMETRY_DISABLED: 'not-a-gateway-setting',
DSH_PROXY_USERNAME: 'unused',
DSH_PROXY_PASSWORD: '',
})
assert.equal(Object.hasOwn(config, 'password'), false)
assert.equal(Object.hasOwn(config, 'username'), false)
assert.equal(Object.hasOwn(config, 'platformPassword'), false)
assert.equal(Object.hasOwn(config, 'workspace'), false)
assert.equal(Object.hasOwn(config, 'telemetryDisabled'), false)
assert.equal(config.managementPort, 3081)
assert.doesNotReject(() => loadConfig({
DSH_PROXY_USERNAME: 'invalid:name',
DSH_PROXY_PASSWORD: 'secret',
DSH_PLATFORM_PASSWORD: 'legacy-secret',
}))
})
@@ -0,0 +1,25 @@
import assert from 'node:assert/strict'
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import test from 'node:test'
import { patchDirectoryPicker } from '../../../../environment/resources/patches/directory-picker.mjs'
test('directory picker patch changes exactly one default without touching explicit paths', async () => {
const directory = await mkdtemp(join(tmpdir(), 'dsh-directory-patch-'))
const target = join(directory, 'index.js')
try {
await writeFile(target, 'before;const target = resolve(path ?? home);after;')
patchDirectoryPicker(target)
assert.equal(
await readFile(target, 'utf8'),
'before;const target = resolve(path ?? process.env.DSH_DEFAULT_WORKSPACE ?? home);after;',
)
assert.throws(() => patchDirectoryPicker(target), /found 0/)
await writeFile(target, 'const target = resolve(path ?? home);const target = resolve(path ?? home);')
assert.throws(() => patchDirectoryPicker(target), /found 2/)
} finally {
await rm(directory, { recursive: true })
}
})
@@ -0,0 +1,84 @@
import assert from 'node:assert/strict'
import { chmod, mkdtemp } from 'node:fs/promises'
import { createServer } from 'node:http'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import test from 'node:test'
import { DshUpstreamAuthentication } from '../lib/dsh-upstream-auth.mjs'
async function listen(server, target, host) {
await new Promise((resolve, reject) => {
server.once('error', reject)
server.listen(target, host, resolve)
})
}
test('exchanges and caches the private DSH launch URL', async t => {
const root = await mkdtemp(join(tmpdir(), 'dsh-upstream-auth-'))
const socketPath = join(root, 'lifecycle.sock')
let exchanges = 0
const dsh = createServer((request, response) => {
exchanges += 1
assert.equal(request.url, '/?token=fixture-token')
response.writeHead(303, {
location: '/',
'set-cookie': 'dsh-auth-fixture=signed; Path=/; HttpOnly; SameSite=Strict',
})
response.end()
})
await listen(dsh, 0, '127.0.0.1')
const port = dsh.address().port
let generation = 'generation-one'
let publicReady = false
const lifecycle = createServer((_request, response) => {
response.writeHead(200, { 'content-type': 'application/json' })
response.end(JSON.stringify({
generation,
publicReady,
ready: true,
readyUrl: `http://127.0.0.1:${String(port)}/?token=fixture-token`,
}))
})
await listen(lifecycle, socketPath)
await chmod(socketPath, 0o600)
t.after(() => { dsh.close(); lifecycle.close() })
const authentication = new DshUpstreamAuthentication({ socketPath, port })
assert.equal(await authentication.publicReady(), false)
assert.equal(await authentication.cookie(), null)
assert.equal(exchanges, 0)
publicReady = true
assert.equal(await authentication.publicReady(), true)
assert.equal(await authentication.cookie(), 'dsh-auth-fixture=signed')
assert.equal(await authentication.cookie(), 'dsh-auth-fixture=signed')
assert.equal(exchanges, 1)
generation = 'generation-two'
assert.equal(await authentication.cookie(), 'dsh-auth-fixture=signed')
assert.equal(exchanges, 2)
publicReady = false
assert.equal(await authentication.cookie(), null)
publicReady = true
assert.equal(await authentication.publicReady(), true)
assert.equal(await authentication.cookie(), 'dsh-auth-fixture=signed')
assert.equal(exchanges, 3)
})
test('keeps probing legacy DSH readiness without inventing a cookie', async t => {
const root = await mkdtemp(join(tmpdir(), 'dsh-upstream-auth-legacy-'))
const socketPath = join(root, 'lifecycle.sock')
let now = 0
let probes = 0
const lifecycle = createServer((_request, response) => {
probes += 1
response.writeHead(200, { 'content-type': 'application/json' })
response.end(JSON.stringify({ ready: true, readyUrl: null }))
})
await listen(lifecycle, socketPath)
t.after(() => lifecycle.close())
const authentication = new DshUpstreamAuthentication({ socketPath, now: () => now })
assert.equal(await authentication.cookie(), null)
assert.equal(await authentication.cookie(), null)
assert.equal(probes, 1)
now = 250
assert.equal(await authentication.cookie(), null)
assert.equal(probes, 2)
})
@@ -0,0 +1,127 @@
import assert from 'node:assert/strict'
import { EventEmitter } from 'node:events'
import test from 'node:test'
import { runGateway } from '../lib/lifecycle.mjs'
class FakeServer extends EventEmitter {
listening = false
listen(port, host) {
this.listening = true
this.bound = { port, host }
queueMicrotask(() => this.emit('listening'))
}
close(callback) {
this.listening = false
queueMicrotask(() => callback())
}
closeAllConnections() {}
}
const config = Object.freeze({
polyfill: true,
trustedHosts: Object.freeze({ wildcard: false, authorities: Object.freeze([]) }),
})
test('gateway owns only its listener and binds browser authentication to Access Manager', async () => {
const signalSource = new EventEmitter()
const server = new FakeServer()
let options
const reports = []
const running = runGateway(config, {
externalHost: '127.0.0.1',
externalPort: 8080,
managementSocketPath: '/run/platform.sock',
maintenanceSocketPath: '/run/maintenance.sock',
accessClient: { request: async () => ({ state: 'recovery-required' }) },
signalSource,
report: (message, fields) => { reports.push({ message, fields }) },
gatewayFactory: value => { options = value; return server },
})
await new Promise(resolve => setImmediate(resolve))
assert.deepEqual(server.bound, { host: '127.0.0.1', port: 8080 })
assert.equal(options.managementSocketPath, '/run/platform.sock')
assert.equal(options.maintenanceSocketPath, '/run/maintenance.sock')
assert.equal(typeof options.browserAuthentication.handle, 'function')
assert.equal(typeof options.platformStatus, 'function')
signalSource.emit('SIGTERM')
assert.equal(await running, 0)
assert.equal(server.listening, false)
assert.deepEqual(reports.map(entry => entry.message), [
'gateway.starting', 'gateway.ready', 'gateway.stopping', 'gateway.stopped',
])
assert.equal(reports[2].fields.signal, 'SIGTERM')
})
test('gateway propagates listener failures without creating a DSH process', async () => {
const server = new FakeServer()
const reports = []
server.listen = () => queueMicrotask(() => server.emit('error', new Error('bind failed')))
await assert.rejects(runGateway(config, {
gatewayFactory: () => server,
accessClient: { request: async () => ({ state: 'recovery-required' }) },
signalSource: new EventEmitter(),
report: (message, fields) => { reports.push({ message, fields }) },
}), /bind failed/)
assert.equal(reports.some(entry => entry.message === 'gateway.fatal'
&& entry.fields.error.message === 'bind failed'), true)
})
test('gateway can expose an isolated Management listener from the same process', async () => {
const signalSource = new EventEmitter()
const servers = []
const running = runGateway(config, {
externalHost: '127.0.0.1',
externalPort: 8080,
managementPort: 8081,
managementHost: '127.0.0.1',
gatewayFactory: options => {
const server = new FakeServer()
server.options = options
servers.push(server)
return server
},
accessClient: { request: async () => ({ state: 'recovery-required' }) },
signalSource,
})
await new Promise(resolve => setImmediate(resolve))
assert.equal(servers.length, 2)
assert.deepEqual(servers[0].bound, { host: '127.0.0.1', port: 8080 })
assert.deepEqual(servers[1].bound, { host: '127.0.0.1', port: 8081 })
assert.equal(servers[0].options.surface, 'compat')
assert.equal(servers[1].options.surface, 'management')
signalSource.emit('SIGTERM')
assert.equal(await running, 0)
assert.equal(servers.every(server => server.listening === false), true)
})
test('gateway retains a recent platform status while Management is handed off', async () => {
const signalSource = new EventEmitter()
const server = new FakeServer()
const expected = { update: { status: 'building-candidate' } }
let requests = 0
let options
const running = runGateway(config, {
gatewayFactory: value => { options = value; return server },
accessClient: { request: async () => ({ state: 'recovery-required' }) },
signalSource,
managementClient: {
request: async () => {
requests += 1
if (requests === 1) return expected
throw Object.assign(new Error('Management is switching'), { code: 'ECONNREFUSED' })
},
},
platformStatusPollMs: 5,
})
try {
await new Promise(resolve => setTimeout(resolve, 15))
assert.deepEqual(await options.platformStatus(), expected)
assert.equal(requests >= 2, true)
} finally {
signalSource.emit('SIGTERM')
assert.equal(await running, 0)
}
})
@@ -0,0 +1,147 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import vm from 'node:vm'
import { injectRandomUuidPolyfill, LIFECYCLE_TRANSITION_GUARD, PLUGIN_RECOVERY_GUARD, RANDOM_UUID_POLYFILL, SESSION_VALIDITY_GUARD } from '../lib/polyfill.mjs'
async function simulatePluginError(bundlePath, { eventType = 'error', storage = new Map() } = {}) {
let replacement
const events = []
const listeners = new Map()
const context = {
URL,
crypto: globalThis.crypto,
location: {
href: 'http://gateway.local/sessions/current',
pathname: '/sessions/current',
search: '',
hash: '',
replace: value => { replacement = value },
},
sessionStorage: {
getItem: key => storage.get(key) ?? null,
setItem: (key, value) => storage.set(key, value),
},
addEventListener: (name, callback) => listeners.set(name, callback),
fetch: async (input, init) => {
if (input === '/_dsh_gateway/readiness') return { json: async () => ({ state: 'ready', pluginRecoveryEligible: true }) }
if (input === '/_dsh_platform/plugin-api/v1/status') return {
json: async () => ({
dshLifecycle: {
state: 'running',
taskId: 'lifecycle-task',
updatedAt: new Date().toISOString(),
},
}),
}
if (input === '/_dsh_gateway/client-event') {
events.push(JSON.parse(init.body))
return { json: async () => ({}) }
}
return { ok: true, json: async () => ({}) }
},
}
vm.runInNewContext(PLUGIN_RECOVERY_GUARD.slice('<script>'.length, -'</script>'.length), context)
if (eventType === 'error') listeners.get('error')?.({ filename: `http://gateway.local${bundlePath}` })
else if (eventType === 'unhandledrejection') listeners.get('unhandledrejection')?.({
reason: { stack: `TypeError: failed to import http://gateway.local${bundlePath}` },
})
await new Promise(resolve => setImmediate(resolve))
return { events, replacement, storage }
}
test('polyfill is inserted immediately after the head tag', () => {
assert.equal(
injectRandomUuidPolyfill('<html><head data-x="1"><title>x</title></head></html>'),
`<html><head data-x="1">${RANDOM_UUID_POLYFILL}${LIFECYCLE_TRANSITION_GUARD}${SESSION_VALIDITY_GUARD}${PLUGIN_RECOVERY_GUARD}<title>x</title></head></html>`,
)
})
test('polyfill falls back to the start when no head exists', () => {
assert.equal(injectRandomUuidPolyfill('<main>x</main>'), `${RANDOM_UUID_POLYFILL}${LIFECYCLE_TRANSITION_GUARD}${SESSION_VALIDITY_GUARD}${PLUGIN_RECOVERY_GUARD}<main>x</main>`)
})
test('gateway lifecycle guard moves an already-open DSH page into the holding flow', async () => {
let inspect
let replacement
const context = {
EventSource: class {
addEventListener(name, callback) { if (name === 'state') inspect = callback }
},
URL,
fetch: async () => ({ json: async () => ({ dshLifecycle: { state: 'restarting' } }) }),
location: {
pathname: '/sessions/current', search: '?view=chat', hash: '#latest',
replace: value => { replacement = value },
},
}
vm.runInNewContext(LIFECYCLE_TRANSITION_GUARD.slice('<script>'.length, -'</script>'.length), context)
await new Promise(resolve => setImmediate(resolve))
assert.equal(replacement, '/_dsh_gateway/wait?return=%2Fsessions%2Fcurrent%3Fview%3Dchat%23latest')
replacement = undefined
await inspect()
assert.equal(replacement, undefined)
})
test('plugin recovery guard runs before DSH modules and bounds lifecycle recovery', () => {
assert.doesNotThrow(() => new Function(PLUGIN_RECOVERY_GUARD.slice('<script>'.length, -'</script>'.length)))
assert.match(PLUGIN_RECOVERY_GUARD, /globalThis\.fetch=function/)
assert.match(PLUGIN_RECOVERY_GUARD, /\/_dsh_gateway\/client-event/)
assert.match(PLUGIN_RECOVERY_GUARD, /\/_dsh_gateway\/wait/)
assert.match(PLUGIN_RECOVERY_GUARD, /attempt>=3/)
assert.match(PLUGIN_RECOVERY_GUARD, /\/_dsh_gateway\/plugin-failure/)
assert.match(PLUGIN_RECOVERY_GUARD, /browser\.plugin-load\.recovery\.completed/)
assert.match(PLUGIN_RECOVERY_GUARD, /addEventListener\("error"/)
assert.match(PLUGIN_RECOVERY_GUARD, /unhandledrejection/)
assert.doesNotMatch(PLUGIN_RECOVERY_GUARD, /Failed to load plugins/)
assert.doesNotMatch(PLUGIN_RECOVERY_GUARD, /localStorage/)
})
test('Gateway session guard reloads DSH pages only after Access Manager rejects the session', () => {
assert.doesNotThrow(() => new Function(SESSION_VALIDITY_GUARD.slice('<script>'.length, -'</script>'.length)))
assert.match(SESSION_VALIDITY_GUARD, /auth\/session-context/)
assert.match(SESSION_VALIDITY_GUARD, /response\.status===401/)
assert.doesNotMatch(SESSION_VALIDITY_GUARD, /innerText|textContent/)
})
test('plugin recovery guard catches official and third-party dynamic import failures', async () => {
for (const [path, pluginId] of [
['/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js?rev=abc123', '@deepseek-ai/dsh-client-ui-input-trigger'],
['/plugins/community-plugin/client.js?rev=def456', 'community-plugin'],
]) {
const result = await simulatePluginError(path)
assert.match(result.replacement, /^\/_dsh_gateway\/wait\?return=/)
assert.deepEqual(result.events.map(value => [value.event, value.pluginId]), [
['browser.plugin-load.failed', pluginId],
['browser.plugin-load.recovery.started', pluginId],
])
}
})
test('plugin recovery guard retries twice and opens the Gateway failure page after the third failure', async () => {
const path = '/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js?rev=abc123'
const storage = new Map()
const first = await simulatePluginError(path, { storage })
const second = await simulatePluginError(path, { storage })
const third = await simulatePluginError(path, { storage })
assert.match(first.replacement, /^\/_dsh_gateway\/wait\?return=/)
assert.match(second.replacement, /^\/_dsh_gateway\/wait\?return=/)
assert.equal(third.replacement, '/_dsh_gateway/plugin-failure')
assert.equal(first.events.at(-1).recoveryAttempt, 1)
assert.equal(second.events.at(-1).recoveryAttempt, 2)
assert.deepEqual(third.events.map(value => [value.event, value.recoveryAttempt]), [
['browser.plugin-load.recovery.failed', 3],
])
})
test('plugin recovery guard does not inspect page text', async () => {
const result = await simulatePluginError('/plugins/example/client.js?rev=abc123', { eventType: 'none' })
assert.equal(result.replacement, undefined)
assert.deepEqual(result.events, [])
})
test('polyfill is feature guarded and uses no weak random source', () => {
assert.match(RANDOM_UUID_POLYFILL, /typeof c\.randomUUID!=="function"/)
assert.match(RANDOM_UUID_POLYFILL, /c\.getRandomValues/)
assert.doesNotMatch(RANDOM_UUID_POLYFILL, /Math\.random/)
})
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,86 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { parseTrustedHosts } from '../lib/config.mjs'
import { inspectExternalRequest, isLoopbackHostname } from '../lib/trust.mjs'
test('isLoopbackHostname follows DSH loopback semantics', () => {
for (const hostname of ['localhost', '127.0.0.1', '127.255.255.255', '[::1]']) {
assert.equal(isLoopbackHostname(hostname), true, hostname)
}
for (const hostname of ['example.com', '128.0.0.1', '127.0.0.999', '[::2]']) {
assert.equal(isLoopbackHostname(hostname), false, hostname)
}
})
test('empty trusted Hosts accepts loopback only', () => {
const trusted = parseTrustedHosts({})
assert.equal(inspectExternalRequest({ host: '127.0.0.1:3080' }, trusted).accepted, true)
assert.equal(inspectExternalRequest({ host: 'localhost:3080' }, trusted).accepted, true)
assert.deepEqual(inspectExternalRequest({ host: '192.168.1.10:3080' }, trusted), {
accepted: false,
reason: 'untrusted-host',
})
})
test('trusted Hosts match optional ports and wildcard', () => {
const trusted = parseTrustedHosts({
DSH_TRUSTED_HOSTS: 'lan.example,exact.example:8443,default.example:80',
})
assert.equal(inspectExternalRequest({ host: 'lan.example:9999' }, trusted).accepted, true)
assert.equal(inspectExternalRequest({ host: 'exact.example:8443' }, trusted).accepted, true)
assert.equal(inspectExternalRequest({ host: 'exact.example:3080' }, trusted).accepted, false)
assert.equal(inspectExternalRequest({ host: 'default.example' }, trusted).accepted, true)
assert.equal(inspectExternalRequest({ host: 'default.example:80' }, trusted).accepted, true)
const wildcard = parseTrustedHosts({ DSH_TRUSTED_HOSTS: '*' })
assert.equal(inspectExternalRequest({ host: 'anything.example' }, wildcard).accepted, true)
})
test('request inspection rejects cross-site and mismatched origins', () => {
const trusted = parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'dsh.example' })
assert.deepEqual(inspectExternalRequest({
host: 'dsh.example',
'sec-fetch-site': 'cross-site',
}, trusted), { accepted: false, reason: 'cross-site' })
assert.deepEqual(inspectExternalRequest({
host: 'dsh.example',
origin: 'https://evil.example',
}, trusted), { accepted: false, reason: 'origin-mismatch' })
assert.equal(inspectExternalRequest({
host: 'dsh.example',
origin: 'https://dsh.example',
'sec-fetch-site': 'same-origin',
}, trusted).accepted, true)
})
test('explicit cross-origin inspection still requires a trusted Host', () => {
const trusted = parseTrustedHosts({ DSH_TRUSTED_HOSTS: 'management.example' })
assert.equal(inspectExternalRequest({
host: 'management.example',
origin: 'https://dsh.example',
'sec-fetch-site': 'cross-site',
}, trusted, { allowCrossOrigin: true }).accepted, true)
assert.equal(inspectExternalRequest({
host: 'untrusted.example',
origin: 'https://dsh.example',
'sec-fetch-site': 'cross-site',
}, trusted, { allowCrossOrigin: true }).accepted, false)
})
test('request inspection rejects missing and malformed browser authorities', () => {
const trusted = parseTrustedHosts({ DSH_TRUSTED_HOSTS: '*' })
assert.deepEqual(inspectExternalRequest({}, trusted), { accepted: false, reason: 'missing-host' })
assert.deepEqual(inspectExternalRequest({ host: 'bad host' }, trusted), {
accepted: false,
reason: 'invalid-host',
})
for (const host of ['ok.example/path', 'user@ok.example', 'ok.example?', 'ok.example#x', 'ok.example:']) {
assert.deepEqual(inspectExternalRequest({ host }, trusted), {
accepted: false,
reason: 'invalid-host',
}, host)
}
assert.deepEqual(inspectExternalRequest({ host: 'ok.example', origin: 'null' }, trusted), {
accepted: false,
reason: 'invalid-origin',
})
})