dsh-mobile 0.3.2 → 0.3.3
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 +11 -0
- package/FUNNEL_THIRD_PARTY_LICENSES.txt +2551 -0
- package/README.en.md +18 -9
- package/README.md +16 -7
- package/SECURITY.md +6 -3
- package/THIRD_PARTY_NOTICES.md +6 -2
- package/bin/dsh-mobile-funnel-win32-x64.exe +0 -0
- package/lib/cli.js +4 -1
- package/lib/cli.js.map +1 -0
- package/lib/client.js +690 -52
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +227 -2
- package/lib/index.mjs +1717 -169
- package/lib/index.mjs.map +1 -0
- package/package.json +10 -6
- package/assets/brand/app-icon-master.png +0 -0
- package/assets/brand/repository-hero.png +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["execFile","execFileCallback","regularFile","createHttpsServer","createHttpServer","requestHttp","request","inside","regularFile","sha256","defaultExtractArtifact","defaultFetchArtifact","hostname","START_TIMEOUT_MS","publicStatus","DEFAULT_VHOST_HTTP_PORT","execFile","execFileCallback","publicStatus","execFile","execFileCallback"],"sources":["../src/access.ts","../src/network.ts","../src/config.ts","../src/compatibility.ts","../src/private-file.ts","../src/control.ts","../src/http-security.ts","../src/version.ts","../src/computer-images.ts","../src/extensions.ts","../src/gateway.ts","../src/storage.ts","../src/frp-component.ts","../src/frp-template.ts","../src/frp-config.ts","../src/remote.ts","../src/frp.ts","../src/diagnostics.ts","../src/mobile-guide.ts","../src/funnel.ts","../src/cpolar.ts","../src/cpolar-component.ts","../src/release-update.ts","../src/managed-setup.ts","../src/plugin.ts"],"sourcesContent":["import { createHash, randomBytes, timingSafeEqual } from 'node:crypto'\nimport type { DeviceSnapshot, DeviceStore, StoredDevice } from './storage.js'\n\n/** Stable error categories converted to deliberately terse HTTP responses. */\nexport class AccessError extends Error {\n constructor(readonly status: number, readonly code: string) {\n super(code)\n this.name = 'AccessError'\n }\n}\n\n/** Resource and lifetime controls for device authentication. */\nexport interface AccessControllerOptions {\n readonly pairingTtlMs: number\n readonly deviceTtlMs: number\n readonly sessionTtlMs: number\n readonly maxDevices: number\n readonly maxSessions: number\n readonly rateLimitWindowMs: number\n readonly maxPairingAttempts: number\n readonly maxRateLimitKeys: number\n readonly now?: () => number\n}\n\n/** Values issued once after pairing; only digests survive the response. */\nexport interface PairingResult {\n readonly deviceId: string\n readonly deviceToken: string\n readonly deviceExpiresAt: number\n readonly sessionToken: string\n readonly csrfToken: string\n readonly sessionExpiresAt: number\n}\n\n/** Values issued after renewal with the persistent HttpOnly device Cookie. */\nexport interface RenewalResult {\n readonly deviceId: string\n readonly sessionToken: string\n readonly csrfToken: string\n readonly sessionExpiresAt: number\n}\n\n/** Authenticated Session identity retained only inside the gateway. */\nexport interface SessionAuthorization {\n readonly sessionKey: string\n readonly deviceId: string\n readonly expiresAt: number\n}\n\n/** Safe device metadata returned by the loopback administration API. */\nexport interface DeviceSummary {\n readonly id: string\n readonly label: string\n readonly createdAt: number\n readonly expiresAt: number\n readonly lastSeenAt: number\n readonly revokedAt?: number\n}\n\ninterface PairingWindow {\n readonly digest: Buffer\n readonly expiresAt: number\n}\n\ninterface SessionRecord {\n readonly key: string\n readonly deviceId: string\n readonly csrfDigest: Buffer\n readonly createdAt: number\n readonly expiresAt: number\n}\n\ninterface LimitBucket {\n count: number\n resetAt: number\n}\n\n/** Fixed-window limiter whose attacker-controlled key table is itself bounded. */\nexport class BoundedRateLimiter {\n private readonly buckets = new Map<string, LimitBucket>()\n\n constructor(\n private readonly limit: number,\n private readonly windowMs: number,\n private readonly maximumKeys: number,\n ) {}\n\n /** Consume one attempt; unknown keys fail closed when the bounded table is full. */\n take(key: string, now: number): boolean {\n for (const [candidate, bucket] of this.buckets) {\n if (bucket.resetAt <= now) this.buckets.delete(candidate)\n }\n const current = this.buckets.get(key)\n if (current === undefined) {\n if (this.buckets.size >= this.maximumKeys) return false\n this.buckets.set(key, { count: 1, resetAt: now + this.windowMs })\n return true\n }\n if (current.count >= this.limit) return false\n current.count += 1\n return true\n }\n\n /** Current table size, exposed for bounded-state assertions. */\n get size(): number {\n return this.buckets.size\n }\n}\n\nfunction opaqueToken(): string {\n return randomBytes(32).toString('base64url')\n}\n\nfunction digest(value: string): Buffer {\n return createHash('sha256').update(value, 'utf8').digest()\n}\n\nfunction digestHex(value: string): string {\n return digest(value).toString('hex')\n}\n\nfunction matchesDigest(value: string, expected: Buffer): boolean {\n return timingSafeEqual(digest(value), expected)\n}\n\nfunction normalizeLabel(value: string | undefined): string {\n const label = (value ?? 'Mobile device').normalize('NFC').trim()\n if (label.length < 1 || label.length > 64 || /[\\u0000-\\u001f\\u007f]/u.test(label)) {\n throw new AccessError(400, 'invalid_request')\n }\n return label\n}\n\nfunction publicDevice(device: StoredDevice): DeviceSummary {\n return Object.freeze({\n id: device.id,\n label: device.label,\n createdAt: device.createdAt,\n expiresAt: device.expiresAt,\n lastSeenAt: device.lastSeenAt,\n ...(device.revokedAt === undefined ? {} : { revokedAt: device.revokedAt }),\n })\n}\n\n/** Pairing, persistent-device, short-Session, revocation, and CSRF state machine. */\nexport class AccessController {\n private readonly now: () => number\n private readonly pairLimiter: BoundedRateLimiter\n private devices: StoredDevice[] = []\n private pairingWindow: PairingWindow | undefined\n private readonly sessions = new Map<string, SessionRecord>()\n private readonly sessionEndedListeners = new Set<(authorization: SessionAuthorization) => void>()\n private mutation: Promise<void> = Promise.resolve()\n private initialized = false\n private closing = false\n private closeTask: Promise<void> | undefined\n\n constructor(private readonly store: DeviceStore, private readonly options: AccessControllerOptions) {\n this.now = options.now ?? Date.now\n this.pairLimiter = new BoundedRateLimiter(\n options.maxPairingAttempts,\n options.rateLimitWindowMs,\n options.maxRateLimitKeys,\n )\n }\n\n /** Load and validate digest-only durable state before accepting traffic. */\n async initialize(): Promise<void> {\n if (this.initialized || this.closing) throw new Error('access controller cannot be initialized again')\n const snapshot = await this.store.load()\n if (snapshot.devices.length > this.options.maxDevices) throw new Error('device state exceeds configured maxDevices')\n this.devices = [...snapshot.devices]\n this.initialized = true\n }\n\n private requireInitialized(): void {\n if (!this.initialized || this.closing) throw new Error('access controller is not available')\n }\n\n private async exclusive<T>(operation: () => Promise<T>): Promise<T> {\n const prior = this.mutation\n let release!: () => void\n this.mutation = new Promise<void>(resolve => { release = resolve })\n await prior\n try {\n return await operation()\n } finally {\n release()\n }\n }\n\n private snapshot(devices: readonly StoredDevice[]): DeviceSnapshot {\n return Object.freeze({ version: 1, devices: Object.freeze([...devices]) })\n }\n\n private emitSessionEnded(session: SessionRecord): void {\n const authorization = Object.freeze({\n sessionKey: session.key,\n deviceId: session.deviceId,\n expiresAt: session.expiresAt,\n })\n for (const listener of this.sessionEndedListeners) listener(authorization)\n }\n\n private removeSession(key: string): void {\n const session = this.sessions.get(key)\n if (session === undefined) return\n this.sessions.delete(key)\n this.emitSessionEnded(session)\n }\n\n private pruneSessions(now: number): void {\n for (const [key, session] of this.sessions) {\n if (session.expiresAt <= now) this.removeSession(key)\n }\n }\n\n private createSession(deviceId: string, now: number, deviceExpiresAt: number): RenewalResult {\n this.pruneSessions(now)\n if (this.sessions.size >= this.options.maxSessions) {\n const oldest = [...this.sessions.values()].sort((left, right) => left.createdAt - right.createdAt)[0]\n if (oldest !== undefined) this.removeSession(oldest.key)\n }\n const sessionToken = opaqueToken()\n const csrfToken = opaqueToken()\n const key = digestHex(sessionToken)\n const record: SessionRecord = Object.freeze({\n key,\n deviceId,\n csrfDigest: digest(csrfToken),\n createdAt: now,\n expiresAt: Math.min(now + this.options.sessionTtlMs, deviceExpiresAt),\n })\n this.sessions.set(key, record)\n return Object.freeze({ deviceId, sessionToken, csrfToken, sessionExpiresAt: record.expiresAt })\n }\n\n /** Open one short pairing window and return its one-time secret to a loopback caller only. */\n async openPairing(requestedTtlMs?: number): Promise<{ token: string; expiresAt: number }> {\n this.requireInitialized()\n return this.exclusive(async () => {\n const ttl = requestedTtlMs ?? this.options.pairingTtlMs\n if (!Number.isSafeInteger(ttl) || ttl < 10_000 || ttl > this.options.pairingTtlMs) {\n throw new AccessError(400, 'invalid_request')\n }\n const token = opaqueToken()\n const expiresAt = this.now() + ttl\n this.pairingWindow = Object.freeze({ digest: digest(token), expiresAt })\n return Object.freeze({ token, expiresAt })\n })\n }\n\n /** Consume the pairing window exactly once and persist only the device-token digest. */\n async pair(sourceKey: string, token: string, label?: string): Promise<PairingResult> {\n this.requireInitialized()\n const now = this.now()\n if (!this.pairLimiter.take(sourceKey, now)) throw new AccessError(429, 'rate_limited')\n if (token.length > 512) throw new AccessError(401, 'authentication_failed')\n return this.exclusive(async () => {\n const window = this.pairingWindow\n if (window === undefined || window.expiresAt <= now || !matchesDigest(token, window.digest)) {\n if (window !== undefined && window.expiresAt <= now) this.pairingWindow = undefined\n throw new AccessError(401, 'authentication_failed')\n }\n this.pairingWindow = undefined\n const active = this.devices.filter(device => device.revokedAt === undefined && device.expiresAt > now)\n if (active.length >= this.options.maxDevices) throw new AccessError(409, 'device_limit')\n\n const deviceToken = opaqueToken()\n const device: StoredDevice = Object.freeze({\n id: randomBytes(16).toString('hex'),\n label: normalizeLabel(label),\n tokenDigest: digestHex(deviceToken),\n createdAt: now,\n expiresAt: now + this.options.deviceTtlMs,\n lastSeenAt: now,\n })\n const retained = this.devices.filter(candidate => candidate.revokedAt === undefined && candidate.expiresAt > now)\n const next = [...retained, device]\n await this.store.save(this.snapshot(next))\n this.devices = next\n const session = this.createSession(device.id, now, device.expiresAt)\n return Object.freeze({\n ...session,\n deviceToken,\n deviceExpiresAt: device.expiresAt,\n })\n })\n }\n\n /** Exchange a valid persistent device credential for a new short Session. */\n async renew(deviceToken: string): Promise<RenewalResult> {\n this.requireInitialized()\n if (deviceToken.length > 512) throw new AccessError(401, 'authentication_failed')\n return this.exclusive(async () => {\n const now = this.now()\n const tokenDigest = digest(deviceToken)\n const index = this.devices.findIndex(device => timingSafeEqual(Buffer.from(device.tokenDigest, 'hex'), tokenDigest))\n const device = this.devices[index]\n if (device === undefined || device.revokedAt !== undefined || device.expiresAt <= now) {\n throw new AccessError(401, 'authentication_failed')\n }\n const updated: StoredDevice = Object.freeze({ ...device, lastSeenAt: now })\n const next = [...this.devices]\n next[index] = updated\n await this.store.save(this.snapshot(next))\n this.devices = next\n return this.createSession(device.id, now, device.expiresAt)\n })\n }\n\n /** Resolve a short Session Cookie without revealing whether device or Session failed. */\n authorizeSession(sessionToken: string): SessionAuthorization {\n this.requireInitialized()\n if (sessionToken.length > 512) throw new AccessError(401, 'authentication_failed')\n const now = this.now()\n this.pruneSessions(now)\n const key = digestHex(sessionToken)\n const session = this.sessions.get(key)\n const device = session === undefined ? undefined : this.devices.find(candidate => candidate.id === session.deviceId)\n if (session === undefined || device === undefined || device.revokedAt !== undefined || device.expiresAt <= now) {\n if (session !== undefined) this.removeSession(session.key)\n throw new AccessError(401, 'authentication_failed')\n }\n return Object.freeze({ sessionKey: key, deviceId: session.deviceId, expiresAt: session.expiresAt })\n }\n\n /** Require the Session-bound anti-CSRF value for an authenticated mutation. */\n assertCsrf(authorization: SessionAuthorization, csrfToken: string | undefined): void {\n const session = this.sessions.get(authorization.sessionKey)\n if (session === undefined || csrfToken === undefined || csrfToken.length > 512\n || !matchesDigest(csrfToken, session.csrfDigest)) {\n throw new AccessError(403, 'forbidden')\n }\n }\n\n /** End one short Session and notify the gateway to abort its attached work. */\n logout(authorization: SessionAuthorization): void {\n this.removeSession(authorization.sessionKey)\n }\n\n /** Persist revocation, then end every Session owned by that device. */\n async revokeDevice(deviceId: string): Promise<boolean> {\n this.requireInitialized()\n return this.exclusive(async () => {\n const index = this.devices.findIndex(device => device.id === deviceId)\n const device = this.devices[index]\n if (device === undefined || device.revokedAt !== undefined) return false\n const next = [...this.devices]\n next[index] = Object.freeze({ ...device, revokedAt: this.now() })\n await this.store.save(this.snapshot(next))\n this.devices = next\n for (const [key, session] of this.sessions) {\n if (session.deviceId === deviceId) this.removeSession(key)\n }\n return true\n })\n }\n\n /** Remove every persistent credential and terminate every active Session. */\n async resetDevices(): Promise<void> {\n this.requireInitialized()\n await this.exclusive(async () => {\n await this.store.save(this.snapshot([]))\n this.devices = []\n for (const key of [...this.sessions.keys()]) this.removeSession(key)\n this.pairingWindow = undefined\n })\n }\n\n /** Safe metadata for the loopback administration surface. */\n listDevices(): readonly DeviceSummary[] {\n this.requireInitialized()\n return Object.freeze(this.devices.map(publicDevice))\n }\n\n /** Pairing status without exposing the one-time secret. */\n pairingStatus(): { open: boolean; expiresAt?: number } {\n this.requireInitialized()\n const window = this.pairingWindow\n if (window === undefined || window.expiresAt <= this.now()) {\n this.pairingWindow = undefined\n return Object.freeze({ open: false })\n }\n return Object.freeze({ open: true, expiresAt: window.expiresAt })\n }\n\n /** Subscribe gateway resources to Session logout, expiry, eviction, and device revocation. */\n onSessionEnded(listener: (authorization: SessionAuthorization) => void): () => void {\n this.sessionEndedListeners.add(listener)\n return () => { this.sessionEndedListeners.delete(listener) }\n }\n\n /** Stop new operations, drain durable mutations, then clear volatile credentials. */\n close(): Promise<void> {\n if (this.closeTask !== undefined) return this.closeTask\n this.closing = true\n this.closeTask = this.finishClose()\n return this.closeTask\n }\n\n private async finishClose(): Promise<void> {\n await this.mutation\n this.pairingWindow = undefined\n for (const key of [...this.sessions.keys()]) this.removeSession(key)\n this.sessionEndedListeners.clear()\n this.initialized = false\n }\n\n /** Bounded volatile-state metrics for tests and local status. */\n metrics(): { sessions: number; rateLimitKeys: number } {\n return Object.freeze({ sessions: this.sessions.size, rateLimitKeys: this.pairLimiter.size })\n }\n}\n","import { isIP } from 'node:net'\n\n/** A parsed IP network used to authorize directly connected clients. */\nexport interface ParsedCidr {\n readonly bits: 32 | 128\n readonly network: bigint\n readonly prefix: number\n readonly source: string\n}\n\n/** A normalized public authority. A missing port is filled from the bound listener. */\nexport interface AuthoritySpec {\n readonly hostname: string\n readonly port?: number\n}\n\nfunction parseIpv4(address: string): bigint {\n const parts = address.split('.')\n if (parts.length !== 4) throw new Error(`invalid IPv4 address ${JSON.stringify(address)}`)\n let value = 0n\n for (const part of parts) {\n if (!/^\\d{1,3}$/u.test(part)) throw new Error(`invalid IPv4 address ${JSON.stringify(address)}`)\n const octet = Number(part)\n if (octet > 255) throw new Error(`invalid IPv4 address ${JSON.stringify(address)}`)\n value = (value << 8n) | BigInt(octet)\n }\n return value\n}\n\nfunction parseIpv6Part(part: string, address: string): number[] {\n if (part.includes('.')) {\n const ipv4 = parseIpv4(part)\n return [Number((ipv4 >> 16n) & 0xffffn), Number(ipv4 & 0xffffn)]\n }\n if (!/^[\\da-f]{1,4}$/iu.test(part)) throw new Error(`invalid IPv6 address ${JSON.stringify(address)}`)\n return [Number.parseInt(part, 16)]\n}\n\nfunction parseIpv6(address: string): bigint {\n const withoutZone = address.split('%', 1)[0] ?? address\n if (withoutZone.split('::').length > 2) throw new Error(`invalid IPv6 address ${JSON.stringify(address)}`)\n const [leftText, rightText] = withoutZone.split('::')\n const left = leftText === '' ? [] : leftText!.split(':').flatMap(part => parseIpv6Part(part, address))\n const right = rightText === undefined || rightText === ''\n ? []\n : rightText.split(':').flatMap(part => parseIpv6Part(part, address))\n const omitted = 8 - left.length - right.length\n if (rightText === undefined ? omitted !== 0 : omitted < 1) {\n throw new Error(`invalid IPv6 address ${JSON.stringify(address)}`)\n }\n const groups = [...left, ...Array.from({ length: omitted }, () => 0), ...right]\n if (groups.length !== 8) throw new Error(`invalid IPv6 address ${JSON.stringify(address)}`)\n return groups.reduce((value, group) => (value << 16n) | BigInt(group), 0n)\n}\n\nfunction mappedIpv4(address: string): string | undefined {\n const match = /^::ffff:(\\d{1,3}(?:\\.\\d{1,3}){3})$/iu.exec(address)\n return match?.[1]\n}\n\nfunction parseIp(address: string): { bits: 32 | 128; value: bigint } {\n const unwrapped = address.startsWith('[') && address.endsWith(']') ? address.slice(1, -1) : address\n const mapped = mappedIpv4(unwrapped)\n if (mapped !== undefined) return { bits: 32, value: parseIpv4(mapped) }\n const version = isIP(unwrapped.split('%', 1)[0] ?? unwrapped)\n if (version === 4) return { bits: 32, value: parseIpv4(unwrapped) }\n if (version === 6) return { bits: 128, value: parseIpv6(unwrapped) }\n throw new Error(`invalid IP address ${JSON.stringify(address)}`)\n}\n\n/** Parse and canonicalize one IPv4 or IPv6 CIDR. */\nexport function parseCidr(source: string): ParsedCidr {\n const slash = source.lastIndexOf('/')\n if (slash <= 0 || slash === source.length - 1) throw new Error(`invalid CIDR ${JSON.stringify(source)}`)\n const address = source.slice(0, slash)\n const parsed = parseIp(address)\n const prefixText = source.slice(slash + 1)\n if (!/^\\d{1,3}$/u.test(prefixText)) throw new Error(`invalid CIDR ${JSON.stringify(source)}`)\n const prefix = Number(prefixText)\n if (prefix > parsed.bits) throw new Error(`invalid CIDR ${JSON.stringify(source)}`)\n const hostBits = BigInt(parsed.bits - prefix)\n const mask = hostBits === BigInt(parsed.bits)\n ? 0n\n : ((1n << BigInt(parsed.bits)) - 1n) ^ ((1n << hostBits) - 1n)\n const network = parsed.value & mask\n if (network !== parsed.value) {\n throw new Error(`CIDR ${JSON.stringify(source)} has host bits set`)\n }\n return Object.freeze({ bits: parsed.bits, network, prefix, source })\n}\n\n/** Whether a directly connected socket address belongs to at least one allowed CIDR. */\nexport function addressAllowed(address: string | undefined, cidrs: readonly ParsedCidr[]): boolean {\n if (address === undefined) return false\n let parsed: ReturnType<typeof parseIp>\n try {\n parsed = parseIp(address)\n } catch {\n return false\n }\n return cidrs.some((cidr) => {\n if (cidr.bits !== parsed.bits) return false\n const hostBits = BigInt(cidr.bits - cidr.prefix)\n const mask = hostBits === BigInt(cidr.bits)\n ? 0n\n : ((1n << BigInt(cidr.bits)) - 1n) ^ ((1n << hostBits) - 1n)\n return (parsed.value & mask) === cidr.network\n })\n}\n\n/** Whether an IP literal is loopback and therefore eligible for HTTP-only development. */\nexport function isLoopbackAddress(address: string): boolean {\n try {\n const parsed = parseIp(address)\n if (parsed.bits === 32) return (parsed.value >> 24n) === 127n\n return parsed.value === 1n\n } catch {\n return false\n }\n}\n\n/** Parse a bare host or host:port authority without accepting URL components. */\nexport function parseAuthority(source: string): AuthoritySpec {\n if (source.trim() !== source || source.length === 0 || /[/?#@\\\\]/u.test(source)) {\n throw new Error(`invalid public authority ${JSON.stringify(source)}`)\n }\n let url: URL\n try {\n url = new URL(`https://${source}`)\n } catch {\n throw new Error(`invalid public authority ${JSON.stringify(source)}`)\n }\n if (url.username !== '' || url.password !== '' || url.pathname !== '/' || url.search !== '' || url.hash !== '') {\n throw new Error(`invalid public authority ${JSON.stringify(source)}`)\n }\n const explicitPort = /\\]:\\d+$/u.test(source) || (!source.startsWith('[') && /:\\d+$/u.test(source))\n const hostname = url.hostname.toLowerCase()\n const port = explicitPort ? Number(url.port === '' ? 443 : url.port) : undefined\n if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65535)) {\n throw new Error(`invalid public authority ${JSON.stringify(source)}`)\n }\n return port === undefined ? Object.freeze({ hostname }) : Object.freeze({ hostname, port })\n}\n\nfunction formatHostname(hostname: string): string {\n return hostname.includes(':') && !hostname.startsWith('[') ? `[${hostname}]` : hostname\n}\n\n/** Resolve an authority against the actual listener port. */\nexport function resolveAuthority(spec: AuthoritySpec, listenerPort: number): string {\n return `${formatHostname(spec.hostname)}:${String(spec.port ?? listenerPort)}`\n}\n\n/** Exact Host/Origin/CIDR policy for the directly exposed listener. */\nexport class RequestTrustPolicy {\n readonly authorities: ReadonlySet<string>\n readonly origins: ReadonlySet<string>\n private readonly scheme: 'http' | 'https'\n\n constructor(\n specs: readonly AuthoritySpec[],\n listenerPort: number,\n readonly cidrs: readonly ParsedCidr[],\n tls: boolean,\n ) {\n this.scheme = tls ? 'https' : 'http'\n this.authorities = new Set(specs.map(spec => resolveAuthority(spec, listenerPort).toLowerCase()))\n this.origins = new Set([...this.authorities].map(\n authority => new URL(`${this.scheme}://${authority}`).origin.toLowerCase(),\n ))\n }\n\n /** Validate the exact Host header after WHATWG authority normalization. */\n acceptsHost(header: string | undefined): boolean {\n return this.canonicalHost(header) !== undefined\n }\n\n /** Return the canonical accepted Host authority, otherwise undefined. */\n canonicalHost(header: string | undefined): string | undefined {\n if (header === undefined || /[/?#@\\\\]/u.test(header)) return undefined\n let normalized: string\n try {\n const parsed = new URL(`${this.scheme}://${header}`)\n if (parsed.pathname !== '/' || parsed.username !== '' || parsed.password !== '') return undefined\n normalized = resolveAuthority({\n hostname: parsed.hostname,\n port: Number(parsed.port || (this.scheme === 'https' ? '443' : '80')),\n }, 80).toLowerCase()\n } catch {\n return undefined\n }\n return this.authorities.has(normalized) ? normalized : undefined\n }\n\n /** Validate an exact same-scheme browser Origin. */\n acceptsOrigin(header: string | undefined): boolean {\n return this.canonicalOrigin(header) !== undefined\n }\n\n /** Return the canonical accepted Origin, otherwise undefined. */\n canonicalOrigin(header: string | undefined): string | undefined {\n if (header === undefined) return undefined\n let normalized: string\n try {\n const parsed = new URL(header)\n if (parsed.pathname !== '/' || parsed.search !== '' || parsed.hash !== '' || parsed.username !== '' || parsed.password !== '') {\n return undefined\n }\n normalized = parsed.origin.toLowerCase()\n } catch {\n return undefined\n }\n return this.origins.has(normalized) ? normalized : undefined\n }\n}\n","import { dirname, isAbsolute, join, resolve } from 'node:path'\nimport { createHash } from 'node:crypto'\nimport { fileURLToPath } from 'node:url'\nimport z from '@deepseek-ai/schemastery'\nimport { isIP } from 'node:net'\nimport { isLoopbackAddress, parseAuthority, parseCidr, type AuthoritySpec, type ParsedCidr } from './network.js'\n\n/** TLS source accepted by the LAN listener. */\nexport interface ProvidedTlsConfig {\n readonly mode: 'provided'\n /** PEM server leaf followed by any intermediate certificate chain. */\n readonly certFile: string\n readonly keyFile: string\n /** Optional PEM intermediates appended after the chain in `certFile`; roots are rejected. */\n readonly caFile?: string\n}\n\n/** HTTP is available only for an explicitly loopback-bound listener. */\nexport interface DisabledTlsConfig {\n readonly mode: 'disabled'\n}\n\nexport type TlsConfig = ProvidedTlsConfig | DisabledTlsConfig\n\n/** Operator-facing plugin configuration. */\nexport interface PluginConfig {\n /** Optional setup JSON written by the packaged CLI. */\n setupFile?: string\n /** Preferred HTTPS origin used to derive the public authority and listener port. */\n publicOrigin?: string\n listenHost?: string\n listenPort?: number\n upstreamOrigin?: string\n publicAuthorities?: string[]\n allowedCidrs?: string[]\n stateFile: string\n /** Internal persisted on/off preference managed by the DSH plugin card. */\n controlFile: string\n /** Optional user stylesheet served to the authenticated mobile UI. */\n customCssFile?: string\n /** Optional user script that mounts authenticated mobile-only Web features. */\n customScriptFile?: string\n /** Internal dedicated mobile layout browser bundle. */\n mobileLayoutFile?: string\n /** Stable public discovery identifier; it is not an authentication secret. */\n instanceId?: string\n /** Managed CA certificate offered to the Android installer after fingerprint binding. */\n pairingCaFile?: string\n /** First-run state used only while the control file does not exist. */\n initiallyEnabled: boolean\n tls?: {\n mode?: 'provided' | 'disabled'\n certFile?: string\n keyFile?: string\n caFile?: string\n }\n pairingTtlMs?: number\n deviceTtlMs?: number\n sessionTtlMs?: number\n maxDevices?: number\n maxSessions?: number\n maxConnections?: number\n maxActiveRequests?: number\n maxWebSockets?: number\n maxBodyBytes?: number\n upstreamTimeoutMs?: number\n rateLimitWindowMs?: number\n maxPairingAttempts?: number\n maxRateLimitKeys?: number\n}\n\n/** Resolved, validated security and resource limits. */\nexport interface ResolvedGatewayConfig {\n readonly listenHost: string\n readonly listenPort: number\n readonly upstreamOrigin: URL\n readonly authorities: readonly AuthoritySpec[]\n readonly allowedCidrs: readonly ParsedCidr[]\n readonly stateFile: string\n /** Local extension root adjacent to the mobile-access state file. */\n readonly extensionsDir: string\n readonly customCssFile: string\n readonly customScriptFile: string\n readonly mobileLayoutFile: string\n readonly instanceId: string\n readonly pairingCaFile?: string\n readonly tls: TlsConfig\n /** Whether the public hop is HTTPS, even when a trusted loopback proxy terminates TLS. */\n readonly publicTls: boolean\n /** LAN discovery is disabled for private proxy listeners such as Funnel ingress. */\n readonly discovery: boolean\n readonly pairingTtlMs: number\n readonly deviceTtlMs: number\n readonly sessionTtlMs: number\n readonly maxDevices: number\n readonly maxSessions: number\n readonly maxConnections: number\n readonly maxActiveRequests: number\n readonly maxWebSockets: number\n readonly maxBodyBytes: number\n readonly upstreamTimeoutMs: number\n readonly rateLimitWindowMs: number\n readonly maxPairingAttempts: number\n readonly maxRateLimitKeys: number\n}\n\n/** Loader-facing defaults; {@link parseGatewayConfig} enforces cross-field security rules. */\nexport const Config: z<PluginConfig> = z.object({\n setupFile: z.string().hidden(),\n publicOrigin: z.string(),\n listenHost: z.string(),\n listenPort: z.natural().max(65535),\n upstreamOrigin: z.string(),\n publicAuthorities: z.array(String).default(undefined as unknown as string[]),\n allowedCidrs: z.array(String).default(undefined as unknown as string[]),\n stateFile: String,\n controlFile: z.string().hidden().required(),\n customCssFile: z.string().hidden(),\n customScriptFile: z.string().hidden(),\n mobileLayoutFile: z.string().hidden(),\n instanceId: z.string().hidden(),\n pairingCaFile: z.string().hidden(),\n initiallyEnabled: z.boolean().hidden().required(),\n tls: z.object({\n mode: z.union([z.const('provided'), z.const('disabled')]),\n certFile: z.string(),\n keyFile: z.string(),\n caFile: z.string(),\n }),\n pairingTtlMs: z.natural(),\n deviceTtlMs: z.natural(),\n sessionTtlMs: z.natural(),\n maxDevices: z.natural(),\n maxSessions: z.natural(),\n maxConnections: z.natural(),\n maxActiveRequests: z.natural(),\n maxWebSockets: z.natural(),\n maxBodyBytes: z.natural(),\n upstreamTimeoutMs: z.natural(),\n rateLimitWindowMs: z.natural(),\n maxPairingAttempts: z.natural(),\n maxRateLimitKeys: z.natural(),\n})\n\nfunction integer(value: unknown, name: string, fallback: number, minimum: number, maximum: number): number {\n const resolved = value ?? fallback\n if (typeof resolved !== 'number' || !Number.isSafeInteger(resolved) || resolved < minimum || resolved > maximum) {\n throw new Error(`${name} must be an integer from ${String(minimum)} through ${String(maximum)}`)\n }\n return resolved\n}\n\nfunction stringArray(value: unknown, name: string): string[] {\n if (!Array.isArray(value) || value.length === 0 || value.some(entry => typeof entry !== 'string')) {\n throw new Error(`${name} must be a non-empty string array`)\n }\n return value as string[]\n}\n\nfunction absoluteFile(value: unknown, name: string): string {\n if (typeof value !== 'string' || value.length === 0 || !isAbsolute(value)) {\n throw new Error(`${name} must be an absolute file path`)\n }\n return resolve(value)\n}\n\n/** Resolve the hidden runtime-control file independently from gateway configuration. */\nexport function parseControlFile(value: unknown): string {\n return absoluteFile(value, 'controlFile')\n}\n\nfunction parseUpstream(value: unknown): URL {\n const source = value ?? 'http://127.0.0.1:3080'\n if (typeof source !== 'string') throw new Error('upstreamOrigin must be a string')\n let url: URL\n try {\n url = new URL(source)\n } catch {\n throw new Error('upstreamOrigin must be an HTTP loopback origin')\n }\n if (url.protocol !== 'http:' || !isLoopbackAddress(url.hostname) || url.username !== '' || url.password !== ''\n || url.pathname !== '/' || url.search !== '' || url.hash !== '' || url.port === '') {\n throw new Error('upstreamOrigin must be an HTTP loopback origin with an explicit port and no path or credentials')\n }\n return url\n}\n\nfunction parsePublicOrigin(value: unknown): { readonly authority: AuthoritySpec; readonly port: number } | undefined {\n if (value === undefined) return undefined\n if (typeof value !== 'string' || value.length === 0 || value.trim() !== value) {\n throw new Error('publicOrigin must be an HTTPS origin')\n }\n let url: URL\n try {\n url = new URL(value)\n } catch {\n throw new Error('publicOrigin must be an HTTPS origin')\n }\n if (url.protocol !== 'https:' || url.username !== '' || url.password !== ''\n || url.pathname !== '/' || url.search !== '' || url.hash !== '') {\n throw new Error('publicOrigin must be an HTTPS origin with no path or credentials')\n }\n if (url.hostname === '0.0.0.0' || url.hostname === '[::]') {\n throw new Error('publicOrigin must name a reachable host')\n }\n return Object.freeze({\n authority: parseAuthority(url.host),\n port: Number(url.port || '443'),\n })\n}\n\nfunction parseTls(value: PluginConfig['tls'], listenHost: string): TlsConfig {\n const mode = value?.mode ?? 'provided'\n if (mode === 'disabled') {\n if (!isLoopbackAddress(listenHost)) throw new Error('TLS may be disabled only on an IP loopback listener')\n return Object.freeze({ mode })\n }\n return Object.freeze({\n mode,\n certFile: absoluteFile(value?.certFile, 'tls.certFile'),\n keyFile: absoluteFile(value?.keyFile, 'tls.keyFile'),\n ...(value?.caFile === undefined ? {} : { caFile: absoluteFile(value.caFile, 'tls.caFile') }),\n })\n}\n\n/** Parse configuration and reject unsafe topology, credential, and resource combinations. */\nexport function parseGatewayConfig(raw: unknown): ResolvedGatewayConfig {\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) throw new Error('mobile-access config must be an object')\n const value = raw as PluginConfig\n const publicOrigin = parsePublicOrigin(value.publicOrigin)\n if (publicOrigin !== undefined && value.listenPort !== undefined) {\n throw new Error('publicOrigin cannot be combined with listenPort')\n }\n if (publicOrigin !== undefined && value.publicAuthorities !== undefined) {\n throw new Error('publicOrigin cannot be combined with publicAuthorities')\n }\n const listenHost = value.listenHost ?? (publicOrigin === undefined ? '127.0.0.1' : '0.0.0.0')\n if (isIP(listenHost) === 0) throw new Error('listenHost must be an IP literal')\n const listenPort = publicOrigin?.port ?? integer(value.listenPort, 'listenPort', 3443, 0, 65535)\n const upstreamOrigin = parseUpstream(value.upstreamOrigin)\n const tls = parseTls(value.tls, listenHost)\n if (publicOrigin !== undefined && tls.mode !== 'provided') {\n throw new Error('publicOrigin requires TLS')\n }\n\n let authorities: AuthoritySpec[]\n if (publicOrigin !== undefined) {\n authorities = [publicOrigin.authority]\n } else {\n let authoritySources = value.publicAuthorities\n if (authoritySources === undefined || authoritySources.length === 0) {\n if (!isLoopbackAddress(listenHost)) throw new Error('publicAuthorities is required for a non-loopback listener')\n authoritySources = [listenHost]\n }\n authorities = authoritySources.map(parseAuthority)\n }\n for (const authority of authorities) {\n if (listenPort === 0 && authority.port !== undefined) {\n throw new Error('explicit public authority ports require a non-zero listenPort')\n }\n if (authority.port !== undefined && listenPort !== 0 && authority.port !== listenPort) {\n throw new Error('every explicit public authority port must equal listenPort')\n }\n }\n if (new Set(authorities.map(entry => `${entry.hostname}:${String(entry.port ?? listenPort)}`)).size !== authorities.length) {\n throw new Error('publicAuthorities must not contain duplicates')\n }\n\n const cidrSources = value.allowedCidrs\n ?? (isLoopbackAddress(listenHost) ? ['127.0.0.0/8', '::1/128'] : undefined)\n const allowedCidrs = stringArray(cidrSources, 'allowedCidrs').map(parseCidr)\n if (new Set(allowedCidrs.map(entry => `${String(entry.bits)}:${entry.network.toString(16)}:${String(entry.prefix)}`)).size !== allowedCidrs.length) {\n throw new Error('allowedCidrs must not contain duplicates')\n }\n const deviceTtlMs = integer(value.deviceTtlMs, 'deviceTtlMs', 90 * 24 * 60 * 60_000, 60_000, 366 * 24 * 60 * 60_000)\n const sessionTtlMs = integer(value.sessionTtlMs, 'sessionTtlMs', 8 * 60 * 60_000, 30_000, 24 * 60 * 60_000)\n if (sessionTtlMs > deviceTtlMs) throw new Error('sessionTtlMs must not exceed deviceTtlMs')\n\n return Object.freeze({\n listenHost,\n listenPort,\n upstreamOrigin,\n authorities: Object.freeze(authorities),\n allowedCidrs: Object.freeze(allowedCidrs),\n stateFile: absoluteFile(value.stateFile, 'stateFile'),\n extensionsDir: join(dirname(absoluteFile(value.stateFile, 'stateFile')), 'extensions'),\n customCssFile: value.customCssFile === undefined\n ? join(dirname(absoluteFile(value.stateFile, 'stateFile')), 'mobile.css')\n : absoluteFile(value.customCssFile, 'customCssFile'),\n customScriptFile: value.customScriptFile === undefined\n ? join(dirname(absoluteFile(value.stateFile, 'stateFile')), 'mobile.js')\n : absoluteFile(value.customScriptFile, 'customScriptFile'),\n mobileLayoutFile: value.mobileLayoutFile === undefined\n ? fileURLToPath(new URL('./mobile-layout.js', import.meta.url))\n : absoluteFile(value.mobileLayoutFile, 'mobileLayoutFile'),\n instanceId: value.instanceId === undefined\n ? createHash('sha256').update(absoluteFile(value.stateFile, 'stateFile')).digest('hex')\n : /^[a-f\\d]{64}$/u.test(value.instanceId)\n ? value.instanceId\n : (() => { throw new Error('instanceId must be a lowercase SHA-256 value') })(),\n ...(value.pairingCaFile === undefined ? {} : { pairingCaFile: absoluteFile(value.pairingCaFile, 'pairingCaFile') }),\n tls,\n publicTls: tls.mode === 'provided',\n discovery: true,\n pairingTtlMs: integer(value.pairingTtlMs, 'pairingTtlMs', 120_000, 10_000, 600_000),\n deviceTtlMs,\n sessionTtlMs,\n maxDevices: integer(value.maxDevices, 'maxDevices', 32, 1, 256),\n maxSessions: integer(value.maxSessions, 'maxSessions', 64, 1, 1024),\n maxConnections: integer(value.maxConnections, 'maxConnections', 64, 1, 1024),\n maxActiveRequests: integer(value.maxActiveRequests, 'maxActiveRequests', 32, 1, 1024),\n maxWebSockets: integer(value.maxWebSockets, 'maxWebSockets', 16, 1, 256),\n maxBodyBytes: integer(value.maxBodyBytes, 'maxBodyBytes', 160 * 1024 * 1024, 1024, 256 * 1024 * 1024),\n upstreamTimeoutMs: integer(value.upstreamTimeoutMs, 'upstreamTimeoutMs', 30_000, 1_000, 300_000),\n rateLimitWindowMs: integer(value.rateLimitWindowMs, 'rateLimitWindowMs', 60_000, 1_000, 3_600_000),\n maxPairingAttempts: integer(value.maxPairingAttempts, 'maxPairingAttempts', 8, 1, 100),\n maxRateLimitKeys: integer(value.maxRateLimitKeys, 'maxRateLimitKeys', 256, 1, 4096),\n })\n}\n","/** DeepSeek Harness prereleases verified by this plugin release. */\nexport const SUPPORTED_DSH_VERSIONS = Object.freeze([\n '0.1.0-rc.5',\n '0.1.0-rc.6',\n '0.1.0-rc.7',\n '0.1.1-rc.2',\n '0.1.2-alpha.1',\n] as const)\n\n/**\n * Reject an unverified DeepSeek Harness Host before opening the LAN listener.\n * @param version - Version reported by the installed DSH WebServer package.\n */\nexport function assertSupportedDshVersion(version: unknown): asserts version is typeof SUPPORTED_DSH_VERSIONS[number] {\n if (typeof version === 'string' && SUPPORTED_DSH_VERSIONS.some(candidate => candidate === version)) return\n throw new Error(`unsupported DeepSeek Harness version ${typeof version === 'string' ? version : '(unknown)'}; supported versions: ${SUPPORTED_DSH_VERSIONS.join(', ')}`)\n}\n","import { execFile as execFileCallback } from 'node:child_process'\nimport { chmod } from 'node:fs/promises'\nimport { promisify } from 'node:util'\n\nconst execFile = promisify(execFileCallback)\nlet userSidTask: Promise<string> | undefined\n\nasync function currentWindowsUserSid(): Promise<string> {\n userSidTask ??= execFile('whoami.exe', ['/user', '/fo', 'csv', '/nh'], {\n encoding: 'utf8',\n windowsHide: true,\n }).then(({ stdout }) => {\n const match = /,\"(S-\\d(?:-\\d+)+)\"\\s*$/u.exec(stdout.trim())\n if (match?.[1] === undefined) throw new Error('unable to resolve the current Windows user SID')\n return match[1]\n })\n return userSidTask\n}\n\n/** Restrict a sensitive regular file to the current user and Windows administrators. */\nexport async function restrictPrivateFile(file: string, mode = 0o600): Promise<void> {\n await chmod(file, mode)\n if (process.platform !== 'win32') return\n const userSid = await currentWindowsUserSid()\n await execFile('icacls.exe', [\n file,\n '/inheritance:r',\n '/grant:r',\n `*${userSid}:(F)`,\n '*S-1-5-18:(F)',\n '*S-1-5-32-544:(F)',\n '/remove:g',\n '*S-1-1-0',\n '*S-1-5-11',\n '*S-1-5-32-545',\n ], { encoding: 'utf8', windowsHide: true })\n}\n","import { randomBytes } from 'node:crypto'\nimport { lstat, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join } from 'node:path'\nimport { restrictPrivateFile } from './private-file.js'\n\n/** Versioned durable preference for the resident mobile-access runtime. */\nexport interface MobileAccessControlState {\n readonly version: 1\n readonly enabled: boolean\n}\n\n/** Persistence seam for the runtime preference. */\nexport interface MobileAccessControlStore {\n load(): Promise<MobileAccessControlState>\n save(state: MobileAccessControlState): Promise<void>\n}\n\n/** One started gateway runtime owned by the controller. */\nexport interface MobileAccessRuntime {\n close(): Promise<void>\n}\n\n/** One address-specific runtime selected from the current LAN state. */\nexport interface MobileAccessRuntimeSelection {\n readonly key: string\n start(): Promise<MobileAccessRuntime>\n}\n\n/** Keeps one runtime aligned with a changing network selection. */\nexport class FollowingMobileAccessRuntime implements MobileAccessRuntime {\n private runtime: MobileAccessRuntime | undefined\n private key: string | undefined\n private queue: Promise<void> = Promise.resolve()\n private closed = false\n private timer: ReturnType<typeof setInterval> | undefined\n\n constructor(\n private readonly select: () => Promise<MobileAccessRuntimeSelection>,\n private readonly onRefreshError: (error: unknown) => void,\n ) {}\n\n /** Start the current selection and optionally poll for later changes. */\n async initialize(refreshIntervalMs?: number): Promise<void> {\n await this.refresh()\n if (refreshIntervalMs === undefined) return\n this.timer = setInterval(() => {\n void this.refresh().catch(this.onRefreshError)\n }, refreshIntervalMs)\n this.timer.unref()\n }\n\n /** Reconcile the active runtime with the latest selection. */\n refresh(): Promise<void> {\n return this.enqueue(async () => {\n if (this.closed) return\n const selection = await this.select()\n if (this.closed || (this.runtime !== undefined && this.key === selection.key)) return\n const previous = this.runtime\n this.runtime = undefined\n this.key = undefined\n if (previous !== undefined) await previous.close()\n this.runtime = await selection.start()\n this.key = selection.key\n })\n }\n\n /** Stop polling and close the most recently selected runtime. */\n close(): Promise<void> {\n if (this.closed) return this.queue\n this.closed = true\n if (this.timer !== undefined) clearInterval(this.timer)\n return this.enqueue(async () => {\n const runtime = this.runtime\n this.runtime = undefined\n this.key = undefined\n if (runtime !== undefined) await runtime.close()\n })\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const run = this.queue.then(operation, operation)\n this.queue = run.then(() => {}, () => {})\n return run\n }\n}\n\n/** Validate control state loaded across the filesystem boundary. */\nexport function parseMobileAccessControlState(value: unknown): MobileAccessControlState {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error('mobile-access control state must be an object')\n }\n const record = value as Record<string, unknown>\n if (record.version !== 1 || typeof record.enabled !== 'boolean'\n || Reflect.ownKeys(record).some(key => key !== 'version' && key !== 'enabled')) {\n throw new Error('mobile-access control state has an unsupported format')\n }\n return Object.freeze({ version: 1, enabled: record.enabled })\n}\n\n/** Atomic JSON store whose absent-file state comes from the installation-time default. */\nexport class JsonMobileAccessControlStore implements MobileAccessControlStore {\n constructor(private readonly file: string, private readonly initiallyEnabled: boolean) {}\n\n async load(): Promise<MobileAccessControlState> {\n let stat\n try {\n stat = await lstat(this.file)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return Object.freeze({ version: 1, enabled: this.initiallyEnabled })\n }\n throw error\n }\n if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 4096) {\n throw new Error('mobile-access control state must be a regular file no larger than 4 KiB')\n }\n await restrictPrivateFile(this.file)\n let parsed: unknown\n try {\n parsed = JSON.parse(await readFile(this.file, 'utf8')) as unknown\n } catch (error) {\n throw new Error('mobile-access control state is not valid JSON', { cause: error })\n }\n return parseMobileAccessControlState(parsed)\n }\n\n async save(state: MobileAccessControlState): Promise<void> {\n const validated = parseMobileAccessControlState(state)\n const directory = dirname(this.file)\n await mkdir(directory, { recursive: true, mode: 0o700 })\n try {\n const current = await lstat(this.file)\n if (!current.isFile() || current.isSymbolicLink()) {\n throw new Error('mobile-access control state target must remain a regular file')\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n const temporary = join(directory, `.${basename(this.file)}.${randomBytes(12).toString('hex')}.tmp`)\n try {\n await writeFile(temporary, `${JSON.stringify(validated)}\\n`, {\n encoding: 'utf8',\n flag: 'wx',\n mode: 0o600,\n })\n await rename(temporary, this.file)\n await restrictPrivateFile(this.file)\n } catch (error) {\n try {\n await rm(temporary, { force: true })\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'control state write and temporary cleanup both failed')\n }\n throw error\n }\n }\n}\n\n/** Serialized persistent lifecycle for the gateway behind the always-loaded Cordis entry. */\nexport class MobileAccessGatewayController {\n private runtime: MobileAccessRuntime | undefined\n private initialized = false\n private closing = false\n private queue: Promise<void> = Promise.resolve()\n private closeTask: Promise<void> | undefined\n\n constructor(\n private readonly store: MobileAccessControlStore,\n private readonly startRuntime: () => Promise<MobileAccessRuntime>,\n ) {}\n\n /** Load the durable preference and start the first runtime when enabled. */\n initialize(): Promise<void> {\n return this.enqueue(async () => {\n if (this.initialized) throw new Error('mobile-access control is already initialized')\n if (this.closing) throw new Error('mobile-access control is closing')\n const state = await this.store.load()\n if (state.enabled) this.runtime = await this.startRuntime()\n this.initialized = true\n })\n }\n\n /** Return the committed in-process runtime state. */\n isRunning(): boolean {\n return this.runtime !== undefined\n }\n\n /** Start or stop the runtime and persist only a successfully committed transition. */\n setRunning(running: boolean): Promise<void> {\n if (this.closing) return Promise.reject(new Error('mobile-access control is closing'))\n return this.enqueue(async () => {\n if (!this.initialized) throw new Error('mobile-access control is not initialized')\n if (this.isRunning() === running) return\n if (running) {\n await this.enable()\n } else {\n await this.disable()\n }\n })\n }\n\n /** Stop the runtime after earlier transitions without changing the restart preference. */\n close(): Promise<void> {\n if (this.closeTask !== undefined) return this.closeTask\n this.closing = true\n this.closeTask = this.enqueue(async () => {\n const runtime = this.runtime\n if (runtime === undefined) return\n await runtime.close()\n this.runtime = undefined\n })\n return this.closeTask\n }\n\n private async enable(): Promise<void> {\n const candidate = await this.startRuntime()\n try {\n await this.store.save({ version: 1, enabled: true })\n } catch (error) {\n try {\n await candidate.close()\n } catch (rollbackError) {\n throw new AggregateError([error, rollbackError], 'enabling mobile access failed and runtime rollback also failed')\n }\n throw error\n }\n this.runtime = candidate\n }\n\n private async disable(): Promise<void> {\n const previous = this.runtime\n if (previous === undefined) return\n await previous.close()\n try {\n await this.store.save({ version: 1, enabled: false })\n } catch (error) {\n try {\n this.runtime = await this.startRuntime()\n } catch (rollbackError) {\n this.runtime = undefined\n throw new AggregateError([error, rollbackError], 'disabling mobile access failed and runtime rollback also failed')\n }\n throw error\n }\n this.runtime = undefined\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const run = this.queue.then(operation, operation)\n this.queue = run.then(() => {}, () => {})\n return run\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { addressAllowed, isLoopbackAddress, RequestTrustPolicy } from './network.js'\n\nexport const DEVICE_COOKIE = 'dsh_ma_device'\nexport const SESSION_COOKIE = 'dsh_ma_session'\nexport const CSRF_COOKIE = 'dsh_ma_csrf'\nexport const CSRF_HEADER = 'x-dsh-mobile-csrf'\nexport const LOCAL_ADMIN_PREFIX = '/api/mobile-access'\nexport const AUTH_PREFIX = '/mobile-access'\nexport const WS_PATHS = new Set(['/api/events.mux', '/api/events.host', '/api/remote.mux'])\n\n/** Terse request failure safe to expose without internal diagnostics. */\nexport class HttpError extends Error {\n constructor(readonly status: number, readonly code: string) {\n super(code)\n this.name = 'HttpError'\n }\n}\n\n/** Parsed origin-form request target with a decoded path for protected-prefix checks. */\nexport interface RequestTarget {\n readonly raw: string\n readonly pathname: string\n readonly decodedPathname: string\n readonly search: string\n}\n\n/** Parse only origin-form request targets and reject ambiguous slash encodings. */\nexport function parseRequestTarget(raw: string | undefined): RequestTarget {\n if (raw === undefined || !raw.startsWith('/') || raw.startsWith('//') || raw.includes('\\\\') || /[\\u0000-\\u001f\\u007f]/u.test(raw)) {\n throw new HttpError(400, 'bad_request')\n }\n let parsed: URL\n let decodedPathname: string\n try {\n parsed = new URL(raw, 'http://gateway.invalid')\n decodedPathname = decodeURIComponent(parsed.pathname)\n } catch {\n throw new HttpError(400, 'bad_request')\n }\n if (decodedPathname.includes('\\\\') || decodedPathname.startsWith('//') || /[\\u0000-\\u001f\\u007f]/u.test(decodedPathname)) {\n throw new HttpError(400, 'bad_request')\n }\n return Object.freeze({ raw, pathname: parsed.pathname, decodedPathname, search: parsed.search })\n}\n\n/** Set the gateway-owned browser protections and non-cacheability. */\nexport function setSecurityHeaders(response: ServerResponse, tls: boolean): void {\n response.setHeader('Cache-Control', 'no-store')\n // DSH emits inline boot code, revives Schemastery callbacks, and applies dynamic styles.\n // These allowances provide compatibility, not XSS isolation.\n response.setHeader('Content-Security-Policy', [\n \"default-src 'self'\",\n \"base-uri 'none'\",\n \"object-src 'none'\",\n \"frame-ancestors 'none'\",\n \"form-action 'self'\",\n \"script-src 'self' 'unsafe-inline' 'unsafe-eval'\",\n \"style-src 'self' 'unsafe-inline'\",\n \"img-src 'self' data: blob:\",\n \"font-src 'self' data:\",\n \"connect-src 'self'\",\n \"worker-src 'self' blob:\",\n ].join('; '))\n response.setHeader('Permissions-Policy', 'camera=(), microphone=(), geolocation=(), payment=(), usb=()')\n response.setHeader('Referrer-Policy', 'no-referrer')\n response.setHeader('X-Content-Type-Options', 'nosniff')\n response.setHeader('X-Frame-Options', 'DENY')\n response.setHeader('Cross-Origin-Resource-Policy', 'same-origin')\n if (tls) response.setHeader('Strict-Transport-Security', 'max-age=31536000')\n}\n\n/** Send a bounded JSON response without reflecting request or upstream data. */\nexport function sendJson(response: ServerResponse, status: number, value: unknown, tls: boolean): void {\n if (response.headersSent || response.destroyed) return\n setSecurityHeaders(response, tls)\n const body = `${JSON.stringify(value)}\\n`\n response.writeHead(status, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body),\n })\n response.end(body)\n}\n\n/** Send a generic failure containing only a stable category. */\nexport function sendFailure(response: ServerResponse, status: number, code: string, tls: boolean): void {\n sendJson(response, status, { error: code }, tls)\n}\n\n/** Read and parse one bounded JSON object. */\nexport async function readJsonObject(request: IncomingMessage, maximumBytes: number): Promise<Record<string, unknown>> {\n const contentType = request.headers['content-type']?.split(';', 1)[0]?.trim().toLowerCase()\n if (contentType !== 'application/json') throw new HttpError(415, 'unsupported_media_type')\n const declared = request.headers['content-length']\n if (declared !== undefined) {\n if (!/^\\d+$/u.test(declared) || Number(declared) > maximumBytes) throw new HttpError(413, 'payload_too_large')\n }\n const chunks: Buffer[] = []\n let total = 0\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n total += buffer.length\n if (total > maximumBytes) throw new HttpError(413, 'payload_too_large')\n chunks.push(buffer)\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(Buffer.concat(chunks).toString('utf8')) as unknown\n } catch {\n throw new HttpError(400, 'bad_request')\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) throw new HttpError(400, 'bad_request')\n return parsed as Record<string, unknown>\n}\n\n/** Strict cookie parser: malformed or duplicate names invalidate the whole header. */\nexport function parseCookies(header: string | undefined): ReadonlyMap<string, string> | undefined {\n if (header === undefined) return new Map()\n if (header.length > 8192) return undefined\n const cookies = new Map<string, string>()\n for (const part of header.split(';')) {\n const equals = part.indexOf('=')\n if (equals <= 0) return undefined\n const name = part.slice(0, equals).trim()\n const value = part.slice(equals + 1).trim()\n if (!/^[!#$%&'*+\\-.^_`|~\\dA-Za-z]+$/u.test(name) || !/^[\\w\\-.~+/=]*$/u.test(value) || cookies.has(name)) {\n return undefined\n }\n cookies.set(name, value)\n }\n return cookies\n}\n\n/** Serialize a host-only Cookie with no Domain attribute. */\nexport function cookie(\n name: string,\n value: string,\n options: { tls: boolean; httpOnly: boolean; path: string; maxAgeSeconds: number },\n): string {\n const parts = [\n `${name}=${value}`,\n `Path=${options.path}`,\n `Max-Age=${String(Math.max(0, Math.floor(options.maxAgeSeconds)))}`,\n 'SameSite=Strict',\n 'Priority=High',\n ]\n if (options.tls) parts.push('Secure')\n if (options.httpOnly) parts.push('HttpOnly')\n return parts.join('; ')\n}\n\n/** Enforce direct CIDR, exact Host, and browser same-origin facts. */\nexport function assertExternalTrust(request: IncomingMessage, policy: RequestTrustPolicy, requireOrigin: boolean): void {\n if (!addressAllowed(request.socket.remoteAddress, policy.cidrs) || !policy.acceptsHost(request.headers.host)) {\n throw new HttpError(403, 'forbidden')\n }\n const origin = request.headers.origin\n if (origin !== undefined && !policy.acceptsOrigin(origin)) throw new HttpError(403, 'forbidden')\n const site = request.headers['sec-fetch-site']\n if (site !== undefined && site !== 'same-origin' && site !== 'none') throw new HttpError(403, 'forbidden')\n if (requireOrigin && (!policy.acceptsOrigin(origin) || site !== 'same-origin')) throw new HttpError(403, 'forbidden')\n}\n\nfunction localAuthority(header: string | undefined): { hostname: string; authority: string } | undefined {\n if (header === undefined || /[/?#@\\\\]/u.test(header)) return undefined\n try {\n const url = new URL(`http://${header}`)\n if (url.pathname !== '/' || url.username !== '' || url.password !== '') return undefined\n return { hostname: url.hostname, authority: url.host.toLowerCase() }\n } catch {\n return undefined\n }\n}\n\n/** Protect the inner management route from non-loopback and DNS-rebinding callers. */\nexport function assertLocalAdminTrust(request: IncomingMessage, requireBrowserOrigin: boolean): void {\n if (request.socket.remoteAddress === undefined || !isLoopbackAddress(request.socket.remoteAddress)) {\n throw new HttpError(403, 'forbidden')\n }\n const host = localAuthority(request.headers.host)\n if (host === undefined || (host.hostname !== 'localhost' && !isLoopbackAddress(host.hostname))) {\n throw new HttpError(403, 'forbidden')\n }\n const site = request.headers['sec-fetch-site']\n if (site !== undefined && site !== 'same-origin' && site !== 'none') throw new HttpError(403, 'forbidden')\n const origin = request.headers.origin\n if (origin !== undefined) {\n try {\n const parsed = new URL(origin)\n if (parsed.host.toLowerCase() !== host.authority || (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')) {\n throw new HttpError(403, 'forbidden')\n }\n } catch (error) {\n if (error instanceof HttpError) throw error\n throw new HttpError(403, 'forbidden')\n }\n }\n if (requireBrowserOrigin && site !== undefined && (origin === undefined || site !== 'same-origin')) {\n throw new HttpError(403, 'forbidden')\n }\n}\n","import { createRequire } from 'node:module'\n\ninterface PackageManifest {\n readonly version?: unknown\n}\n\nconst manifest = createRequire(import.meta.url)('../package.json') as PackageManifest\n\n/** Version of the installed DSH Mobile plugin package. */\nexport const DSH_MOBILE_VERSION = typeof manifest.version === 'string' ? manifest.version : 'unknown'\n\n/** Oldest Android App release supported by this plugin generation. */\nexport const MINIMUM_ANDROID_APP_VERSION = '0.2.2'\n\n/** Public gateway metadata format understood by the Android App. */\nexport const MOBILE_METADATA_VERSION = 1\n","import { lstat, opendir, readFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { basename, dirname, extname, isAbsolute, resolve } from 'node:path'\nimport { HttpError } from './http-security.js'\n\nconst MAX_ENTRIES = 500\nconst MAX_IMAGE_BYTES = 20 * 1024 * 1024\nconst IMAGE_TYPES: Readonly<Record<string, string>> = Object.freeze({\n '.gif': 'image/gif',\n '.jpeg': 'image/jpeg',\n '.jpg': 'image/jpeg',\n '.png': 'image/png',\n '.webp': 'image/webp',\n})\n\n/** One computer-side row rendered by the authenticated mobile file sheet. */\nexport interface ComputerImageEntry {\n readonly kind: 'directory' | 'image'\n readonly name: string\n readonly path: string\n}\n\n/** A bounded computer-side directory listing containing folders and supported images. */\nexport interface ComputerImageListing {\n readonly path: string\n readonly parent?: string\n readonly entries: readonly ComputerImageEntry[]\n readonly truncated: boolean\n}\n\n/** Normalize an optional mobile-browser path without rebasing relative input. */\nexport function resolveComputerImagePath(path: string | null): string {\n if (path === null || path === '') return homedir()\n if (!isAbsolute(path) || path.includes('\\0')) throw new HttpError(400, 'bad_path')\n return resolve(path)\n}\n\n/** List folders and supported image files without following symbolic links. */\nexport async function listComputerImages(path: string | null, signal?: AbortSignal): Promise<ComputerImageListing> {\n signal?.throwIfAborted()\n const target = resolveComputerImagePath(path)\n const rows: ComputerImageEntry[] = []\n let truncated = false\n let directory\n try {\n directory = await opendir(target)\n for await (const entry of directory) {\n signal?.throwIfAborted()\n if (entry.isSymbolicLink()) continue\n const kind = entry.isDirectory() ? 'directory' : IMAGE_TYPES[extname(entry.name).toLowerCase()] === undefined ? undefined : 'image'\n if (kind === undefined) continue\n if (rows.length === MAX_ENTRIES) {\n truncated = true\n break\n }\n rows.push({ kind, name: entry.name, path: resolve(target, entry.name) })\n }\n } catch (error) {\n if (signal?.aborted) throw signal.reason\n throw new HttpError(404, 'directory_unavailable')\n } finally {\n await directory?.close().catch(() => undefined)\n }\n rows.sort((left, right) => left.kind === right.kind\n ? left.name.localeCompare(right.name)\n : left.kind === 'directory' ? -1 : 1)\n const parent = dirname(target)\n return Object.freeze({\n path: target,\n ...(parent === target ? {} : { parent }),\n entries: Object.freeze(rows),\n truncated,\n })\n}\n\n/** Read one bounded regular image file selected by an authenticated device. */\nexport async function readComputerImage(path: string | null, signal?: AbortSignal): Promise<{ body: Buffer; contentType: string; name: string }> {\n signal?.throwIfAborted()\n const target = resolveComputerImagePath(path)\n const contentType = IMAGE_TYPES[extname(target).toLowerCase()]\n if (contentType === undefined) throw new HttpError(415, 'unsupported_file_type')\n let info\n try {\n info = await lstat(target)\n } catch {\n throw new HttpError(404, 'file_unavailable')\n }\n if (!info.isFile() || info.isSymbolicLink()) throw new HttpError(404, 'file_unavailable')\n if (info.size > MAX_IMAGE_BYTES) throw new HttpError(413, 'file_too_large')\n try {\n return { body: await readFile(target, { signal }), contentType, name: basename(target) }\n } catch (error) {\n if (signal?.aborted) throw signal.reason\n throw new HttpError(404, 'file_unavailable')\n }\n}\n","import { createHash } from 'node:crypto'\nimport type { Dirent } from 'node:fs'\nimport { lstat, mkdir, opendir, readFile, realpath } from 'node:fs/promises'\nimport { basename, isAbsolute, join, relative, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { Service, type Context } from '@deepseek-ai/cordis'\nimport z from '@deepseek-ai/schemastery'\nimport { finished, type Readable } from 'node:stream'\n\n/** Maximum sizes enforced at the local-extension filesystem boundary. */\nexport const EXTENSION_LIMITS = Object.freeze({\n manifest: 64 * 1024,\n script: 1024 * 1024,\n css: 512 * 1024,\n asset: 8 * 1024 * 1024,\n assetFiles: 256,\n assetBytes: 32 * 1024 * 1024,\n assetDepth: 8,\n})\n\n/** A misbehaving host activation must not wedge the local watcher forever. */\nconst HOST_ACTIVATION_TIMEOUT_MS = 5_000\n\n/** The previous Host outlives the hidden-page refresh interval and one timed refresh. */\nconst RETIRED_GENERATION_TTL_MS = 10 * 60_000\n\n/** Extension teardown is advisory and must never stop watcher progress. */\nconst HOST_TEARDOWN_TIMEOUT_MS = 2_000\n\nasync function withActivationTimeout<T>(promise: Promise<T>, id: string, signal: AbortSignal): Promise<T> {\n let timer: NodeJS.Timeout | undefined\n let onAbort: (() => void) | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new MobileExtensionError('host_load_timeout', `extension ${id} activation timed out`, 500)), HOST_ACTIVATION_TIMEOUT_MS)\n }),\n new Promise<never>((_, reject) => {\n const abort = (): void => { reject(new MobileExtensionError('host_activation_closed', `extension ${id} activation is closed`, 409)) }\n if (signal.aborted) abort()\n else { onAbort = abort; signal.addEventListener('abort', abort, { once: true }) }\n }),\n ])\n } finally {\n if (timer !== undefined) clearTimeout(timer)\n if (onAbort !== undefined) signal.removeEventListener('abort', onAbort)\n }\n}\n\n/** A controlled business failure returned by an extension action or route. */\nexport class MobileExtensionError extends Error {\n constructor(readonly code: string, message: string, readonly status = 400) {\n super(message)\n this.name = 'MobileExtensionError'\n }\n}\n\n/** One host-side action exposed by an extension. */\nexport interface MobileHostAction {\n readonly input?: { parse(value: unknown): unknown }\n readonly run: (context: MobileActionContext, input: unknown) => unknown | Promise<unknown>\n}\n\n/** Context supplied to a host action. */\nexport interface MobileActionContext {\n readonly signal: AbortSignal\n readonly deviceId: string\n}\n\n/** Safe request values supplied to a host route. */\nexport interface MobileRouteRequest {\n readonly method: string\n readonly pathname: string\n readonly query: Readonly<URLSearchParams>\n readonly headers: Readonly<Record<string, string>>\n readonly body: Uint8Array\n readonly signal: AbortSignal\n readonly deviceId: string\n}\n\n/** Values an extension route may return; status is a final HTTP code from 200 through 599. */\nexport interface MobileRouteResponse {\n readonly status?: number\n readonly contentType?: string\n readonly headers?: Readonly<Record<string, string>>\n readonly body: string | Uint8Array | Readable\n}\n\n/** One host-side route exposed by an extension. */\nexport interface MobileHostRoute {\n readonly method: string\n readonly path: string\n readonly kind?: 'exact' | 'prefix'\n readonly handle: (request: MobileRouteRequest) => MobileRouteResponse | Promise<MobileRouteResponse>\n}\n\n/** Metadata shared by local and npm-provided extensions. */\nexport interface MobileExtensionManifest {\n readonly schemaVersion: 1\n readonly id: string\n readonly name: string\n readonly version: string\n readonly description?: string\n}\n\n/** Definition registered by a normal Cordis plugin. */\nexport interface MobileExtensionDefinition extends MobileExtensionManifest {\n readonly actions?: Readonly<Record<string, MobileHostAction>>\n readonly routes?: readonly MobileHostRoute[]\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n mobileAccess: MobileAccessService\n }\n}\n\n/** A local extension manifest read from extension.json. */\nexport interface LocalExtensionManifest extends MobileExtensionManifest {}\n\n/** Public snapshot sent to the mobile browser. */\nexport interface MobileExtensionClientEntry extends MobileExtensionManifest {\n readonly generation?: string\n readonly scriptUrl?: string\n readonly styleUrl?: string\n readonly assetsUrl?: string\n}\n\ninterface LocalAssetSnapshot {\n readonly body: Buffer\n readonly digest: string\n readonly name: string\n}\n\n/** Small status summary used by the desktop mobile-access card. */\nexport interface MobileExtensionStatus {\n readonly loaded: number\n readonly failed: number\n}\n\ninterface ActiveLocalExtension {\n readonly manifest: LocalExtensionManifest\n readonly directory: string\n readonly scriptBody?: Buffer\n readonly styleBody?: Buffer\n readonly assets: ReadonlyMap<string, LocalAssetSnapshot>\n readonly host: MobileExtensionDefinition\n readonly controller: AbortController\n readonly cleanups: readonly (() => void | Promise<void>)[]\n readonly digest: string\n}\n\ninterface RegisteredExtension {\n readonly definition: MobileExtensionDefinition\n readonly dispose: () => void\n}\n\ninterface RetiredLocalExtension {\n readonly active: ActiveLocalExtension\n readonly timer: NodeJS.Timeout\n}\n\ntype HostApi = {\n readonly manifest: LocalExtensionManifest\n readonly context: Context\n readonly schema: typeof z\n readonly signal: AbortSignal\n action(name: string, spec: MobileHostAction): void\n route(spec: MobileHostRoute): void\n effect(setup: () => void | (() => void | Promise<void>) | Promise<void | (() => void | Promise<void>)>): void\n}\n\ntype LocalHostModule = { readonly default?: (api: HostApi) => void | Promise<void> }\n\n/** Validate user-facing extension text without allowing control characters. */\nfunction text(value: unknown, field: string, maximum: number, required: boolean): string | undefined {\n if (value === undefined && !required) return undefined\n if (typeof value !== 'string' || (required && value.length === 0) || value.length > maximum\n || /[\\u0000-\\u001f\\u007f]/u.test(value)) throw new MobileExtensionError('invalid_manifest', `${field} is invalid`)\n return value\n}\n\n/** Validate a stable extension id. */\nexport function assertExtensionId(value: unknown): string {\n if (typeof value !== 'string' || !/^[a-z][a-z0-9-]{0,63}$/u.test(value)) {\n throw new MobileExtensionError('invalid_manifest', 'extension id is invalid')\n }\n return value\n}\n\n/** Validate a manifest from JSON or a plugin definition. */\nexport function parseExtensionManifest(value: unknown): LocalExtensionManifest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new MobileExtensionError('invalid_manifest', 'extension.json must be an object')\n }\n const record = value as Record<string, unknown>\n if (record.schemaVersion !== 1) throw new MobileExtensionError('invalid_manifest', 'unsupported extension schema')\n const id = assertExtensionId(record.id)\n const name = text(record.name, 'name', 120, true) as string\n const version = text(record.version, 'version', 64, true) as string\n const description = text(record.description, 'description', 500, false)\n for (const key of Reflect.ownKeys(record)) {\n if (!['schemaVersion', 'id', 'name', 'version', 'description'].includes(String(key))) {\n throw new MobileExtensionError('invalid_manifest', 'extension.json has unknown fields')\n }\n }\n return Object.freeze({ schemaVersion: 1, id, name, version, ...(description === undefined ? {} : { description }) })\n}\n\nfunction normalizeRelativePath(value: string, field: string): string {\n if (value.length === 0 || value.includes('\\0') || isAbsolute(value)) throw new MobileExtensionError('invalid_extension_path', `${field} is invalid`)\n const normalized = value.replaceAll('\\\\', '/')\n if (normalized.split('/').some(part => part === '' || part === '.' || part === '..')) {\n throw new MobileExtensionError('invalid_extension_path', `${field} escapes extension directory`)\n }\n return normalized\n}\n\nasync function regularFile(path: string, maximum: number, field: string): Promise<{ readonly path: string; readonly size: number }> {\n let info\n try { info = await lstat(path) } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') throw new MobileExtensionError('invalid_extension', `${field} is missing`)\n throw error\n }\n if (!info.isFile() || info.isSymbolicLink() || info.size > maximum) {\n throw new MobileExtensionError('invalid_extension', `${field} must be a regular file within its size limit`)\n }\n return { path, size: info.size }\n}\n\nasync function containedPath(root: string, relativePath: string, maximum: number, field: string): Promise<{ readonly path: string; readonly size: number }> {\n const normalized = normalizeRelativePath(relativePath, field)\n const target = resolve(root, normalized)\n const rootReal = await realpath(root)\n const targetReal = await realpath(target)\n const relation = relative(rootReal, targetReal)\n if (relation === '' || relation.startsWith('..') || isAbsolute(relation)) throw new MobileExtensionError('invalid_extension_path', `${field} escapes extension directory`)\n return regularFile(targetReal, maximum, field)\n}\n\nasync function optionalFile(root: string, name: string, maximum: number, field: string): Promise<string | undefined> {\n try {\n return (await containedPath(root, name, maximum, field)).path\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined\n if (error instanceof MobileExtensionError && error.message.includes('is missing')) return undefined\n throw error\n }\n}\n\nasync function optionalBytes(root: string, name: string, maximum: number, field: string): Promise<Buffer | undefined> {\n const path = await optionalFile(root, name, maximum, field)\n return path === undefined ? undefined : readFile(path)\n}\n\nfunction assertRealPathWithin(rootReal: string, targetReal: string, field: string): void {\n const relation = relative(rootReal, targetReal)\n if (relation === '' || relation.startsWith('..') || isAbsolute(relation)) {\n throw new MobileExtensionError('invalid_extension_path', `${field} escapes extension directory`)\n }\n}\n\nasync function realExtensionRoot(directory: string): Promise<string> {\n const root = resolve(directory)\n const info = await lstat(root)\n if (!info.isDirectory() || info.isSymbolicLink()) throw new MobileExtensionError('invalid_extension', 'extension directory must be real')\n return realpath(root)\n}\n\nasync function assetSnapshot(extensionRootReal: string): Promise<ReadonlyMap<string, LocalAssetSnapshot>> {\n const assetsPath = join(extensionRootReal, 'assets')\n let assetsInfo\n try { assetsInfo = await lstat(assetsPath) } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return new Map()\n throw error\n }\n if (!assetsInfo.isDirectory() || assetsInfo.isSymbolicLink()) {\n throw new MobileExtensionError('invalid_extension', 'assets must be a real directory')\n }\n const assetsReal = await realpath(assetsPath)\n assertRealPathWithin(extensionRootReal, assetsReal, 'assets')\n const snapshots = new Map<string, LocalAssetSnapshot>()\n let totalBytes = 0\n const visit = async (directoryReal: string, prefix: string, depth: number): Promise<void> => {\n if (depth > EXTENSION_LIMITS.assetDepth) {\n throw new MobileExtensionError('invalid_extension', 'asset tree exceeds its depth limit')\n }\n assertRealPathWithin(extensionRootReal, directoryReal, 'asset directory')\n const handle = await opendir(directoryReal)\n const entries: Dirent[] = []\n try { for await (const entry of handle) entries.push(entry) }\n finally { await handle.close().catch(() => undefined) }\n entries.sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0)\n for (const entry of entries) {\n const path = join(directoryReal, entry.name)\n const info = await lstat(path)\n if (info.isSymbolicLink()) throw new MobileExtensionError('invalid_extension_path', 'asset escapes extension directory')\n const targetReal = await realpath(path)\n assertRealPathWithin(extensionRootReal, targetReal, 'asset')\n const key = prefix === '' ? entry.name : `${prefix}/${entry.name}`\n if (info.isDirectory()) {\n await visit(targetReal, key, depth + 1)\n continue\n }\n if (!info.isFile() || info.size > EXTENSION_LIMITS.asset) {\n throw new MobileExtensionError('invalid_extension', 'asset must be a regular file within its size limit')\n }\n const body = await readFile(targetReal)\n totalBytes += body.byteLength\n if (snapshots.size >= EXTENSION_LIMITS.assetFiles || totalBytes > EXTENSION_LIMITS.assetBytes) {\n throw new MobileExtensionError('invalid_extension', 'asset tree exceeds its aggregate limit')\n }\n snapshots.set(key, Object.freeze({ body, digest: createHash('sha256').update(body).digest('hex'), name: entry.name }))\n }\n }\n await visit(assetsReal, '', 0)\n return snapshots\n}\n\ninterface LocalExtensionFingerprint {\n readonly manifest: LocalExtensionManifest\n readonly digest: string\n readonly scriptBody?: Buffer\n readonly styleBody?: Buffer\n readonly assets: ReadonlyMap<string, LocalAssetSnapshot>\n}\n\nasync function extensionFingerprint(directory: string): Promise<LocalExtensionFingerprint> {\n const root = await realExtensionRoot(directory)\n const manifestFile = await regularFile(join(root, 'extension.json'), EXTENSION_LIMITS.manifest, 'extension.json')\n const manifestBody = await readFile(manifestFile.path)\n const manifest = parseExtensionManifest(JSON.parse(manifestBody.toString('utf8')) as unknown)\n if (manifest.id !== basename(root)) throw new MobileExtensionError('invalid_manifest', 'extension id must match its directory name')\n const [host, script, style, assets] = await Promise.all([\n optionalBytes(root, 'host.mjs', EXTENSION_LIMITS.script, 'host.mjs'),\n optionalBytes(root, 'mobile.js', EXTENSION_LIMITS.script, 'mobile.js'),\n optionalBytes(root, 'mobile.css', EXTENSION_LIMITS.css, 'mobile.css'),\n assetSnapshot(root),\n ])\n const digest = createHash('sha256').update(`manifest:${manifestBody.byteLength}:`).update(createHash('sha256').update(manifestBody).digest())\n for (const [name, body] of [['host', host], ['script', script], ['style', style]] as const) {\n digest.update(`\\0${name}:${body?.byteLength ?? -1}:`)\n if (body !== undefined) digest.update(createHash('sha256').update(body).digest())\n }\n for (const [name, asset] of assets) {\n digest.update(`\\0asset:${Buffer.byteLength(name)}:${name}:${asset.body.byteLength}:${asset.digest}`)\n }\n return {\n manifest,\n digest: digest.digest('hex'),\n assets,\n ...(script === undefined ? {} : { scriptBody: script }),\n ...(style === undefined ? {} : { styleBody: style }),\n }\n}\n\nfunction routeKey(route: MobileHostRoute): string {\n const method = route.method.toUpperCase()\n const path = normalizeRoutePath(route.path)\n return `${method} ${route.kind ?? 'exact'} ${path}`\n}\n\nfunction normalizeRoutePath(value: string): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > 256\n || value.includes('?') || value.includes('#') || value.includes('\\\\') || value.includes('\\0')\n || /[\\u0000-\\u001f\\u007f]/u.test(value)) throw new MobileExtensionError('invalid_route', 'extension route path is invalid')\n const normalizedInput = value.startsWith('/') ? value : `/${value}`\n const parts = normalizedInput.split('/')\n if (parts.some(part => part === '..' || part === '.')) throw new MobileExtensionError('invalid_route', 'extension route path is invalid')\n return normalizedInput === '/' ? '/' : normalizedInput.replace(/\\/+$/u, '')\n}\n\nfunction validateDefinition(definition: MobileExtensionDefinition): MobileExtensionDefinition {\n const manifest = parseExtensionManifest({\n schemaVersion: definition.schemaVersion,\n id: definition.id,\n name: definition.name,\n version: definition.version,\n ...(definition.description === undefined ? {} : { description: definition.description }),\n })\n const actionNames = new Set<string>()\n for (const [name, action] of Object.entries(definition.actions ?? {})) {\n if (!/^[a-z][a-z0-9-]{0,63}$/u.test(name) || action === null || typeof action !== 'object' || typeof action.run !== 'function' || actionNames.has(name)) {\n throw new MobileExtensionError('invalid_action', `invalid action ${name}`)\n }\n actionNames.add(name)\n }\n const routeNames = new Set<string>()\n const routes = (definition.routes ?? []).map(route => {\n if (route === null || typeof route !== 'object' || typeof route.handle !== 'function') throw new MobileExtensionError('invalid_route', 'invalid extension route')\n const method = route.method.toUpperCase()\n if (!['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) throw new MobileExtensionError('invalid_route', 'unsupported extension route method')\n const normalized: MobileHostRoute = { ...route, method, path: normalizeRoutePath(route.path) }\n const key = routeKey(normalized)\n if (routeNames.has(key)) throw new MobileExtensionError('duplicate_route', `duplicate route ${key}`)\n routeNames.add(key)\n return normalized\n })\n return Object.freeze({ ...manifest, ...(definition.actions === undefined ? {} : { actions: Object.freeze({ ...definition.actions }) }), ...(routes.length === 0 ? {} : { routes: Object.freeze(routes) }) })\n}\n\ninterface CombinedSignalLifetime {\n readonly signal: AbortSignal\n readonly cleanup: () => void\n}\n\nfunction combineSignalLifetime(first: AbortSignal, second: AbortSignal): CombinedSignalLifetime {\n if (first.aborted || second.aborted) {\n const aborted = new AbortController()\n aborted.abort(first.aborted ? first.reason : second.reason)\n return { signal: aborted.signal, cleanup: () => undefined }\n }\n const controller = new AbortController()\n const cleanup = (): void => {\n first.removeEventListener('abort', abortFirst)\n second.removeEventListener('abort', abortSecond)\n }\n const abortFirst = (): void => { cleanup(); controller.abort(first.reason) }\n const abortSecond = (): void => { cleanup(); controller.abort(second.reason) }\n first.addEventListener('abort', abortFirst, { once: true })\n second.addEventListener('abort', abortSecond, { once: true })\n return { signal: controller.signal, cleanup }\n}\n\n/** Combine two abort lifetimes without relying on AbortSignal.any in older WebViews. */\nexport function combineSignals(first: AbortSignal, second: AbortSignal): AbortSignal {\n return combineSignalLifetime(first, second).signal\n}\n\n/** Host registry and service consumed by both npm plugins and local extensions. */\nexport class MobileAccessService extends Service {\n private readonly registered = new Map<string, RegisteredExtension>()\n private readonly local = new Map<string, ActiveLocalExtension>()\n private readonly retired = new Map<string, RetiredLocalExtension>()\n private readonly failures = new Map<string, string>()\n private readonly contentListeners = new Set<() => void>()\n private contentHash = createHash('sha256').update('').digest('hex')\n private localRoot: string | undefined\n private localContext: Context | undefined\n private localTimer: NodeJS.Timeout | undefined\n private localRefreshing: Promise<void> | undefined\n private localRefreshAbort: AbortController | undefined\n private localLifecycle = 0\n private localClosed = true\n\n constructor(ctx: Context) { super(ctx, 'mobileAccess') }\n\n /** Register a normal Cordis extension and return an idempotent disposer. */\n registerExtension(definition: MobileExtensionDefinition): () => void {\n const validated = validateDefinition(definition)\n if (this.registered.has(validated.id) || this.local.has(validated.id)) throw new Error(`mobile extension id already registered: ${validated.id}`)\n const dispose = (): void => {\n const current = this.registered.get(validated.id)\n if (current?.dispose === dispose) {\n this.registered.delete(validated.id)\n this.updateContentHash()\n }\n }\n this.registered.set(validated.id, { definition: validated, dispose })\n this.updateContentHash()\n return dispose\n }\n\n /** Aggregate digest covering every registered and active local extension. */\n contentDigest(): string {\n return this.contentHash\n }\n\n /** Subscribe to committed extension generation changes. */\n onContentChanged(listener: () => void): () => void {\n this.contentListeners.add(listener)\n return () => { this.contentListeners.delete(listener) }\n }\n\n private updateContentHash(): void {\n const parts = [\n ...[...this.registered.values()].map(entry => entry.definition.id),\n ...[...this.local.values()].map(active => `${active.manifest.id}:${active.digest}`),\n ]\n const next = createHash('sha256').update(parts.sort().join('|')).digest('hex')\n if (next === this.contentHash) return\n this.contentHash = next\n for (const listener of this.contentListeners) {\n try { listener() } catch { /* One observer cannot block a committed generation. */ }\n }\n }\n\n /** Return the current client-facing manifest, deterministically sorted by id. */\n manifest(): readonly MobileExtensionClientEntry[] {\n const entries = new Map<string, MobileExtensionClientEntry>()\n for (const { definition } of this.registered.values()) entries.set(definition.id, {\n schemaVersion: 1, id: definition.id, name: definition.name, version: definition.version,\n ...(definition.description === undefined ? {} : { description: definition.description }),\n })\n for (const active of this.local.values()) entries.set(active.manifest.id, {\n ...active.manifest,\n generation: active.digest,\n ...(active.scriptBody === undefined ? {} : { scriptUrl: `/mobile-access/extensions/${active.manifest.id}/mobile.js?generation=${active.digest}` }),\n ...(active.styleBody === undefined ? {} : { styleUrl: `/mobile-access/extensions/${active.manifest.id}/mobile.css?generation=${active.digest}` }),\n assetsUrl: `/mobile-access/extensions/${active.manifest.id}/assets/`,\n })\n return [...entries.values()].sort((left, right) => left.id.localeCompare(right.id))\n }\n\n /** Return loaded and failed local extension counts without exposing host errors. */\n status(): MobileExtensionStatus {\n return Object.freeze({ loaded: this.registered.size + this.local.size, failed: this.failures.size })\n }\n\n /** Locate one active extension. */\n extension(id: string, generation?: string): MobileExtensionDefinition | ActiveLocalExtension | undefined {\n if (generation !== undefined) {\n const current = this.local.get(id)\n if (current?.digest === generation) return current\n const previous = this.retired.get(id)?.active\n return previous?.digest === generation ? previous : undefined\n }\n return this.local.get(id) ?? this.registered.get(id)?.definition\n }\n\n /** Return the active local generation signal for gateway cancellation wiring. */\n signal(id: string, generation?: string): AbortSignal | undefined {\n const extension = this.extension(id, generation)\n return extension !== undefined && 'host' in extension ? extension.controller.signal : undefined\n }\n\n /** Read a local client entry after validating that it remains inside its directory. */\n async readClientFile(id: string, kind: 'script' | 'style', signal?: AbortSignal, generation?: string): Promise<{ readonly body: Buffer; readonly digest: string }> {\n signal?.throwIfAborted()\n const selected = this.extension(id, generation)\n const active = selected !== undefined && 'host' in selected ? selected : undefined\n if (active === undefined) throw new MobileExtensionError('extension_generation_not_found', 'extension generation not found', 404)\n const snapshot = kind === 'script' ? active.scriptBody : active.styleBody\n if (snapshot === undefined) throw new MobileExtensionError('extension_asset_not_found', 'extension asset not found', 404)\n const body = Buffer.from(snapshot)\n return { body, digest: createHash('sha256').update(body).digest('hex') }\n }\n\n /** Read a generation-pinned static asset from its validated snapshot. */\n async readAsset(id: string, assetPath: string, signal?: AbortSignal, generation?: string): Promise<{ readonly body: Buffer; readonly digest: string; readonly name: string }> {\n signal?.throwIfAborted()\n const selected = this.extension(id, generation)\n const active = selected !== undefined && 'host' in selected ? selected : undefined\n if (active === undefined) throw new MobileExtensionError('extension_generation_not_found', 'extension generation not found', 404)\n const normalized = normalizeRelativePath(assetPath, 'asset')\n const asset = active.assets.get(normalized)\n if (asset === undefined) throw new MobileExtensionError('extension_asset_not_found', 'extension asset not found', 404)\n return { body: Buffer.from(asset.body), digest: asset.digest, name: asset.name }\n }\n\n /** Invoke one action after parsing its input and binding the request lifetime. */\n async invoke(id: string, actionName: string, input: unknown, context: MobileActionContext, generation?: string): Promise<unknown> {\n const extension = this.extension(id, generation)\n if (extension === undefined) throw new MobileExtensionError('extension_not_found', 'extension not found', 404)\n const definition = 'host' in extension ? extension.host : extension\n const action = definition.actions?.[actionName]\n if (action === undefined) throw new MobileExtensionError('action_not_found', 'action not found', 404)\n let parsed = input\n try { parsed = action.input?.parse(input) ?? input } catch { throw new MobileExtensionError('invalid_action_input', 'action input is invalid', 400) }\n const lifetime = 'host' in extension ? combineSignalLifetime(extension.controller.signal, context.signal) : undefined\n const signal = lifetime?.signal ?? context.signal\n try { return await action.run({ ...context, signal }, parsed) } catch (error) {\n if (error instanceof MobileExtensionError) throw error\n throw new MobileExtensionError('extension_failed', 'extension action failed', 500)\n } finally { lifetime?.cleanup() }\n }\n\n /** Match one route and invoke it with a generation-bound abort signal. */\n async route(id: string, method: string, pathname: string, request: MobileRouteRequest, generation?: string): Promise<MobileRouteResponse> {\n const extension = this.extension(id, generation)\n if (extension === undefined) throw new MobileExtensionError('extension_not_found', 'extension not found', 404)\n const definition = 'host' in extension ? extension.host : extension\n const route = definition.routes?.find((candidate: MobileHostRoute) => {\n if (candidate.method !== method) return false\n return (candidate.kind ?? 'exact') === 'exact'\n ? candidate.path === pathname\n : pathname === candidate.path || pathname.startsWith(`${candidate.path}/`)\n })\n if (route === undefined) throw new MobileExtensionError('route_not_found', 'route not found', 404)\n const lifetime = 'host' in extension ? combineSignalLifetime(extension.controller.signal, request.signal) : undefined\n let releaseLifetime = true\n try {\n const routeRequest = lifetime === undefined ? request : { ...request, signal: lifetime.signal }\n const result = await route.handle(routeRequest)\n if (result === null || typeof result !== 'object' || typeof result.body !== 'string' && !(result.body instanceof Uint8Array) && !isReadable(result.body)) {\n throw new MobileExtensionError('invalid_route_response', 'extension returned an invalid response', 500)\n }\n if (lifetime !== undefined && isReadable(result.body)) {\n releaseLifetime = false\n releaseSignalLifetimeWhenStreamSettles(result.body, lifetime.cleanup)\n }\n return result\n } catch (error) {\n if (error instanceof MobileExtensionError) throw error\n throw new MobileExtensionError('extension_failed', 'extension route failed', 500)\n } finally { if (releaseLifetime) lifetime?.cleanup() }\n }\n\n /** Start the local directory watcher; an absent directory is intentionally inert. */\n async startLocal(root: string, context: Context): Promise<void> {\n const targetRoot = resolve(root)\n if (this.localRoot !== undefined && resolve(this.localRoot) !== targetRoot) await this.stopLocal()\n if (this.localTimer !== undefined) clearInterval(this.localTimer)\n const lifecycle = ++this.localLifecycle\n this.localRoot = targetRoot; this.localContext = context; this.localClosed = false\n await mkdir(this.localRoot, { recursive: true })\n if (this.localClosed || this.localLifecycle !== lifecycle || this.localRoot !== targetRoot || this.localContext !== context) return\n await this.refreshLocal()\n if (this.localClosed || this.localLifecycle !== lifecycle || this.localRoot !== targetRoot || this.localContext !== context) return\n this.localTimer = setInterval(() => { void this.refreshLocal() }, 2_000)\n this.localTimer.unref()\n }\n\n /** Stop the watcher and abort every local host generation. */\n async stopLocal(): Promise<void> {\n this.localClosed = true\n const lifecycle = ++this.localLifecycle\n if (this.localTimer !== undefined) clearInterval(this.localTimer)\n this.localTimer = undefined\n const refreshing = this.localRefreshing\n this.localRefreshAbort?.abort()\n const previous = [...this.local.values(), ...[...this.retired.values()].map(entry => entry.active)]\n this.local.clear()\n for (const entry of this.retired.values()) clearTimeout(entry.timer)\n this.retired.clear()\n this.failures.clear()\n this.updateContentHash()\n await Promise.allSettled([\n abortAndDisposeLocal(previous),\n ...(refreshing === undefined ? [] : [refreshing]),\n ])\n if (this.localLifecycle !== lifecycle) return\n const late = [...this.local.values(), ...[...this.retired.values()].map(entry => entry.active)]\n this.local.clear()\n for (const entry of this.retired.values()) clearTimeout(entry.timer)\n this.retired.clear()\n this.failures.clear()\n this.updateContentHash()\n await abortAndDisposeLocal(late)\n if (this.localTimer !== undefined) clearInterval(this.localTimer)\n this.localTimer = undefined\n }\n\n /** Refresh all local extensions atomically; failures keep the previous snapshot. */\n refreshLocal(): Promise<void> {\n if (this.localRefreshing !== undefined) return this.localRefreshing\n const controller = new AbortController()\n this.localRefreshAbort = controller\n const refreshing = this.stageAndCommit(controller.signal).finally(() => {\n if (this.localRefreshing === refreshing) this.localRefreshing = undefined\n if (this.localRefreshAbort === controller) this.localRefreshAbort = undefined\n })\n this.localRefreshing = refreshing\n return refreshing\n }\n\n private async stageAndCommit(signal: AbortSignal): Promise<void> {\n if (this.localClosed || signal.aborted || this.localRoot === undefined || this.localContext === undefined) return\n let names: string[] = []\n try {\n const directory = await opendir(this.localRoot)\n try { for await (const entry of directory) if (entry.isDirectory() && !entry.isSymbolicLink()) names.push(entry.name) }\n finally { await directory.close().catch(() => undefined) }\n } catch { return }\n names.sort()\n const staged: ActiveLocalExtension[] = []\n const stagedFresh: ActiveLocalExtension[] = []\n let failingName = 'local'\n try {\n for (const name of names) {\n signal.throwIfAborted()\n failingName = name\n const directory = join(this.localRoot, name)\n const fingerprint = await extensionFingerprint(directory)\n const current = this.local.get(fingerprint.manifest.id)\n const retired = this.retired.get(fingerprint.manifest.id)?.active\n const previous = current?.digest === fingerprint.digest ? current : retired?.digest === fingerprint.digest ? retired : undefined\n if (previous?.digest === fingerprint.digest) staged.push(previous)\n else {\n const fresh = await loadLocalExtension(directory, this.localContext, fingerprint, signal)\n try {\n signal.throwIfAborted()\n const confirmed = await extensionFingerprint(directory)\n if (confirmed.digest !== fingerprint.digest) {\n throw new MobileExtensionError('extension_changed_during_activation', `extension ${fingerprint.manifest.id} changed during activation`, 409)\n }\n } catch (error) {\n await abortAndDisposeLocal([fresh])\n throw error\n }\n staged.push(fresh); stagedFresh.push(fresh)\n }\n }\n if (this.localClosed || signal.aborted || this.localRoot === undefined || this.localContext === undefined) {\n await abortAndDisposeLocal(stagedFresh)\n return\n }\n const duplicate = new Set<string>()\n for (const entry of staged) {\n if (duplicate.has(entry.manifest.id) || this.registered.has(entry.manifest.id)) throw new MobileExtensionError('duplicate_extension', `duplicate extension id ${entry.manifest.id}`)\n duplicate.add(entry.manifest.id)\n }\n const previous = [...this.local.values()]\n for (const entry of staged) {\n const retired = this.retired.get(entry.manifest.id)\n if (retired?.active === entry) {\n clearTimeout(retired.timer)\n this.retired.delete(entry.manifest.id)\n }\n }\n const stagedIds = new Set(staged.map(entry => entry.manifest.id))\n const removed: ActiveLocalExtension[] = []\n for (const entry of previous) {\n if (staged.includes(entry)) continue\n if (stagedIds.has(entry.manifest.id)) {\n this.retire(entry)\n continue\n }\n removed.push(entry)\n const retired = this.retired.get(entry.manifest.id)\n if (retired !== undefined) {\n clearTimeout(retired.timer)\n this.retired.delete(entry.manifest.id)\n removed.push(retired.active)\n }\n }\n this.local.clear()\n for (const entry of staged) this.local.set(entry.manifest.id, entry)\n for (const entry of staged) this.failures.delete(entry.manifest.id)\n for (const name of names) this.failures.delete(name)\n for (const failure of this.failures.keys()) {\n if (failure !== 'local' && !names.includes(failure)) this.failures.delete(failure)\n }\n this.failures.delete('local')\n if (removed.length > 0) void abortAndDisposeLocal(removed)\n this.updateContentHash()\n } catch (error) {\n await abortAndDisposeLocal(stagedFresh)\n if (this.localClosed || signal.aborted) return\n const message = error instanceof Error ? error.message : String(error)\n this.failures.set(failingName, message)\n if (!(error instanceof MobileExtensionError)) this.ctx.logger.warn(error instanceof Error ? error : new Error(String(error)))\n }\n }\n\n private retire(active: ActiveLocalExtension): void {\n const previous = this.retired.get(active.manifest.id)\n if (previous?.active === active) return\n if (previous !== undefined) {\n clearTimeout(previous.timer)\n this.retired.delete(active.manifest.id)\n void abortAndDisposeLocal([previous.active])\n }\n const timer = setTimeout(() => {\n const current = this.retired.get(active.manifest.id)\n if (current?.active !== active) return\n this.retired.delete(active.manifest.id)\n void abortAndDisposeLocal([active])\n }, RETIRED_GENERATION_TTL_MS)\n timer.unref()\n this.retired.set(active.manifest.id, { active, timer })\n }\n}\n\nfunction isReadable(value: unknown): value is Readable {\n return value !== null && typeof value === 'object' && typeof (value as { pipe?: unknown }).pipe === 'function'\n}\n\nfunction releaseSignalLifetimeWhenStreamSettles(stream: Readable, cleanup: () => void): void {\n let stopObserving: (() => void) | undefined\n stopObserving = finished(stream, () => {\n stopObserving?.()\n cleanup()\n })\n}\n\nfunction invokeCleanups(cleanups: readonly (() => void | Promise<void>)[]): Promise<unknown>[] {\n const pending: Promise<unknown>[] = []\n for (const cleanup of [...cleanups].reverse()) {\n try { pending.push(Promise.resolve(cleanup())) } catch { /* extension teardown cannot block the owner */ }\n }\n return pending\n}\n\nasync function settleBounded(pending: readonly Promise<unknown>[], timeoutMs: number): Promise<void> {\n if (pending.length === 0) return\n let timer: NodeJS.Timeout | undefined\n await Promise.race([\n Promise.allSettled(pending),\n new Promise<void>(resolveTimeout => { timer = setTimeout(resolveTimeout, timeoutMs) }),\n ])\n if (timer !== undefined) clearTimeout(timer)\n}\n\nasync function abortAndDisposeLocal(entries: readonly ActiveLocalExtension[]): Promise<void> {\n const pending: Promise<unknown>[] = []\n for (const entry of entries) {\n entry.controller.abort()\n pending.push(...invokeCleanups(entry.cleanups))\n }\n await settleBounded(pending, HOST_TEARDOWN_TIMEOUT_MS)\n}\n\nasync function loadLocalExtension(directory: string, context: Context, known?: LocalExtensionFingerprint, parentSignal?: AbortSignal): Promise<ActiveLocalExtension> {\n const root = await realExtensionRoot(directory)\n const manifestFile = await regularFile(join(root, 'extension.json'), EXTENSION_LIMITS.manifest, 'extension.json')\n const manifest = known?.manifest ?? parseExtensionManifest(JSON.parse(await readFile(manifestFile.path, 'utf8')) as unknown)\n if (manifest.id !== basename(root)) throw new MobileExtensionError('invalid_manifest', 'extension id must match its directory name')\n const scriptBody = known === undefined\n ? await optionalFile(root, 'mobile.js', EXTENSION_LIMITS.script, 'mobile.js').then(path => path === undefined ? undefined : readFile(path))\n : known.scriptBody\n const styleBody = known === undefined\n ? await optionalFile(root, 'mobile.css', EXTENSION_LIMITS.css, 'mobile.css').then(path => path === undefined ? undefined : readFile(path))\n : known.styleBody\n const assets = known?.assets ?? await assetSnapshot(root)\n const hostFile = await optionalFile(root, 'host.mjs', EXTENSION_LIMITS.script, 'host.mjs')\n const controller = new AbortController()\n const actions: Record<string, MobileHostAction> = {}\n const routes: MobileHostRoute[] = []\n const cleanups: (() => void | Promise<void>)[] = []\n const pendingEffects: Promise<void>[] = []\n let activationOpen = true\n const onParentAbort = (): void => { controller.abort(parentSignal?.reason) }\n if (parentSignal?.aborted === true) onParentAbort()\n else parentSignal?.addEventListener('abort', onParentAbort, { once: true })\n const ensureActivationOpen = (): void => {\n if (!activationOpen || controller.signal.aborted) throw new MobileExtensionError('host_activation_closed', `extension ${manifest.id} activation is closed`, 409)\n }\n const api: HostApi = {\n manifest,\n context,\n schema: z,\n signal: controller.signal,\n action(name, spec) { ensureActivationOpen(); if (actions[name] !== undefined) throw new MobileExtensionError('duplicate_action', `duplicate action ${name}`); actions[name] = spec },\n route(spec) { ensureActivationOpen(); routes.push(spec) },\n effect(setup) {\n ensureActivationOpen()\n const result = setup()\n if (result instanceof Promise) {\n pendingEffects.push(result.then(async cleanup => {\n if (typeof cleanup !== 'function') return\n if (activationOpen) cleanups.push(cleanup)\n else await cleanup()\n }))\n } else if (typeof result === 'function') {\n if (activationOpen) cleanups.push(result)\n else void Promise.resolve(result()).catch(() => undefined)\n }\n },\n }\n try {\n const activate = async (): Promise<void> => {\n controller.signal.throwIfAborted()\n if (hostFile !== undefined) {\n const digest = createHash('sha256').update(await readFile(hostFile)).digest('hex')\n controller.signal.throwIfAborted()\n let imported: LocalHostModule\n try { imported = await import(`${pathToFileURL(hostFile).href}?dsh_generation=${digest}`) as LocalHostModule }\n catch { throw new MobileExtensionError('host_load_failed', `could not load ${manifest.id}/host.mjs`, 500) }\n controller.signal.throwIfAborted()\n if (imported.default !== undefined) await imported.default(api)\n }\n await Promise.all(pendingEffects)\n }\n await withActivationTimeout(activate(), manifest.id, controller.signal)\n const host = validateDefinition({ ...manifest, actions, routes })\n activationOpen = false\n const digest = known?.digest ?? createHash('sha256').update(manifest.id).digest('hex')\n return Object.freeze({ manifest, directory: root, ...(scriptBody === undefined ? {} : { scriptBody }), ...(styleBody === undefined ? {} : { styleBody }), assets, host, controller, cleanups: Object.freeze(cleanups), digest })\n } catch (error) {\n activationOpen = false\n controller.abort()\n const cleanupPromises = invokeCleanups(cleanups.splice(0))\n await settleBounded([...pendingEffects, ...cleanupPromises], HOST_TEARDOWN_TIMEOUT_MS)\n throw error\n } finally {\n parentSignal?.removeEventListener('abort', onParentAbort)\n }\n}\n\n/** Construct the service in a Cordis plugin without importing DSH internals. */\nexport function createMobileAccessService(ctx: Context): MobileAccessService {\n return new MobileAccessService(ctx)\n}\n","import { createHash, X509Certificate } from 'node:crypto'\nimport { createSocket, type Socket as DatagramSocket } from 'node:dgram'\nimport { readFile, stat } from 'node:fs/promises'\nimport { hostname } from 'node:os'\nimport { extname } from 'node:path'\nimport {\n createServer as createHttpServer,\n request as requestHttp,\n type ClientRequest,\n type IncomingHttpHeaders,\n type IncomingMessage,\n type OutgoingHttpHeaders,\n type Server as HttpServer,\n type ServerResponse,\n} from 'node:http'\nimport { createServer as createHttpsServer, type Server as HttpsServer, type ServerOptions } from 'node:https'\nimport { connect, isIP, type AddressInfo, type Socket } from 'node:net'\nimport { Transform, type TransformCallback } from 'node:stream'\nimport { pipeline } from 'node:stream/promises'\nimport { promisify } from 'node:util'\nimport { createGzip, gzip } from 'node:zlib'\nimport type { WebRoute } from '@deepseek-ai/dsh-host-webserver'\nimport Bonjour from 'bonjour-service'\nimport * as QRCode from 'qrcode'\nimport {\n AccessController,\n AccessError,\n BoundedRateLimiter,\n type DeviceSummary,\n type SessionAuthorization,\n} from './access.js'\nimport type { ResolvedGatewayConfig } from './config.js'\nimport {\n AUTH_PREFIX,\n assertExternalTrust,\n assertLocalAdminTrust,\n cookie,\n CSRF_COOKIE,\n CSRF_HEADER,\n DEVICE_COOKIE,\n HttpError,\n LOCAL_ADMIN_PREFIX,\n parseCookies,\n parseRequestTarget,\n readJsonObject,\n sendFailure,\n sendJson,\n SESSION_COOKIE,\n setSecurityHeaders,\n WS_PATHS,\n} from './http-security.js'\nimport {\n DSH_MOBILE_VERSION,\n MINIMUM_ANDROID_APP_VERSION,\n MOBILE_METADATA_VERSION,\n} from './version.js'\nimport { addressAllowed, isLoopbackAddress, type ParsedCidr, RequestTrustPolicy } from './network.js'\nimport type { DeviceStore } from './storage.js'\nimport { listComputerImages, readComputerImage } from './computer-images.js'\nimport {\n EXTENSION_LIMITS,\n MobileExtensionError,\n type MobileAccessService,\n type MobileRouteRequest,\n type MobileRouteResponse,\n} from './extensions.js'\n\ntype GatewayServer = HttpServer | HttpsServer\n\ninterface ActiveRequest {\n readonly sessionKey: string\n readonly deviceId: string\n readonly expiresAt: number\n readonly abort: () => void\n readonly timer: NodeJS.Timeout\n}\n\ninterface ActiveWebSocket {\n readonly sessionKey: string\n readonly deviceId: string\n readonly client: Socket\n readonly upstream: Socket\n readonly timer: NodeJS.Timeout\n}\n\nconst MAX_CONTROL_BODY_BYTES = 16 * 1024\nconst MAX_HEADER_BYTES = 16 * 1024\nconst MOBILE_HISTORY_PAGE_MESSAGES = 10\nconst SESSION_HISTORY_PATH = '/api/session.history'\nconst DISCOVERY_QUERY = Buffer.from('DSH_MOBILE_DISCOVER_V1', 'ascii')\nconst DISCOVERY_PROTOCOL = 1\nconst DISCOVERY_INTERVAL_MS = 3_000\nconst MDNS_SERVICE_TYPE = 'dsh-mobile'\nconst MOBILE_LAYOUT_MODULE = '@deepseek-ai/dsh-client-ui-layout'\nconst MOBILE_LAYOUT_PATH = `${AUTH_PREFIX}/mobile-layout.js`\nconst MOBILE_BOOT_BATCH_PREFIX = `${AUTH_PREFIX}/mobile-boot/`\nconst MAX_MOBILE_BOOT_BATCH_BYTES = 32 * 1024 * 1024\nconst MAX_MOBILE_BOOT_ENTRY_BYTES = 8 * 1024 * 1024\nconst MAX_MOBILE_BOOT_BATCHES = 8\nconst UPSTREAM_AUTH_REFRESH_MARGIN_MS = 60_000\nconst UPSTREAM_COOKIE_PAIR = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+=[\\x21-\\x3A\\x3C-\\x7E]*$/u\nconst CUSTOM_STYLE_FALLBACK = '/* Add mobile overrides in the DSH home mobile-access/mobile.css file. */\\n'\nconst CUSTOM_SCRIPT_FALLBACK = 'window.dshMobile?.register(() => undefined)\\n'\nconst EXTENSION_CHANGE_POLL_MS = 2_000\nconst EXTENSION_EVENT_HEARTBEAT_MS = 15_000\nconst MOBILE_CLIENT_MODULE = 'dsh-mobile'\nconst CONNECTION_MODULE = '@deepseek-ai/dsh-client-connection'\nconst RUNTIME_MODULE = '@deepseek-ai/dsh-client-runtime'\nconst RENDERER_MODULE = '@deepseek-ai/dsh-client-ui-renderer'\nconst SIDEBAR_MODULE = '@deepseek-ai/dsh-client-ui-sidebar'\nconst SETTINGS_MODULE = '@deepseek-ai/dsh-client-ui-settings'\nconst MOBILE_LAYOUT_DEPENDENCY_PROFILES = Object.freeze([\n Object.freeze({\n slots: RUNTIME_MODULE,\n dependencies: Object.freeze([RUNTIME_MODULE, '@deepseek-ai/dsh-client-ui-theme']),\n }),\n Object.freeze({\n slots: RENDERER_MODULE,\n dependencies: Object.freeze([\n '@deepseek-ai/dsh-client-locale',\n RENDERER_MODULE,\n '@deepseek-ai/dsh-client-ui-session',\n '@deepseek-ai/dsh-client-ui-theme',\n ]),\n }),\n])\nconst MOBILE_CSRF_FETCH_BOOTSTRAP = `(()=>{const nativeFetch=window.fetch.bind(window);window.fetch=(input,init)=>{const source=input instanceof Request?input:undefined;const method=String(init?.method??source?.method??'GET').toUpperCase();if(method==='GET'||method==='HEAD')return nativeFetch(input,init);const raw=typeof input==='string'?input:input instanceof URL?input.href:source?.url;if(raw===undefined||new URL(raw,location.href).origin!==location.origin)return nativeFetch(input,init);const headers=new Headers(init?.headers??source?.headers);if(!headers.has(${JSON.stringify(CSRF_HEADER)})){const prefix=${JSON.stringify(`${CSRF_COOKIE}=`)};const token=document.cookie.split(';').map(value=>value.trim()).find(value=>value.startsWith(prefix))?.slice(prefix.length);if(token!==undefined)headers.set(${JSON.stringify(CSRF_HEADER)},token)}return nativeFetch(input,{...init,headers})};})();`\nconst PAIR_PAGE = `<!doctype html>\n<html lang=\"en\">\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,viewport-fit=cover\">\n<title>Pair DSH mobile access</title>\n<main>\n <h1>Pair this device</h1>\n <form id=\"pair-form\">\n <label>Pairing code <input id=\"pair-token\" autocomplete=\"one-time-code\" required></label>\n <label>Device name <input id=\"device-label\" maxlength=\"64\" autocomplete=\"off\"></label>\n <button type=\"submit\">Pair</button>\n <output id=\"pair-status\"></output>\n </form>\n</main>\n<script src=\"/mobile-access/pair.js\" defer></script>\n</html>\n`\n\ninterface BootGraphEntry {\n id: string\n url: string\n rev: string\n inject?: string[]\n immediately?: boolean\n}\n\ninterface BootGraphBatch {\n phase: 'bootstrap' | 'application'\n url: string\n rev: string\n entries: string[]\n}\n\ninterface MobileBootBatchEntry {\n readonly id: string\n readonly url: string\n readonly rev: string\n}\n\ninterface MobileBootBatchPlan {\n readonly key: string\n readonly path: string\n readonly entries: readonly MobileBootBatchEntry[]\n}\n\ninterface RewrittenMobileIndex {\n readonly html: string\n readonly batch?: MobileBootBatchPlan\n}\n\ninterface StoredMobileBootBatch {\n readonly plan: MobileBootBatchPlan\n body?: Buffer\n gzipBody?: Buffer\n etag?: string\n layoutMtimeMs?: number\n}\n\nconst gzipBuffer = promisify(gzip)\n\nfunction ensureMobileViewport(html: string): string {\n const viewport = /<meta\\b(?=[^>]*\\bname\\s*=\\s*[\"']viewport[\"'])[^>]*>/iu\n const match = viewport.exec(html)\n if (match === null) {\n const head = /<head\\b[^>]*>/iu.exec(html)\n if (head?.index === undefined) return html\n const position = head.index + head[0].length\n return `${html.slice(0, position)}<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,viewport-fit=cover\">${html.slice(position)}`\n }\n if (/\\bviewport-fit\\s*=\\s*cover\\b/iu.test(match[0])) return html\n const content = /\\bcontent\\s*=\\s*([\"'])(.*?)\\1/iu\n const next = content.test(match[0])\n ? match[0].replace(content, (_whole, quote: string, value: string) => `content=${quote}${value},viewport-fit=cover${quote}`)\n : match[0].replace(/\\s*\\/?>$/u, ' content=\"width=device-width,initial-scale=1,viewport-fit=cover\">')\n return `${html.slice(0, match.index)}${next}${html.slice(match.index + match[0].length)}`\n}\n\nfunction orderAuthenticatedSettings(entries: BootGraphEntry[], slotsProvider: string): void {\n const mobile = entries.filter(entry => entry !== null && typeof entry === 'object' && entry.id === MOBILE_CLIENT_MODULE)\n const settings = entries.filter(entry => entry !== null && typeof entry === 'object' && entry.id === SETTINGS_MODULE)\n if (mobile.length === 0 || settings.length === 0) return\n if (mobile.length !== 1 || settings.length !== 1) throw new Error('upstream DSH mobile settings graph is ambiguous')\n if (!Array.isArray(mobile[0]?.inject)\n || !mobile[0].inject.includes(CONNECTION_MODULE)\n || !mobile[0].inject.includes(SIDEBAR_MODULE)) {\n throw new Error('dsh-mobile client has unsupported dependencies')\n }\n if (!Array.isArray(settings[0]?.inject)\n || !settings[0].inject.includes(CONNECTION_MODULE)) {\n throw new Error('upstream DSH settings module has unsupported dependencies')\n }\n mobile[0].inject = [CONNECTION_MODULE, slotsProvider]\n if (!settings[0].inject.includes(MOBILE_CLIENT_MODULE)) settings[0].inject = [...settings[0].inject, MOBILE_CLIENT_MODULE]\n}\n\nfunction revisionedMobileBatchPath(entries: readonly MobileBootBatchEntry[]): { readonly key: string; readonly path: string } {\n const key = createHash('sha256')\n .update(DSH_MOBILE_VERSION)\n .update(JSON.stringify(entries))\n .digest('hex')\n return { key, path: `${MOBILE_BOOT_BATCH_PREFIX}${key}.js` }\n}\n\nfunction rewriteMobileIndexWithBatch(html: string): RewrittenMobileIndex {\n const assignment = /(?:window\\.__DSH_BOOT__|globalThis\\[\"__DSH_BOOT__\"\\])\\s*=\\s*/u.exec(html)\n if (assignment?.index === undefined) throw new Error('upstream DSH index has no boot manifest')\n const start = assignment.index\n const valueStart = start + assignment[0].length\n const scriptEnd = html.indexOf('</script>', valueStart)\n if (scriptEnd < 0) throw new Error('upstream DSH boot manifest script is incomplete')\n const source = html.slice(valueStart, scriptEnd).trim().replace(/;$/u, '')\n const parsed = JSON.parse(source) as { rev?: unknown; entries?: unknown; batches?: unknown }\n if (typeof parsed.rev !== 'string' || !Array.isArray(parsed.entries)) {\n throw new Error('upstream DSH boot manifest is malformed')\n }\n const entries = parsed.entries as BootGraphEntry[]\n const layout = entries.filter(entry => entry !== null && typeof entry === 'object' && entry.id === MOBILE_LAYOUT_MODULE)\n if (layout.length !== 1 || typeof layout[0]?.url !== 'string' || typeof layout[0].rev !== 'string') {\n throw new Error('upstream DSH boot manifest has no unique layout module')\n }\n if (!Array.isArray(layout[0].inject)) {\n throw new Error('upstream DSH layout module has unsupported dependencies')\n }\n const dependencyProfile = MOBILE_LAYOUT_DEPENDENCY_PROFILES.find(profile => (\n profile.dependencies.every(dependency => layout[0]?.inject?.includes(dependency))\n ))\n if (dependencyProfile === undefined) throw new Error('upstream DSH layout module has unsupported dependencies')\n layout[0].url = MOBILE_LAYOUT_PATH\n layout[0].rev = `dsh-mobile-layout-${DSH_MOBILE_VERSION}`\n orderAuthenticatedSettings(entries, dependencyProfile.slots)\n\n let mobileBatch: MobileBootBatchPlan | undefined\n if (parsed.batches !== undefined) {\n if (!Array.isArray(parsed.batches)) throw new Error('upstream DSH boot manifest batches are malformed')\n const batches = parsed.batches as BootGraphBatch[]\n const entryById = new Map(entries.map(entry => [entry.id, entry]))\n if (entryById.size !== entries.length) throw new Error('upstream DSH boot manifest has duplicate entries')\n const layoutBatches: BootGraphBatch[] = []\n for (const batch of batches) {\n if (batch === null || typeof batch !== 'object'\n || (batch.phase !== 'bootstrap' && batch.phase !== 'application')\n || typeof batch.url !== 'string' || typeof batch.rev !== 'string'\n || !Array.isArray(batch.entries) || batch.entries.length === 0\n || batch.entries.some(id => typeof id !== 'string' || !entryById.has(id))) {\n throw new Error('upstream DSH boot manifest batches are malformed')\n }\n if (batch.entries.includes(MOBILE_LAYOUT_MODULE)) layoutBatches.push(batch)\n }\n if (layoutBatches.length !== 1 || layoutBatches[0]?.phase !== 'application') {\n throw new Error('upstream DSH boot manifest has no unique application layout batch')\n }\n const layoutBatch = layoutBatches[0]\n const planEntries = layoutBatch.entries.map((id): MobileBootBatchEntry => {\n const entry = entryById.get(id)\n if (entry === undefined || typeof entry.url !== 'string' || typeof entry.rev !== 'string') {\n throw new Error('upstream DSH boot manifest batches are malformed')\n }\n return Object.freeze({ id, url: entry.url, rev: entry.rev })\n })\n const revision = revisionedMobileBatchPath(planEntries)\n layoutBatch.url = revision.path\n layoutBatch.rev = revision.key\n mobileBatch = Object.freeze({ ...revision, entries: Object.freeze(planEntries) })\n parsed.rev = createHash('sha256').update(JSON.stringify({ entries, batches })).digest('hex').slice(0, 16)\n }\n const replacement = `${MOBILE_CSRF_FETCH_BOOTSTRAP}window.__DSH_MOBILE_FRONTEND__=\"dedicated\";${assignment[0]}${JSON.stringify(parsed)};`\n return Object.freeze({\n html: ensureMobileViewport(`${html.slice(0, start)}${replacement}${html.slice(scriptEnd)}`),\n ...(mobileBatch === undefined ? {} : { batch: mobileBatch }),\n })\n}\n\n/** Replace only DSH's layout client module while retaining its complete plugin graph. */\nexport function rewriteMobileIndex(html: string): string {\n return rewriteMobileIndexWithBatch(html).html\n}\n\nconst PAIR_SCRIPT = `(() => {\n const form = document.getElementById('pair-form')\n const token = document.getElementById('pair-token')\n const label = document.getElementById('device-label')\n const status = document.getElementById('pair-status')\n const fragment = new URLSearchParams(location.hash.slice(1))\n const supplied = fragment.get('token')\n history.replaceState(null, '', location.pathname)\n if (supplied) token.value = supplied\n form.addEventListener('submit', async (event) => {\n event.preventDefault()\n status.value = 'Pairing…'\n const response = await fetch('/mobile-access/auth/pair', {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ token: token.value, label: label.value || undefined }),\n })\n if (!response.ok) {\n status.value = 'Pairing failed'\n return\n }\n location.replace('/')\n })\n})()\n`\n\nconst LOGIN_PAGE = `<!doctype html>\n<html lang=\"en\">\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,viewport-fit=cover\">\n<title>Reconnect DSH mobile access</title>\n<main>\n <h1>Reconnect this device</h1>\n <p id=\"login-progress\">Restoring the secure Session…</p>\n <section id=\"login-failed\" hidden>\n <p>This device is no longer paired. Open pairing on the computer, then pair it again.</p>\n <a href=\"/mobile-access/pair\">Open pairing</a>\n </section>\n</main>\n<script src=\"/mobile-access/login.js\" defer></script>\n</html>\n`\n\nconst LOGIN_SCRIPT = `(() => {\n const candidate = new URL(location.href).searchParams.get('return')\n let returnPath = '/'\n if (candidate && candidate.startsWith('/')) {\n try {\n const resolved = new URL(candidate, location.origin)\n const pathname = decodeURIComponent(resolved.pathname)\n if (resolved.origin === location.origin && pathname !== '/mobile-access'\n && !pathname.startsWith('/mobile-access/') && !pathname.includes('\\\\\\\\')) {\n returnPath = resolved.pathname + resolved.search + resolved.hash\n }\n } catch {\n // Malformed untrusted return targets keep the safe root default.\n }\n }\n fetch('/mobile-access/auth/renew', {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n }).then((response) => {\n if (response.ok) {\n location.replace(returnPath)\n return\n }\n document.getElementById('login-progress').hidden = true\n document.getElementById('login-failed').hidden = false\n }).catch(() => {\n document.getElementById('login-progress').textContent = 'The computer is unavailable.'\n })\n})()\n`\n\nclass ByteLimitTransform extends Transform {\n private total = 0\n\n constructor(private readonly maximum: number) {\n super()\n }\n\n override _transform(chunk: Buffer, encoding: BufferEncoding, callback: TransformCallback): void {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding)\n this.total += buffer.length\n if (this.total > this.maximum) {\n callback(new HttpError(413, 'payload_too_large'))\n return\n }\n callback(null, buffer)\n }\n}\n\nfunction stripIpv6Brackets(hostname: string): string {\n return hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname\n}\n\ninterface PemCertificate {\n readonly pem: string\n readonly certificate: X509Certificate\n}\n\nfunction parsePemCertificates(contents: Buffer, source: string): PemCertificate[] {\n const text = contents.toString('utf8')\n const pattern = /-----BEGIN CERTIFICATE-----[\\s\\S]*?-----END CERTIFICATE-----/gu\n const blocks = text.match(pattern) ?? []\n if (blocks.length === 0 || text.replace(pattern, '').trim() !== '') {\n throw new Error(`${source} must contain only PEM certificates`)\n }\n return blocks.map((pem) => {\n let certificate: X509Certificate\n try {\n certificate = new X509Certificate(pem)\n } catch (error) {\n throw new Error(`${source} contains an invalid certificate`, { cause: error })\n }\n return Object.freeze({ pem: `${pem}\\n`, certificate })\n })\n}\n\nfunction validateServerChain(chain: readonly PemCertificate[]): void {\n const now = Date.now()\n for (const [index, entry] of chain.entries()) {\n if (Date.parse(entry.certificate.validFrom) > now || Date.parse(entry.certificate.validTo) <= now) {\n throw new Error('TLS certificate chain contains a certificate that is not currently valid')\n }\n if (index === 0) continue\n if (entry.certificate.subject === entry.certificate.issuer\n && entry.certificate.verify(entry.certificate.publicKey)) {\n throw new Error('TLS server certificate chain must not include a self-signed root')\n }\n const child = chain[index - 1]!.certificate\n if (!entry.certificate.ca || !child.checkIssued(entry.certificate)\n || !child.verify(entry.certificate.publicKey)) {\n throw new Error('TLS server certificate chain is not an ordered leaf-to-intermediate chain')\n }\n }\n}\n\nasync function tlsOptions(config: ResolvedGatewayConfig): Promise<ServerOptions> {\n if (config.tls.mode === 'disabled') throw new Error('TLS options requested for a disabled listener')\n const [certFile, key, additionalChainFile] = await Promise.all([\n readFile(config.tls.certFile),\n readFile(config.tls.keyFile),\n config.tls.caFile === undefined ? Promise.resolve(undefined) : readFile(config.tls.caFile),\n ])\n const chain = [\n ...parsePemCertificates(certFile, 'tls.certFile'),\n ...(additionalChainFile === undefined ? [] : parsePemCertificates(additionalChainFile, 'tls.caFile')),\n ]\n validateServerChain(chain)\n const leaf = chain[0]!.certificate\n for (const authority of config.authorities) {\n const hostname = stripIpv6Brackets(authority.hostname)\n const match = isIP(hostname) === 0 ? leaf.checkHost(hostname) : leaf.checkIP(hostname)\n if (match === undefined) throw new Error(`TLS certificate does not cover configured authority ${hostname}`)\n }\n return {\n cert: chain.map(entry => entry.pem).join(''),\n key,\n requestCert: false,\n minVersion: 'TLSv1.2',\n maxHeaderSize: MAX_HEADER_BYTES,\n }\n}\n\nfunction websocketAccept(key: string): string {\n return createHash('sha1').update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`, 'ascii').digest('base64')\n}\n\nfunction headerValue(headers: IncomingHttpHeaders, name: string): string | undefined {\n const value = headers[name]\n return Array.isArray(value) ? undefined : value\n}\n\nfunction hasToken(header: string | undefined, token: string): boolean {\n return header?.split(',').some(value => value.trim().toLowerCase() === token) ?? false\n}\n\nfunction rejectUpgrade(socket: Socket, status: number, code: string): void {\n if (socket.destroyed) return\n const body = `${JSON.stringify({ error: code })}\\n`\n socket.end([\n `HTTP/1.1 ${String(status)} ${status === 401 ? 'Unauthorized' : status === 403 ? 'Forbidden' : 'Bad Request'}`,\n 'Connection: close',\n 'Cache-Control: no-store',\n 'Content-Type: application/json; charset=utf-8',\n 'Referrer-Policy: no-referrer',\n 'X-Content-Type-Options: nosniff',\n `Content-Length: ${String(Buffer.byteLength(body))}`,\n '',\n body,\n ].join('\\r\\n'))\n}\n\nfunction sanitizeRequestHeaders(\n request: IncomingMessage,\n upstream: URL,\n): OutgoingHttpHeaders {\n const headers: OutgoingHttpHeaders = {\n host: upstream.host,\n }\n if (request.headers.origin !== undefined) headers.origin = upstream.origin\n if (request.headers['sec-fetch-site'] !== undefined) headers['sec-fetch-site'] = 'same-origin'\n const allowed = [\n 'accept', 'accept-encoding', 'accept-language', 'content-encoding', 'content-length', 'content-type',\n 'if-match', 'if-modified-since', 'if-none-match', 'if-unmodified-since', 'range', 'user-agent',\n ] as const\n for (const name of allowed) {\n const value = request.headers[name]\n if (value !== undefined) headers[name] = value\n }\n return headers\n}\n\nconst BLOCKED_RESPONSE_HEADERS = new Set([\n 'alt-svc', 'cache-control', 'connection', 'content-security-policy', 'content-security-policy-report-only',\n 'cross-origin-embedder-policy', 'cross-origin-opener-policy', 'cross-origin-resource-policy', 'expires',\n 'keep-alive', 'nel', 'permissions-policy', 'pragma', 'proxy-authenticate', 'referrer-policy',\n 'report-to', 'reporting-endpoints', 'server', 'set-cookie', 'strict-transport-security', 'trailer',\n 'transfer-encoding', 'upgrade', 'via', 'x-content-type-options', 'x-frame-options', 'x-powered-by',\n])\n\nfunction sanitizeResponseHeaders(headers: IncomingHttpHeaders, upstream: URL): OutgoingHttpHeaders {\n const clean: OutgoingHttpHeaders = {}\n for (const [name, value] of Object.entries(headers)) {\n const lower = name.toLowerCase()\n if (value === undefined || BLOCKED_RESPONSE_HEADERS.has(lower) || lower.startsWith('access-control-')) continue\n if (lower === 'location' && typeof value === 'string') {\n try {\n const location = new URL(value, upstream)\n clean.location = location.origin === upstream.origin\n ? `${location.pathname}${location.search}${location.hash}`\n : value\n } catch {\n continue\n }\n continue\n }\n clean[lower] = value\n }\n return clean\n}\n\nfunction acceptsGzip(header: string | undefined): boolean {\n if (header === undefined) return false\n let wildcard: boolean | undefined\n for (const entry of header.split(',')) {\n const [rawName, ...parameters] = entry.split(';')\n const name = rawName?.trim().toLowerCase()\n if (name === undefined || name === '') continue\n let quality = 1\n for (const parameter of parameters) {\n const match = /^\\s*q\\s*=\\s*(0(?:\\.\\d+)?|1(?:\\.0+)?)\\s*$/iu.exec(parameter)\n if (match !== null) quality = Number(match[1])\n }\n if (name === 'gzip') return quality > 0\n if (name === '*') wildcard = quality > 0\n }\n return wildcard ?? false\n}\n\nfunction isCompressibleContentType(value: string | string[] | undefined): boolean {\n const contentType = Array.isArray(value) ? value[0] : value\n if (contentType === undefined) return false\n const mediaType = contentType.split(';', 1)[0]?.trim().toLowerCase() ?? ''\n return mediaType.startsWith('text/')\n || /^(?:application\\/(?:javascript|json|xml|x-javascript)|image\\/svg\\+xml)$/u.test(mediaType)\n}\n\nfunction shouldCompressResponse(request: IncomingMessage, response: IncomingMessage): boolean {\n const pathname = request.url?.split('?', 1)[0] ?? ''\n const compressibleRequest = (request.method === 'GET'\n && (pathname.startsWith('/plugins/') || pathname.startsWith('/assets/')))\n || (request.method === 'POST' && pathname === SESSION_HISTORY_PATH)\n return compressibleRequest\n && response.statusCode === 200\n && request.headers.range === undefined\n && response.headers['content-range'] === undefined\n && response.headers['content-encoding'] === undefined\n && acceptsGzip(request.headers['accept-encoding'])\n && isCompressibleContentType(response.headers['content-type'])\n}\n\nfunction revisionedStaticCacheControl(request: IncomingMessage): string | undefined {\n if (request.method !== 'GET' && request.method !== 'HEAD') return undefined\n let target: URL\n try { target = new URL(request.url ?? '/', 'https://dsh-mobile.invalid') } catch { return undefined }\n const revision = target.searchParams.get('rev')\n const hasRevision = revision !== null && /^[a-z0-9_-]{4,128}$/iu.test(revision)\n const hashedAsset = /^\\/assets\\/.*-[a-z0-9_-]{8,}\\.[a-z0-9]+$/iu.test(target.pathname)\n if (!(target.pathname.startsWith('/plugins/') && hasRevision)\n && !(target.pathname.startsWith('/assets/') && (hasRevision || hashedAsset))) return undefined\n return 'private, max-age=31536000, immutable'\n}\n\nfunction isJsonRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction mobileHistoryRequestBody(request: IncomingMessage, body: Buffer): Buffer {\n if (request.method !== 'POST' || request.url?.split('?', 1)[0] !== SESSION_HISTORY_PATH) return body\n let parsed: unknown\n try {\n parsed = JSON.parse(body.toString('utf8'))\n } catch {\n return body\n }\n if (!isJsonRecord(parsed) || parsed.method !== 'session.history' || !isJsonRecord(parsed.payload)) return body\n const requested = parsed.payload.maxMessages\n if (typeof requested === 'number' && Number.isInteger(requested) && requested > 0 && requested <= MOBILE_HISTORY_PAGE_MESSAGES) {\n return body\n }\n return Buffer.from(JSON.stringify({\n ...parsed,\n payload: { ...parsed.payload, maxMessages: MOBILE_HISTORY_PAGE_MESSAGES },\n }))\n}\n\nfunction addVaryAcceptEncoding(headers: OutgoingHttpHeaders): void {\n const existing = headers.vary\n const rawValues: string[] = Array.isArray(existing)\n ? existing.map(value => String(value))\n : existing === undefined ? [] : [String(existing)]\n const values = rawValues.flatMap(value => value.split(',').map(part => part.trim()).filter(Boolean))\n if (!values.some(value => value.toLowerCase() === 'accept-encoding')) values.push('Accept-Encoding')\n headers.vary = values.join(', ')\n}\n\nfunction requestCookies(request: IncomingMessage): ReadonlyMap<string, string> {\n const cookies = parseCookies(request.headers.cookie)\n if (cookies === undefined) throw new HttpError(401, 'authentication_failed')\n return cookies\n}\n\nfunction mapError(error: unknown): HttpError {\n if (error instanceof HttpError) return error\n if (error instanceof AccessError) return new HttpError(error.status, error.code)\n if (error instanceof MobileExtensionError) return new HttpError(error.status, error.code)\n return new HttpError(500, 'internal_error')\n}\n\nfunction discoveryDeviceName(): string {\n const value = hostname().trim().replaceAll(/[\\u0000-\\u001f\\u007f]/gu, '')\n return (value === '' ? 'DeepSeek Harness' : value).slice(0, 63)\n}\n\nfunction discoveryMdnsHost(instanceId: string): string {\n const label = hostname().toLowerCase().replaceAll(/[^a-z0-9-]/gu, '-').replaceAll(/^-+|-+$/gu, '').slice(0, 40)\n return `${label === '' ? 'dsh' : label}-${instanceId.slice(0, 8)}.local`\n}\n\nfunction discoveryBroadcastTargets(cidrs: readonly ParsedCidr[]): readonly string[] {\n const targets = new Set<string>(['255.255.255.255'])\n for (const cidr of cidrs) {\n if (cidr.bits !== 32 || cidr.prefix >= 32) continue\n const hostBits = BigInt(32 - cidr.prefix)\n const broadcast = cidr.network | ((1n << hostBits) - 1n)\n targets.add([24n, 16n, 8n, 0n].map(shift => Number((broadcast >> shift) & 0xffn)).join('.'))\n }\n return [...targets]\n}\n\nfunction extensionTarget(pathname: string):\n | { readonly kind: 'manifest' }\n | { readonly kind: 'events' }\n | { readonly kind: 'script' | 'style' | 'asset'; readonly id: string; readonly path?: string }\n | { readonly kind: 'action'; readonly id: string; readonly action: string }\n | { readonly kind: 'route'; readonly id: string; readonly path: string }\n | undefined {\n const prefix = `${AUTH_PREFIX}/extensions`\n if (pathname === prefix || pathname === `${prefix}/` || pathname === `${prefix}/manifest`) return { kind: 'manifest' }\n if (pathname === `${prefix}/events`) return { kind: 'events' }\n if (!pathname.startsWith(`${prefix}/`)) return undefined\n const parts = pathname.slice(prefix.length + 1).split('/')\n const id = parts.shift()\n if (id === undefined || !/^[a-z][a-z0-9-]{0,63}$/u.test(id)) return undefined\n const leaf = parts.shift()\n if (leaf === 'mobile.js' && parts.length === 0) return { kind: 'script', id }\n if (leaf === 'mobile.css' && parts.length === 0) return { kind: 'style', id }\n if (leaf === 'assets' && parts.length > 0) return { kind: 'asset', id, path: parts.join('/') }\n if (leaf === 'actions' && parts.length === 1 && /^[a-z][a-z0-9-]{0,63}$/u.test(parts[0]!)) return { kind: 'action', id, action: parts[0]! }\n if (leaf === 'routes') return { kind: 'route', id, path: `/${parts.join('/')}`.replace(/\\/{2,}/gu, '/') }\n return undefined\n}\n\nconst EXTENSION_GENERATION_HEADER = 'x-dsh-mobile-extension-generation'\n\nfunction extensionGeneration(value: string | undefined): string | undefined {\n if (value === undefined) return undefined\n if (!/^[a-f\\d]{64}$/u.test(value)) throw new HttpError(400, 'invalid_extension_generation')\n return value\n}\n\nfunction mobileBootBatchKey(pathname: string): string | undefined {\n const match = new RegExp(`^${MOBILE_BOOT_BATCH_PREFIX.replaceAll('/', '\\\\/')}([a-f\\\\d]{64})\\\\.js$`, 'u').exec(pathname)\n return match?.[1]\n}\n\nfunction assertBoundedContentLength(request: IncomingMessage, maximum: number): void {\n const declared = request.headers['content-length']\n if (declared !== undefined && (!/^\\d+$/u.test(declared) || Number(declared) > maximum)) {\n throw new HttpError(413, 'payload_too_large')\n }\n}\n\nasync function readBoundedBody(request: IncomingMessage, maximum: number): Promise<Buffer> {\n assertBoundedContentLength(request, maximum)\n const chunks: Buffer[] = []\n let total = 0\n for await (const chunk of request) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n total += buffer.length\n if (total > maximum) throw new HttpError(413, 'payload_too_large')\n chunks.push(buffer)\n }\n return Buffer.concat(chunks)\n}\n\nfunction extensionRequestHeaders(headers: IncomingHttpHeaders): Readonly<Record<string, string>> {\n const allowed = new Set(['accept', 'content-type', 'content-length', 'content-range', 'range', 'if-none-match', 'if-modified-since'])\n const output: Record<string, string> = {}\n for (const [name, value] of Object.entries(headers)) {\n if (!allowed.has(name) || typeof value !== 'string') continue\n output[name] = value\n }\n return Object.freeze(output)\n}\n\nfunction extensionContentType(path: string): string {\n const type = {\n '.css': 'text/css; charset=utf-8',\n '.csv': 'text/csv; charset=utf-8',\n '.gif': 'image/gif',\n '.html': 'text/html; charset=utf-8',\n '.jpeg': 'image/jpeg',\n '.jpg': 'image/jpeg',\n '.js': 'text/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.png': 'image/png',\n '.svg': 'image/svg+xml',\n '.webp': 'image/webp',\n }[extname(path).toLowerCase()]\n return type ?? 'application/octet-stream'\n}\n\n/** Authenticated TLS edge in front of the ordinary loopback-only DSH Web server. */\nexport class MobileAccessGateway {\n readonly access: AccessController\n private readonly listenerTlsEnabled: boolean\n private readonly tlsEnabled: boolean\n private policy: RequestTrustPolicy | undefined\n private server: GatewayServer | undefined\n private discoverySocket: DatagramSocket | undefined\n private discoveryTimer: NodeJS.Timeout | undefined\n private bonjour: Bonjour | undefined\n private pairingCaCertificate: string | undefined\n private listenerPort: number | undefined\n private readonly connectedSockets = new Set<Socket>()\n private readonly activeRequests = new Map<number, ActiveRequest>()\n private readonly activeWebSockets = new Map<number, ActiveWebSocket>()\n private readonly mobileBootBatches = new Map<string, StoredMobileBootBatch>()\n private readonly extensionEventListeners = new Set<(revision: number) => void>()\n private extensionEventRevision = 0\n private extensionChangeTimer: NodeJS.Timeout | undefined\n private extensionChangeTask: Promise<void> | undefined\n private legacyCustomDigest = ''\n private upstreamCookie: string | undefined\n private upstreamCookieExpiresAt = 0\n private upstreamCookieTask: Promise<string> | undefined\n private upstreamAuthRequest: ClientRequest | undefined\n private nextOperationId = 1\n private closing = false\n private started = false\n private closeTask: Promise<void> | undefined\n private readonly removeSessionListener: () => void\n private readonly removeExtensionContentListener: () => void\n private readonly renewLimiter: BoundedRateLimiter\n\n constructor(\n readonly config: ResolvedGatewayConfig,\n store: DeviceStore,\n private readonly extensions?: MobileAccessService,\n private readonly upstreamAuthenticatedUrl?: string,\n ) {\n this.listenerTlsEnabled = config.tls.mode === 'provided'\n this.tlsEnabled = config.publicTls\n this.access = new AccessController(store, {\n pairingTtlMs: config.pairingTtlMs,\n deviceTtlMs: config.deviceTtlMs,\n sessionTtlMs: config.sessionTtlMs,\n maxDevices: config.maxDevices,\n maxSessions: config.maxSessions,\n rateLimitWindowMs: config.rateLimitWindowMs,\n maxPairingAttempts: config.maxPairingAttempts,\n maxRateLimitKeys: config.maxRateLimitKeys,\n })\n this.renewLimiter = new BoundedRateLimiter(\n Math.min(100, config.maxPairingAttempts * 4),\n config.rateLimitWindowMs,\n config.maxRateLimitKeys,\n )\n this.removeSessionListener = this.access.onSessionEnded(authorization => {\n this.abortSessionResources(authorization.sessionKey)\n })\n this.removeExtensionContentListener = this.extensions?.onContentChanged(() => {\n this.broadcastExtensionChange()\n }) ?? (() => undefined)\n }\n\n /** Initialize durable state, validate TLS, and bind the externally reachable listener. */\n async start(): Promise<void> {\n if (this.started || this.server !== undefined) throw new Error('mobile-access gateway cannot be started twice')\n this.started = true\n await this.access.initialize()\n try {\n if (this.config.pairingCaFile !== undefined) {\n const certificate = new X509Certificate(await readFile(this.config.pairingCaFile))\n const fingerprint = certificate.fingerprint256.replaceAll(':', '').toLowerCase()\n if (!certificate.ca || certificate.subject !== certificate.issuer\n || !certificate.verify(certificate.publicKey) || fingerprint !== this.config.instanceId) {\n throw new Error('pairingCaFile must be the self-signed CA identified by instanceId')\n }\n this.pairingCaCertificate = certificate.raw.toString('base64')\n }\n const handler = (request: IncomingMessage, response: ServerResponse): void => {\n void this.handleExternalRequest(request, response).catch((error: unknown) => {\n const mapped = mapError(error)\n if (response.headersSent) response.destroy()\n else sendFailure(response, mapped.status, mapped.code, this.tlsEnabled)\n })\n }\n const server = this.listenerTlsEnabled\n ? createHttpsServer(await tlsOptions(this.config), handler)\n : createHttpServer({ maxHeaderSize: MAX_HEADER_BYTES }, handler)\n this.server = server\n server.maxHeadersCount = 64\n server.maxConnections = this.config.maxConnections\n server.headersTimeout = 10_000\n server.requestTimeout = this.config.upstreamTimeoutMs\n server.keepAliveTimeout = 5_000\n server.on('connection', (socket: Socket) => {\n if (this.connectedSockets.size >= this.config.maxConnections) {\n socket.destroy()\n return\n }\n this.connectedSockets.add(socket)\n socket.on('error', () => { socket.destroy() })\n socket.once('close', () => { this.connectedSockets.delete(socket) })\n })\n server.on('connect', (_request, socket) => { socket.destroy() })\n server.on('upgrade', (request, socket, head) => {\n void this.handleUpgrade(request, socket as Socket, head).catch((error: unknown) => {\n const mapped = mapError(error)\n rejectUpgrade(socket as Socket, mapped.status, mapped.code)\n })\n })\n server.on('clientError', (_error, socket) => { rejectUpgrade(socket as Socket, 400, 'bad_request') })\n await new Promise<void>((resolve, reject) => {\n const failed = (error: Error): void => { reject(error) }\n server.once('error', failed)\n server.listen(this.config.listenPort, this.config.listenHost, () => {\n server.off('error', failed)\n resolve()\n })\n })\n const address = server.address()\n if (address === null || typeof address === 'string') throw new Error('gateway listener has no TCP address')\n this.listenerPort = address.port\n this.policy = new RequestTrustPolicy(\n this.config.authorities,\n address.port,\n this.config.allowedCidrs,\n this.tlsEnabled,\n )\n if (this.config.discovery) await this.startDiscovery(address.port)\n await this.pollLegacyCustomChanges()\n this.extensionChangeTimer = setInterval(() => { void this.pollLegacyCustomChanges() }, EXTENSION_CHANGE_POLL_MS)\n this.extensionChangeTimer.unref()\n } catch (error) {\n await this.closeFailedStart()\n throw error\n }\n }\n\n private async startDiscovery(port: number): Promise<void> {\n const socket = createSocket('udp4')\n this.discoverySocket = socket\n const announcement = this.discoveryAnnouncement(port)\n socket.on('message', (message, remote) => {\n if (this.closing || !message.equals(DISCOVERY_QUERY)\n || !addressAllowed(remote.address, this.config.allowedCidrs)) return\n socket.send(announcement, remote.port, remote.address, () => undefined)\n })\n await new Promise<void>((resolve, reject) => {\n const failed = (error: Error): void => { reject(error) }\n socket.once('error', failed)\n // The UDP socket is IPv4-only; only a literal IPv4 loopback address is bindable, never ::1.\n const bindHost = isIP(this.config.listenHost) === 4 && isLoopbackAddress(this.config.listenHost) ? this.config.listenHost : '0.0.0.0'\n socket.bind(port, bindHost, () => {\n socket.off('error', failed)\n socket.setBroadcast(true)\n resolve()\n })\n })\n const announce = (): void => {\n for (const target of discoveryBroadcastTargets(this.config.allowedCidrs)) {\n socket.send(announcement, port, target, () => undefined)\n }\n }\n announce()\n this.discoveryTimer = setInterval(announce, DISCOVERY_INTERVAL_MS)\n this.discoveryTimer.unref()\n\n const deviceName = discoveryDeviceName()\n const bonjour = new Bonjour({ disableIPv6: true })\n this.bonjour = bonjour\n bonjour.publish({\n name: `${deviceName} (${this.config.instanceId.slice(0, 8)})`,\n type: MDNS_SERVICE_TYPE,\n protocol: 'tcp',\n port,\n host: discoveryMdnsHost(this.config.instanceId),\n disableIPv6: true,\n txt: {\n deviceName,\n origin: this.address().origin,\n instanceId: this.config.instanceId,\n protocol: String(DISCOVERY_PROTOCOL),\n },\n })\n }\n\n private discoveryAnnouncement(port: number): Buffer {\n return Buffer.from(JSON.stringify({\n deviceName: discoveryDeviceName(),\n origin: this.address().origin,\n port,\n protocol: DISCOVERY_PROTOCOL,\n instanceId: this.config.instanceId,\n }), 'utf8')\n }\n\n private async closeFailedStart(): Promise<void> {\n if (this.extensionChangeTimer !== undefined) clearInterval(this.extensionChangeTimer)\n this.extensionChangeTimer = undefined\n this.removeExtensionContentListener()\n if (this.discoveryTimer !== undefined) clearInterval(this.discoveryTimer)\n this.discoveryTimer = undefined\n await this.closeBonjour()\n this.discoverySocket?.close()\n this.discoverySocket = undefined\n for (const socket of this.connectedSockets) socket.destroy()\n const server = this.server\n this.server = undefined\n if (server?.listening === true) {\n await new Promise<void>(resolve => { server.close(() => resolve()) })\n }\n await this.access.close()\n }\n\n private async closeBonjour(): Promise<void> {\n const bonjour = this.bonjour\n this.bonjour = undefined\n if (bonjour === undefined) return\n await new Promise<void>(resolve => {\n bonjour.unpublishAll(() => { bonjour.destroy(() => resolve()) })\n })\n }\n\n /** Actual bound address, available after start and safe for loopback status output. */\n address(): { host: string; port: number; origin: string } {\n if (this.listenerPort === undefined || this.policy === undefined) throw new Error('gateway is not listening')\n const origin = this.policy.origins.values().next().value as string | undefined\n if (origin === undefined) throw new Error('gateway has no public authority')\n return Object.freeze({ host: this.config.listenHost, port: this.listenerPort, origin })\n }\n\n private requirePolicy(): RequestTrustPolicy {\n if (this.policy === undefined || this.closing) throw new HttpError(503, 'unavailable')\n return this.policy\n }\n\n private authorize(request: IncomingMessage): SessionAuthorization {\n const sessionToken = requestCookies(request).get(SESSION_COOKIE)\n if (sessionToken === undefined) throw new HttpError(401, 'authentication_failed')\n return this.access.authorizeSession(sessionToken)\n }\n\n private requireCsrf(request: IncomingMessage, authorization: SessionAuthorization): void {\n const value = headerValue(request.headers, CSRF_HEADER)\n this.access.assertCsrf(authorization, value)\n }\n\n private setSessionCookies(response: ServerResponse, result: {\n sessionToken: string\n csrfToken: string\n sessionExpiresAt: number\n }, now: number): void {\n const maxAge = (result.sessionExpiresAt - now) / 1000\n response.setHeader('Set-Cookie', [\n cookie(SESSION_COOKIE, result.sessionToken, { tls: this.tlsEnabled, httpOnly: true, path: '/', maxAgeSeconds: maxAge }),\n cookie(CSRF_COOKIE, result.csrfToken, { tls: this.tlsEnabled, httpOnly: false, path: '/', maxAgeSeconds: maxAge }),\n ])\n }\n\n private async handlePair(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const body = await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n if (typeof body.token !== 'string' || (body.label !== undefined && typeof body.label !== 'string')) {\n throw new HttpError(400, 'bad_request')\n }\n const result = await this.access.pair(request.socket.remoteAddress ?? 'unknown', body.token, body.label as string | undefined)\n const now = Date.now()\n this.setSessionCookies(response, result, now)\n const sessionCookies = response.getHeader('Set-Cookie') as string[]\n response.setHeader('Set-Cookie', [\n ...sessionCookies,\n cookie(DEVICE_COOKIE, result.deviceToken, {\n tls: this.tlsEnabled,\n httpOnly: true,\n path: '/mobile-access/auth/renew',\n maxAgeSeconds: (result.deviceExpiresAt - now) / 1000,\n }),\n ])\n sendJson(response, 201, {\n paired: true,\n deviceId: result.deviceId,\n csrfToken: result.csrfToken,\n sessionExpiresAt: result.sessionExpiresAt,\n }, this.tlsEnabled)\n }\n\n private async handleRenew(request: IncomingMessage, response: ServerResponse): Promise<void> {\n if (!this.renewLimiter.take(request.socket.remoteAddress ?? 'unknown', Date.now())) {\n throw new HttpError(429, 'rate_limited')\n }\n await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n const deviceToken = requestCookies(request).get(DEVICE_COOKIE)\n if (deviceToken === undefined) throw new HttpError(401, 'authentication_failed')\n let result\n try {\n result = await this.access.renew(deviceToken)\n } catch (error) {\n if (error instanceof AccessError && error.status === 401) {\n response.setHeader('Set-Cookie', cookie(DEVICE_COOKIE, '', {\n tls: this.tlsEnabled,\n httpOnly: true,\n path: '/mobile-access/auth/renew',\n maxAgeSeconds: 0,\n }))\n }\n throw error\n }\n this.setSessionCookies(response, result, Date.now())\n sendJson(response, 200, {\n renewed: true,\n deviceId: result.deviceId,\n csrfToken: result.csrfToken,\n sessionExpiresAt: result.sessionExpiresAt,\n }, this.tlsEnabled)\n }\n\n private async handleNativePair(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const body = await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n if (typeof body.token !== 'string' || (body.label !== undefined && typeof body.label !== 'string')) {\n throw new HttpError(400, 'bad_request')\n }\n const result = await this.access.pair(\n request.socket.remoteAddress ?? 'unknown',\n body.token,\n body.label as string | undefined,\n )\n sendJson(response, 201, {\n instanceId: this.config.instanceId,\n deviceId: result.deviceId,\n deviceToken: result.deviceToken,\n deviceExpiresAt: result.deviceExpiresAt,\n sessionToken: result.sessionToken,\n csrfToken: result.csrfToken,\n sessionExpiresAt: result.sessionExpiresAt,\n }, this.tlsEnabled)\n }\n\n private async handleNativeRenew(request: IncomingMessage, response: ServerResponse): Promise<void> {\n if (!this.renewLimiter.take(request.socket.remoteAddress ?? 'unknown', Date.now())) {\n throw new HttpError(429, 'rate_limited')\n }\n const body = await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n if (typeof body.deviceToken !== 'string') throw new HttpError(400, 'bad_request')\n const result = await this.access.renew(body.deviceToken)\n sendJson(response, 200, {\n instanceId: this.config.instanceId,\n deviceId: result.deviceId,\n sessionToken: result.sessionToken,\n csrfToken: result.csrfToken,\n sessionExpiresAt: result.sessionExpiresAt,\n }, this.tlsEnabled)\n }\n\n private async handleLogout(request: IncomingMessage, response: ServerResponse): Promise<void> {\n await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n const authorization = this.authorize(request)\n this.requireCsrf(request, authorization)\n this.access.logout(authorization)\n response.setHeader('Set-Cookie', [\n cookie(SESSION_COOKIE, '', { tls: this.tlsEnabled, httpOnly: true, path: '/', maxAgeSeconds: 0 }),\n cookie(CSRF_COOKIE, '', { tls: this.tlsEnabled, httpOnly: false, path: '/', maxAgeSeconds: 0 }),\n ])\n sendJson(response, 200, { loggedOut: true }, this.tlsEnabled)\n }\n\n private async handleExternalRequest(request: IncomingMessage, response: ServerResponse): Promise<void> {\n const target = parseRequestTarget(request.url)\n const policy = this.requirePolicy()\n const isMutation = request.method !== 'GET' && request.method !== 'HEAD'\n assertExternalTrust(request, policy, isMutation)\n if (target.decodedPathname === LOCAL_ADMIN_PREFIX || target.decodedPathname.startsWith(`${LOCAL_ADMIN_PREFIX}/`)) {\n throw new HttpError(404, 'not_found')\n }\n if (request.method === 'TRACE' || request.method === 'CONNECT') throw new HttpError(405, 'method_not_allowed')\n\n if (target.search === '' && request.method === 'GET' && target.decodedPathname === `${AUTH_PREFIX}/health`) {\n sendJson(response, 200, { ok: true }, this.tlsEnabled)\n return\n }\n if (target.search === '' && request.method === 'GET' && target.decodedPathname === `${AUTH_PREFIX}/metadata`) {\n sendJson(response, 200, {\n version: MOBILE_METADATA_VERSION,\n pluginVersion: DSH_MOBILE_VERSION,\n minimumAndroidAppVersion: MINIMUM_ANDROID_APP_VERSION,\n discoveryProtocol: DISCOVERY_PROTOCOL,\n }, this.tlsEnabled)\n return\n }\n if (target.search === '' && request.method === 'GET' && target.decodedPathname === `${AUTH_PREFIX}/discovery`) {\n sendJson(response, 200, {\n deviceName: discoveryDeviceName(),\n origin: this.address().origin,\n port: this.address().port,\n protocol: DISCOVERY_PROTOCOL,\n instanceId: this.config.instanceId,\n }, this.tlsEnabled)\n return\n }\n if (target.search === '' && request.method === 'GET' && target.decodedPathname === `${AUTH_PREFIX}/ca.cer`) {\n if (this.pairingCaCertificate === undefined) throw new HttpError(404, 'not_found')\n const body = Buffer.from(this.pairingCaCertificate, 'base64')\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, {\n 'Content-Type': 'application/pkix-cert',\n 'Content-Length': body.length,\n 'Cache-Control': 'no-store',\n })\n response.end(body)\n return\n }\n if (target.search === '' && request.method === 'GET'\n && (target.decodedPathname === `${AUTH_PREFIX}/pair` || target.decodedPathname === `${AUTH_PREFIX}/pair.js`)) {\n if (!this.access.pairingStatus().open) throw new HttpError(404, 'not_found')\n setSecurityHeaders(response, this.tlsEnabled)\n const body = target.decodedPathname.endsWith('.js') ? PAIR_SCRIPT : PAIR_PAGE\n response.writeHead(200, {\n 'Content-Type': target.decodedPathname.endsWith('.js') ? 'text/javascript; charset=utf-8' : 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body),\n })\n response.end(body)\n return\n }\n if (request.method === 'GET'\n && (target.decodedPathname === `${AUTH_PREFIX}/login` || target.decodedPathname === `${AUTH_PREFIX}/login.js`)) {\n if (target.decodedPathname.endsWith('.js') && target.search !== '') throw new HttpError(400, 'bad_request')\n setSecurityHeaders(response, this.tlsEnabled)\n const body = target.decodedPathname.endsWith('.js') ? LOGIN_SCRIPT : LOGIN_PAGE\n response.writeHead(200, {\n 'Content-Type': target.decodedPathname.endsWith('.js') ? 'text/javascript; charset=utf-8' : 'text/html; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body),\n })\n response.end(body)\n return\n }\n if (target.search === '' && request.method === 'POST' && target.decodedPathname === `${AUTH_PREFIX}/auth/pair`) {\n await this.handlePair(request, response)\n return\n }\n if (target.search === '' && request.method === 'POST' && target.decodedPathname === `${AUTH_PREFIX}/auth/renew`) {\n await this.handleRenew(request, response)\n return\n }\n if (target.search === '' && request.method === 'POST' && target.decodedPathname === `${AUTH_PREFIX}/auth/native-pair`) {\n await this.handleNativePair(request, response)\n return\n }\n if (target.search === '' && request.method === 'POST' && target.decodedPathname === `${AUTH_PREFIX}/auth/native-renew`) {\n await this.handleNativeRenew(request, response)\n return\n }\n if (target.search === '' && request.method === 'POST' && target.decodedPathname === `${AUTH_PREFIX}/auth/logout`) {\n await this.handleLogout(request, response)\n return\n }\n const computerImages = request.method === 'GET' && target.decodedPathname === `${AUTH_PREFIX}/computer-images`\n const computerImage = request.method === 'GET' && target.decodedPathname === `${AUTH_PREFIX}/computer-image`\n const requestedExtension = extensionTarget(target.decodedPathname)\n const requestedMobileBootBatch = mobileBootBatchKey(target.decodedPathname)\n const customAsset = request.method === 'GET'\n ? target.decodedPathname === `${AUTH_PREFIX}/custom.css`\n ? {\n file: this.config.customCssFile,\n contentType: 'text/css; charset=utf-8',\n fallback: CUSTOM_STYLE_FALLBACK,\n }\n : target.decodedPathname === `${AUTH_PREFIX}/custom.js`\n ? {\n file: this.config.customScriptFile,\n contentType: 'text/javascript; charset=utf-8',\n fallback: CUSTOM_SCRIPT_FALLBACK,\n }\n : target.decodedPathname === MOBILE_LAYOUT_PATH\n ? {\n file: this.config.mobileLayoutFile,\n contentType: 'text/javascript; charset=utf-8',\n fallback: undefined,\n }\n : undefined\n : undefined\n if (customAsset === undefined && requestedMobileBootBatch === undefined && !computerImages && !computerImage\n && extensionTarget(target.decodedPathname) === undefined\n && (target.decodedPathname === AUTH_PREFIX || target.decodedPathname.startsWith(`${AUTH_PREFIX}/`))) {\n throw new HttpError(404, 'not_found')\n }\n\n if (request.method !== 'GET' && request.method !== 'HEAD' && request.method !== 'POST'\n && requestedExtension?.kind !== 'route') {\n throw new HttpError(405, 'method_not_allowed')\n }\n let authorization: SessionAuthorization\n try {\n authorization = this.authorize(request)\n } catch (error) {\n const mapped = mapError(error)\n const acceptsHtml = request.headers.accept?.split(',').some(value => value.trim().split(';', 1)[0] === 'text/html') ?? false\n const topLevel = request.method === 'GET'\n && acceptsHtml\n && (request.headers['sec-fetch-dest'] === undefined || request.headers['sec-fetch-dest'] === 'document')\n && target.decodedPathname !== '/api'\n && !target.decodedPathname.startsWith('/api/')\n if (mapped.status === 401 && topLevel) {\n const returnPath = target.raw.length <= 2048 ? target.raw : '/'\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(302, {\n Location: `${AUTH_PREFIX}/login?return=${encodeURIComponent(returnPath)}`,\n 'Content-Length': 0,\n })\n response.end()\n return\n }\n throw error\n }\n if (isMutation) this.requireCsrf(request, authorization)\n const extension = requestedExtension\n if (extension !== undefined) {\n await this.handleExtensionRequest(extension, target, request, response, authorization)\n return\n }\n if (requestedMobileBootBatch !== undefined) {\n await this.serveMobileBootBatch(requestedMobileBootBatch, request, response, authorization)\n return\n }\n if (customAsset !== undefined) {\n const operation = this.allocateRequest(authorization, response, {})\n try {\n let body: Buffer\n let mtime: Date | undefined\n try {\n body = await readFile(customAsset.file, { signal: operation.signal })\n try {\n const fileStat = await stat(customAsset.file)\n mtime = fileStat.mtime\n } catch { /* keep undefined */ }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n if (customAsset.fallback === undefined) throw new HttpError(503, 'mobile_frontend_unavailable')\n body = Buffer.from(customAsset.fallback)\n }\n if (body.byteLength > 256 * 1024) throw new HttpError(413, 'payload_too_large')\n const etag = createHash('sha256').update(body).digest('hex')\n const ifNoneMatch = headerValue(request.headers, 'if-none-match')\n if (ifNoneMatch !== undefined && ifNoneMatch === etag) {\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(304)\n response.end()\n return\n }\n setSecurityHeaders(response, this.tlsEnabled)\n const responseHeaders: Record<string, string | number> = {\n 'Content-Type': customAsset.contentType,\n 'Content-Length': body.byteLength,\n 'ETag': etag,\n }\n if (mtime !== undefined) responseHeaders['Last-Modified'] = mtime.toUTCString()\n response.writeHead(200, responseHeaders)\n response.end(body)\n return\n } finally {\n operation.release()\n }\n }\n if (computerImages) {\n const operation = this.allocateRequest(authorization, response, {})\n try {\n const query = new URL(target.raw, this.address().origin).searchParams\n sendJson(response, 200, await listComputerImages(query.get('path'), operation.signal), this.tlsEnabled)\n return\n } finally {\n operation.release()\n }\n }\n if (computerImage) {\n const operation = this.allocateRequest(authorization, response, {})\n try {\n const query = new URL(target.raw, this.address().origin).searchParams\n const image = await readComputerImage(query.get('path'), operation.signal)\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, {\n 'Content-Type': image.contentType,\n 'Content-Length': image.body.byteLength,\n 'Content-Disposition': `inline; filename*=UTF-8''${encodeURIComponent(image.name)}`,\n })\n response.end(image.body)\n return\n } finally {\n operation.release()\n }\n }\n const stockFrontend = new URL(target.raw, this.address().origin).searchParams.get('frontend') === 'stock'\n const acceptsHtml = request.headers.accept?.split(',').some(value => value.trim().split(';', 1)[0] === 'text/html') ?? false\n if (request.method === 'GET' && acceptsHtml && !stockFrontend) {\n await this.proxyMobileIndex(request, response, authorization)\n return\n }\n if (stockFrontend && target.decodedPathname === '/') request.url = '/'\n await this.proxyHttp(request, response, authorization)\n }\n\n private async handleExtensionRequest(\n targetInfo: NonNullable<ReturnType<typeof extensionTarget>>,\n target: ReturnType<typeof parseRequestTarget>,\n request: IncomingMessage,\n response: ServerResponse,\n authorization: SessionAuthorization,\n ): Promise<void> {\n const extensions = this.extensions\n if (extensions === undefined) throw new HttpError(404, 'not_found')\n if (targetInfo.kind === 'events') {\n if (request.method !== 'GET' || target.search !== '') throw new HttpError(request.method === 'GET' ? 400 : 405, request.method === 'GET' ? 'bad_request' : 'method_not_allowed')\n this.openExtensionEventStream(request, response, authorization)\n return\n }\n if (targetInfo.kind === 'manifest') {\n if (request.method !== 'GET' && request.method !== 'HEAD') throw new HttpError(405, 'method_not_allowed')\n const operation = this.allocateRequest(authorization, response, {})\n try {\n operation.signal.throwIfAborted()\n const customRevision = async (file: string, fallback: string): Promise<string> => {\n let source: Buffer\n try {\n source = await readFile(file, { signal: operation.signal })\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n source = Buffer.from(fallback)\n }\n if (source.byteLength > 256 * 1024) throw new HttpError(413, 'payload_too_large')\n return createHash('sha256').update(source).digest('hex')\n }\n const [scriptRevision, styleRevision] = await Promise.all([\n customRevision(this.config.customScriptFile, CUSTOM_SCRIPT_FALLBACK),\n customRevision(this.config.customCssFile, CUSTOM_STYLE_FALLBACK),\n ])\n const body = Buffer.from(JSON.stringify({\n protocol: 1,\n extensions: extensions.manifest(),\n legacy: { scriptRevision, styleRevision },\n }))\n // The ETag must cover extension content, not just the manifest body, so\n // editing mobile.js/css alone invalidates the client's cached manifest.\n const etag = createHash('sha256').update(body).update(extensions.contentDigest()).digest('hex')\n if (headerValue(request.headers, 'if-none-match') === etag) {\n setSecurityHeaders(response, this.tlsEnabled); response.writeHead(304); response.end(); return\n }\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Content-Length': body.byteLength, ETag: etag })\n if (request.method === 'HEAD') response.end(); else response.end(body)\n return\n } finally {\n operation.release()\n }\n }\n if (targetInfo.kind === 'script' || targetInfo.kind === 'style' || targetInfo.kind === 'asset') {\n if (request.method !== 'GET' && request.method !== 'HEAD') throw new HttpError(405, 'method_not_allowed')\n const generation = extensionGeneration(new URLSearchParams(target.search).get('generation') ?? undefined)\n const operation = this.allocateRequest(authorization, response, {})\n try {\n const file = targetInfo.kind === 'script'\n ? await extensions.readClientFile(targetInfo.id, 'script', operation.signal, generation)\n : targetInfo.kind === 'style'\n ? await extensions.readClientFile(targetInfo.id, 'style', operation.signal, generation)\n : await extensions.readAsset(targetInfo.id, targetInfo.path ?? '', operation.signal, generation)\n if (headerValue(request.headers, 'if-none-match') === file.digest) {\n setSecurityHeaders(response, this.tlsEnabled); response.writeHead(304); response.end(); return\n }\n const contentType = targetInfo.kind === 'script'\n ? 'text/javascript; charset=utf-8'\n : targetInfo.kind === 'style' ? 'text/css; charset=utf-8' : extensionContentType(targetInfo.path ?? '')\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, { 'Content-Type': contentType, 'Content-Length': file.body.byteLength, ETag: file.digest })\n if (request.method === 'HEAD') response.end(); else response.end(file.body)\n return\n } finally {\n operation.release()\n }\n }\n if (targetInfo.kind === 'action') {\n if (request.method !== 'POST') throw new HttpError(405, 'method_not_allowed')\n const maximum = 1024 * 1024\n assertBoundedContentLength(request, maximum)\n const generation = extensionGeneration(headerValue(request.headers, EXTENSION_GENERATION_HEADER))\n const operation = this.allocateRequest(authorization, response, {})\n const abort = new AbortController()\n response.once('close', () => { abort.abort() })\n const generationSignal = extensions.signal(targetInfo.id, generation)\n const onGenerationAbort = (): void => { abort.abort(); if (!response.destroyed) response.destroy() }\n generationSignal?.addEventListener('abort', onGenerationAbort, { once: true })\n try {\n const body = await readJsonObject(request, maximum)\n const result = await extensions.invoke(targetInfo.id, targetInfo.action, body, { signal: abort.signal, deviceId: authorization.deviceId }, generation)\n let serialized: Buffer\n try { serialized = Buffer.from(JSON.stringify(result)) } catch { throw new MobileExtensionError('extension_failed', 'extension action failed', 500) }\n if (serialized.byteLength > 4 * 1024 * 1024) throw new MobileExtensionError('extension_result_too_large', 'extension result is too large', 500)\n sendJson(response, 200, result, this.tlsEnabled)\n } finally {\n generationSignal?.removeEventListener('abort', onGenerationAbort)\n abort.abort(); operation.release()\n }\n return\n }\n if (targetInfo.kind === 'route') {\n const method = request.method ?? 'GET'\n if (!['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) throw new HttpError(405, 'method_not_allowed')\n const hasBody = method !== 'GET' && method !== 'HEAD'\n if (hasBody) assertBoundedContentLength(request, this.config.maxBodyBytes)\n const generation = extensionGeneration(headerValue(request.headers, EXTENSION_GENERATION_HEADER))\n const operation = this.allocateRequest(authorization, response, {})\n const abort = new AbortController()\n response.once('close', () => { abort.abort() })\n const generationSignal = extensions.signal(targetInfo.id, generation)\n const onGenerationAbort = (): void => { abort.abort(); if (!response.destroyed) response.destroy() }\n generationSignal?.addEventListener('abort', onGenerationAbort, { once: true })\n try {\n const body = hasBody ? await readBoundedBody(request, this.config.maxBodyBytes) : Buffer.alloc(0)\n const parsed = new URL(target.raw, this.address().origin)\n const routeRequest: MobileRouteRequest = {\n method, pathname: targetInfo.path, query: parsed.searchParams,\n headers: extensionRequestHeaders(request.headers), body, signal: abort.signal, deviceId: authorization.deviceId,\n }\n const result = await extensions.route(targetInfo.id, method, targetInfo.path, routeRequest, generation)\n await this.sendExtensionResponse(response, result, request.method === 'HEAD')\n } finally {\n generationSignal?.removeEventListener('abort', onGenerationAbort)\n abort.abort(); operation.release()\n }\n }\n }\n\n private async sendExtensionResponse(response: ServerResponse, result: MobileRouteResponse, head: boolean): Promise<void> {\n const status = result.status ?? 200\n if (!Number.isSafeInteger(status) || status < 200 || status > 599) {\n throw new MobileExtensionError('invalid_route_response', 'extension returned an invalid HTTP status', 500)\n }\n const contentType = result.contentType ?? 'application/octet-stream'\n if (contentType.length > 1024\n || !/^[\\x20-\\x7e]+$/u.test(contentType)\n || !/^[\\w!#$&+.^-]+\\/[\\w!#$&+.^-]+(?:;[\\x20-\\x7e]*)?$/u.test(contentType)) {\n throw new MobileExtensionError('invalid_route_response', 'extension returned an invalid content type', 500)\n }\n const safeHeaders: Record<string, string> = {}\n for (const [name, value] of Object.entries(result.headers ?? {})) {\n if (!/^(?:content-disposition|cache-control|etag)$/iu.test(name) || /[\\r\\n]/u.test(value)) continue\n safeHeaders[name] = value\n }\n setSecurityHeaders(response, this.tlsEnabled)\n if (typeof result.body === 'string' || result.body instanceof Uint8Array) {\n const body = typeof result.body === 'string' ? Buffer.from(result.body) : Buffer.from(result.body)\n if (body.byteLength > 4 * 1024 * 1024) throw new MobileExtensionError('extension_result_too_large', 'extension response is too large', 500)\n response.writeHead(status, { ...safeHeaders, 'Content-Type': contentType, 'Content-Length': body.byteLength })\n if (head) response.end(); else response.end(body)\n return\n }\n response.writeHead(status, { ...safeHeaders, 'Content-Type': contentType })\n if (head) { result.body.destroy(); response.end(); return }\n await pipeline(result.body, new ByteLimitTransform(4 * 1024 * 1024), response)\n }\n\n /** Exchange DSH's process-local launch token for an authority-bound cookie kept inside this gateway. */\n private async upstreamCookieHeader(): Promise<string | undefined> {\n if (this.upstreamAuthenticatedUrl === undefined) return undefined\n if (this.upstreamCookie !== undefined\n && this.upstreamCookieExpiresAt > Date.now() + UPSTREAM_AUTH_REFRESH_MARGIN_MS) {\n return this.upstreamCookie\n }\n if (this.upstreamCookieTask !== undefined) return this.upstreamCookieTask\n const task = this.exchangeUpstreamCookie()\n this.upstreamCookieTask = task\n try {\n return await task\n } finally {\n if (this.upstreamCookieTask === task) this.upstreamCookieTask = undefined\n }\n }\n\n private async exchangeUpstreamCookie(): Promise<string> {\n const authenticatedUrl = this.upstreamAuthenticatedUrl\n if (authenticatedUrl === undefined) throw new HttpError(502, 'upstream_unavailable')\n let target: URL\n try {\n target = new URL(authenticatedUrl)\n } catch {\n throw new HttpError(502, 'upstream_unavailable')\n }\n if (target.origin !== this.config.upstreamOrigin.origin || target.pathname !== '/'\n || target.hash !== '' || target.search === '') {\n throw new HttpError(502, 'upstream_unavailable')\n }\n try {\n const proxied = await new Promise<IncomingMessage>((resolve, reject) => {\n const upstreamRequest = requestHttp({\n protocol: 'http:',\n hostname: stripIpv6Brackets(this.config.upstreamOrigin.hostname),\n port: Number(this.config.upstreamOrigin.port),\n method: 'GET',\n path: `${target.pathname}${target.search}`,\n headers: {\n host: this.config.upstreamOrigin.host,\n accept: 'text/html',\n 'accept-encoding': 'identity',\n },\n agent: false,\n })\n this.upstreamAuthRequest = upstreamRequest\n upstreamRequest.setTimeout(this.config.upstreamTimeoutMs, () => {\n upstreamRequest.destroy(new Error('upstream timeout'))\n })\n upstreamRequest.once('response', resolve)\n upstreamRequest.once('error', reject)\n upstreamRequest.end()\n })\n await new Promise<void>((resolve, reject) => {\n proxied.once('end', resolve)\n proxied.once('error', reject)\n proxied.resume()\n })\n const setCookie = proxied.headers['set-cookie']?.[0]\n const pair = setCookie?.split(';', 1)[0]\n const maxAgeText = setCookie === undefined\n ? undefined\n : /(?:^|;\\s*)Max-Age=(\\d+)(?:;|$)/iu.exec(setCookie)?.[1]\n const maxAgeSeconds = maxAgeText === undefined ? Number.NaN : Number(maxAgeText)\n const expiresAt = Date.now() + maxAgeSeconds * 1000\n if (proxied.statusCode !== 303 || pair === undefined || pair.length > 4096\n || !UPSTREAM_COOKIE_PAIR.test(pair) || !Number.isSafeInteger(expiresAt)\n || maxAgeSeconds <= 0) {\n throw new HttpError(502, 'upstream_unavailable')\n }\n this.upstreamCookie = pair\n this.upstreamCookieExpiresAt = expiresAt\n return pair\n } catch (error) {\n if (error instanceof HttpError) throw error\n throw new HttpError(502, 'upstream_unavailable')\n } finally {\n this.upstreamAuthRequest?.destroy()\n this.upstreamAuthRequest = undefined\n }\n }\n\n private async proxyMobileIndex(\n request: IncomingMessage,\n response: ServerResponse,\n authorization: SessionAuthorization,\n ): Promise<void> {\n const holder: { request?: ClientRequest } = {}\n const operation = this.allocateRequest(authorization, response, holder)\n try {\n const upstreamHeaders = sanitizeRequestHeaders(request, this.config.upstreamOrigin)\n const upstreamCookie = await this.upstreamCookieHeader()\n if (upstreamCookie !== undefined) upstreamHeaders.cookie = upstreamCookie\n upstreamHeaders['accept-encoding'] = 'identity'\n const proxied = await new Promise<IncomingMessage>((resolve, reject) => {\n const upstreamRequest = requestHttp({\n protocol: 'http:',\n hostname: stripIpv6Brackets(this.config.upstreamOrigin.hostname),\n port: Number(this.config.upstreamOrigin.port),\n method: 'GET',\n path: '/',\n headers: upstreamHeaders,\n agent: false,\n })\n holder.request = upstreamRequest\n upstreamRequest.setTimeout(this.config.upstreamTimeoutMs, () => {\n upstreamRequest.destroy(new Error('upstream timeout'))\n })\n upstreamRequest.once('response', resolve)\n upstreamRequest.once('error', reject)\n upstreamRequest.end()\n })\n if ((proxied.statusCode ?? 502) !== 200) throw new HttpError(502, 'upstream_unavailable')\n const chunks: Buffer[] = []\n let bytes = 0\n for await (const chunk of proxied) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n bytes += buffer.byteLength\n if (bytes > 4 * 1024 * 1024) throw new HttpError(502, 'upstream_unavailable')\n chunks.push(buffer)\n }\n let body: Buffer\n try {\n const rewritten = rewriteMobileIndexWithBatch(Buffer.concat(chunks).toString('utf8'))\n if (rewritten.batch !== undefined) this.rememberMobileBootBatch(rewritten.batch)\n body = Buffer.from(rewritten.html)\n } catch {\n throw new HttpError(502, 'upstream_unavailable')\n }\n const headers = sanitizeResponseHeaders(proxied.headers, this.config.upstreamOrigin)\n delete headers['content-length']\n delete headers['content-encoding']\n delete headers.etag\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, {\n ...headers,\n 'Content-Type': 'text/html; charset=utf-8',\n 'Content-Length': body.byteLength,\n })\n response.end(body)\n } catch (error) {\n holder.request?.destroy()\n if (error instanceof HttpError) throw error\n if (response.headersSent) response.destroy()\n else throw new HttpError(502, 'upstream_unavailable')\n } finally {\n operation.release()\n }\n }\n\n private rememberMobileBootBatch(plan: MobileBootBatchPlan): void {\n const existing = this.mobileBootBatches.get(plan.key)\n this.mobileBootBatches.delete(plan.key)\n this.mobileBootBatches.set(plan.key, existing ?? { plan })\n while (this.mobileBootBatches.size > MAX_MOBILE_BOOT_BATCHES) {\n const oldest = this.mobileBootBatches.keys().next().value as string | undefined\n if (oldest === undefined) break\n this.mobileBootBatches.delete(oldest)\n }\n }\n\n private async serveMobileBootBatch(\n key: string,\n request: IncomingMessage,\n response: ServerResponse,\n authorization: SessionAuthorization,\n ): Promise<void> {\n if (request.method !== 'GET' && request.method !== 'HEAD') throw new HttpError(405, 'method_not_allowed')\n const stored = this.mobileBootBatches.get(key)\n if (stored === undefined) throw new HttpError(404, 'not_found')\n const operation = this.allocateRequest(authorization, response, {})\n try {\n const layoutStat = await stat(this.config.mobileLayoutFile)\n if (stored.body === undefined || stored.etag === undefined || stored.layoutMtimeMs !== layoutStat.mtimeMs) {\n const body = await this.assembleMobileBootBatch(stored.plan, operation.signal)\n stored.body = body\n delete stored.gzipBody\n stored.etag = createHash('sha256').update(body).digest('hex')\n stored.layoutMtimeMs = layoutStat.mtimeMs\n }\n const compressed = acceptsGzip(request.headers['accept-encoding'])\n const body = compressed\n ? stored.gzipBody ??= await gzipBuffer(stored.body)\n : stored.body\n const etag = compressed ? `${stored.etag}-gzip` : stored.etag\n const headers: OutgoingHttpHeaders = {\n 'Content-Type': 'text/javascript; charset=utf-8',\n 'Content-Length': body.byteLength,\n 'Cache-Control': 'private, no-cache',\n ETag: etag,\n }\n if (compressed) headers['Content-Encoding'] = 'gzip'\n addVaryAcceptEncoding(headers)\n if (headerValue(request.headers, 'if-none-match') === etag) {\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(304, { ETag: etag, 'Cache-Control': 'private, no-cache', Vary: String(headers.vary) })\n response.end()\n return\n }\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, headers)\n if (request.method === 'HEAD') response.end()\n else response.end(body)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') throw new HttpError(503, 'mobile_frontend_unavailable')\n throw error\n } finally {\n operation.release()\n }\n }\n\n private async assembleMobileBootBatch(plan: MobileBootBatchPlan, signal: AbortSignal): Promise<Buffer> {\n const bodies = new Array<Buffer>(plan.entries.length)\n let cursor = 0\n const worker = async (): Promise<void> => {\n while (cursor < plan.entries.length) {\n const index = cursor++\n const entry = plan.entries[index]!\n bodies[index] = entry.id === MOBILE_LAYOUT_MODULE\n ? await readFile(this.config.mobileLayoutFile, { signal })\n : await this.readUpstreamClientBundle(entry.url, signal)\n if (bodies[index]!.byteLength > MAX_MOBILE_BOOT_ENTRY_BYTES) throw new HttpError(502, 'upstream_unavailable')\n }\n }\n await Promise.all(Array.from({ length: Math.min(8, plan.entries.length) }, worker))\n const total = bodies.reduce((bytes, body) => bytes + body.byteLength + 2, 0)\n if (total > MAX_MOBILE_BOOT_BATCH_BYTES) throw new HttpError(502, 'upstream_unavailable')\n return Buffer.concat(bodies.flatMap(body => [body, Buffer.from('\\n;\\n')]))\n }\n\n private async readUpstreamClientBundle(source: string, signal: AbortSignal): Promise<Buffer> {\n if (!source.startsWith('/plugins/') || source.includes('#')) throw new HttpError(502, 'upstream_unavailable')\n const target = new URL(source, this.config.upstreamOrigin)\n if (target.origin !== this.config.upstreamOrigin.origin) throw new HttpError(502, 'upstream_unavailable')\n let upstreamRequest: ClientRequest | undefined\n const aborted = (): void => { upstreamRequest?.destroy(new Error('request aborted')) }\n signal.addEventListener('abort', aborted, { once: true })\n try {\n const upstreamCookie = await this.upstreamCookieHeader()\n const proxied = await new Promise<IncomingMessage>((resolve, reject) => {\n upstreamRequest = requestHttp({\n protocol: 'http:',\n hostname: stripIpv6Brackets(this.config.upstreamOrigin.hostname),\n port: Number(this.config.upstreamOrigin.port),\n method: 'GET',\n path: `${target.pathname}${target.search}`,\n headers: {\n host: this.config.upstreamOrigin.host,\n accept: 'text/javascript',\n 'accept-encoding': 'identity',\n ...(upstreamCookie === undefined ? {} : { cookie: upstreamCookie }),\n },\n agent: false,\n })\n upstreamRequest.setTimeout(this.config.upstreamTimeoutMs, () => {\n upstreamRequest?.destroy(new Error('upstream timeout'))\n })\n upstreamRequest.once('response', resolve)\n upstreamRequest.once('error', reject)\n upstreamRequest.end()\n })\n if ((proxied.statusCode ?? 502) !== 200) throw new HttpError(502, 'upstream_unavailable')\n const chunks: Buffer[] = []\n let bytes = 0\n for await (const chunk of proxied) {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n bytes += buffer.byteLength\n if (bytes > MAX_MOBILE_BOOT_ENTRY_BYTES) throw new HttpError(502, 'upstream_unavailable')\n chunks.push(buffer)\n }\n return Buffer.concat(chunks)\n } catch (error) {\n if (error instanceof HttpError) throw error\n throw new HttpError(502, 'upstream_unavailable')\n } finally {\n signal.removeEventListener('abort', aborted)\n upstreamRequest?.destroy()\n }\n }\n\n private allocateRequest(\n authorization: SessionAuthorization,\n response: ServerResponse,\n upstream: { request?: ClientRequest },\n ): { id: number; signal: AbortSignal; release: () => void } {\n if (this.activeRequests.size >= this.config.maxActiveRequests) throw new HttpError(429, 'busy')\n const id = this.nextOperationId++\n const controller = new AbortController()\n const abort = (): void => {\n controller.abort()\n upstream.request?.destroy()\n if (!response.destroyed) response.destroy()\n }\n const timer = setTimeout(abort, Math.max(1, authorization.expiresAt - Date.now()))\n timer.unref()\n this.activeRequests.set(id, Object.freeze({ ...authorization, abort, timer }))\n return {\n id,\n signal: controller.signal,\n release: () => {\n const entry = this.activeRequests.get(id)\n if (entry !== undefined) clearTimeout(entry.timer)\n this.activeRequests.delete(id)\n },\n }\n }\n\n private async proxyHttp(\n request: IncomingMessage,\n response: ServerResponse,\n authorization: SessionAuthorization,\n ): Promise<void> {\n const declared = request.headers['content-length']\n if (declared !== undefined && (!/^\\d+$/u.test(declared) || Number(declared) > this.config.maxBodyBytes)) {\n throw new HttpError(413, 'payload_too_large')\n }\n const holder: { request?: ClientRequest } = {}\n const operation = this.allocateRequest(authorization, response, holder)\n let bodyDone: Promise<void> | undefined\n try {\n const bufferedBody = request.method === 'POST' && request.url?.split('?', 1)[0] === SESSION_HISTORY_PATH\n ? mobileHistoryRequestBody(request, await readBoundedBody(request, this.config.maxBodyBytes))\n : undefined\n const upstreamHeaders = sanitizeRequestHeaders(request, this.config.upstreamOrigin)\n const upstreamCookie = await this.upstreamCookieHeader()\n if (upstreamCookie !== undefined) upstreamHeaders.cookie = upstreamCookie\n if (bufferedBody !== undefined) upstreamHeaders['content-length'] = String(bufferedBody.byteLength)\n const upstreamResponse = new Promise<IncomingMessage>((resolve, reject) => {\n const upstreamRequest = requestHttp({\n protocol: 'http:',\n hostname: stripIpv6Brackets(this.config.upstreamOrigin.hostname),\n port: Number(this.config.upstreamOrigin.port),\n method: request.method,\n path: request.url,\n headers: upstreamHeaders,\n agent: false,\n })\n holder.request = upstreamRequest\n upstreamRequest.setTimeout(this.config.upstreamTimeoutMs, () => {\n upstreamRequest.destroy(new Error('upstream timeout'))\n })\n upstreamRequest.once('response', resolve)\n upstreamRequest.once('error', reject)\n if (bufferedBody === undefined) {\n bodyDone = pipeline(request, new ByteLimitTransform(this.config.maxBodyBytes), upstreamRequest)\n } else {\n upstreamRequest.end(bufferedBody)\n bodyDone = Promise.resolve()\n }\n void bodyDone.catch(reject)\n })\n const proxied = await upstreamResponse\n setSecurityHeaders(response, this.tlsEnabled)\n const headers = sanitizeResponseHeaders(proxied.headers, this.config.upstreamOrigin)\n const cacheControl = revisionedStaticCacheControl(request)\n if (cacheControl !== undefined) headers['cache-control'] = cacheControl\n const compressed = shouldCompressResponse(request, proxied)\n if (compressed) {\n delete headers['accept-ranges']\n delete headers['content-length']\n delete headers.etag\n headers['content-encoding'] = 'gzip'\n addVaryAcceptEncoding(headers)\n }\n response.writeHead(proxied.statusCode ?? 502, headers)\n await Promise.all([\n bodyDone,\n compressed ? pipeline(proxied, createGzip(), response) : pipeline(proxied, response),\n ])\n } catch (error) {\n holder.request?.destroy()\n await bodyDone?.catch(() => undefined)\n if (error instanceof HttpError) throw error\n if (response.headersSent) response.destroy()\n else throw new HttpError(502, 'upstream_unavailable')\n } finally {\n operation.release()\n }\n }\n\n private abortSessionResources(sessionKey: string): void {\n for (const request of this.activeRequests.values()) {\n if (request.sessionKey === sessionKey) request.abort()\n }\n for (const socket of this.activeWebSockets.values()) {\n if (socket.sessionKey === sessionKey) {\n socket.client.destroy()\n socket.upstream.destroy()\n }\n }\n }\n\n private broadcastExtensionChange(): void {\n if (this.closing) return\n this.extensionEventRevision += 1\n for (const listener of this.extensionEventListeners) listener(this.extensionEventRevision)\n }\n\n private pollLegacyCustomChanges(): Promise<void> {\n if (this.extensionChangeTask !== undefined) return this.extensionChangeTask\n const digestFile = async (path: string, fallback: string): Promise<string> => {\n try {\n const info = await stat(path)\n if (!info.isFile() || info.size > 256 * 1024) return `invalid:${String(info.size)}:${String(info.mtimeMs)}`\n return createHash('sha256').update(await readFile(path)).digest('hex')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return createHash('sha256').update(fallback).digest('hex')\n return `error:${String((error as NodeJS.ErrnoException).code ?? 'unknown')}`\n }\n }\n const task = Promise.all([\n digestFile(this.config.customScriptFile, CUSTOM_SCRIPT_FALLBACK),\n digestFile(this.config.customCssFile, CUSTOM_STYLE_FALLBACK),\n ]).then(parts => {\n const next = createHash('sha256').update(parts.join('|')).digest('hex')\n if (this.legacyCustomDigest !== '' && next !== this.legacyCustomDigest) this.broadcastExtensionChange()\n this.legacyCustomDigest = next\n }).finally(() => {\n if (this.extensionChangeTask === task) this.extensionChangeTask = undefined\n })\n this.extensionChangeTask = task\n return task\n }\n\n private openExtensionEventStream(\n request: IncomingMessage,\n response: ServerResponse,\n authorization: SessionAuthorization,\n ): void {\n const operation = this.allocateRequest(authorization, response, {})\n let closed = false\n let heartbeat: NodeJS.Timeout | undefined\n const close = (): void => {\n if (closed) return\n closed = true\n if (heartbeat !== undefined) clearInterval(heartbeat)\n this.extensionEventListeners.delete(send)\n request.removeListener('aborted', close)\n response.removeListener('close', close)\n operation.release()\n }\n const send = (revision: number): void => {\n if (closed || response.destroyed || response.writableEnded) return\n response.write(`id: ${String(revision)}\\nevent: extensions-changed\\ndata: {\\\"revision\\\":${String(revision)}}\\n\\n`)\n }\n setSecurityHeaders(response, this.tlsEnabled)\n response.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-store',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n })\n response.write('retry: 2000\\n: ready\\n\\n')\n this.extensionEventListeners.add(send)\n heartbeat = setInterval(() => {\n if (!closed && !response.destroyed && !response.writableEnded) response.write(': heartbeat\\n\\n')\n }, EXTENSION_EVENT_HEARTBEAT_MS)\n heartbeat.unref()\n request.once('aborted', close)\n response.once('close', close)\n }\n\n private async readUpgradeResponse(upstream: Socket, expectedAccept: string): Promise<{ header: string; remainder: Buffer }> {\n return new Promise((resolve, reject) => {\n let buffer = Buffer.alloc(0)\n const failed = (error: Error): void => { cleanup(); reject(error) }\n const closed = (): void => { cleanup(); reject(new Error('upstream closed during WebSocket handshake')) }\n const data = (chunk: Buffer): void => {\n buffer = Buffer.concat([buffer, chunk])\n if (buffer.length > MAX_HEADER_BYTES) {\n failed(new Error('upstream WebSocket headers are too large'))\n return\n }\n const end = buffer.indexOf('\\r\\n\\r\\n')\n if (end < 0) return\n cleanup()\n const lines = buffer.subarray(0, end).toString('latin1').split('\\r\\n')\n if (lines.shift() !== 'HTTP/1.1 101 Switching Protocols') {\n reject(new Error('upstream refused WebSocket upgrade'))\n return\n }\n const selected = new Map<string, string>()\n for (const line of lines) {\n const colon = line.indexOf(':')\n if (colon <= 0) {\n reject(new Error('upstream returned malformed WebSocket headers'))\n return\n }\n const name = line.slice(0, colon).trim().toLowerCase()\n const value = line.slice(colon + 1).trim()\n if (selected.has(name)) {\n reject(new Error('upstream returned duplicate WebSocket headers'))\n return\n }\n selected.set(name, value)\n }\n if (selected.get('upgrade')?.toLowerCase() !== 'websocket'\n || !hasToken(selected.get('connection'), 'upgrade')\n || selected.get('sec-websocket-accept') !== expectedAccept) {\n reject(new Error('upstream returned an invalid WebSocket handshake'))\n return\n }\n const output = [\n 'HTTP/1.1 101 Switching Protocols',\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Accept: ${expectedAccept}`,\n ]\n const protocol = selected.get('sec-websocket-protocol')\n const extensions = selected.get('sec-websocket-extensions')\n if (protocol !== undefined) output.push(`Sec-WebSocket-Protocol: ${protocol}`)\n if (extensions !== undefined) output.push(`Sec-WebSocket-Extensions: ${extensions}`)\n output.push('Referrer-Policy: no-referrer', 'X-Content-Type-Options: nosniff', '', '')\n resolve({ header: output.join('\\r\\n'), remainder: buffer.subarray(end + 4) })\n }\n const cleanup = (): void => {\n upstream.off('data', data)\n upstream.off('error', failed)\n upstream.off('close', closed)\n }\n upstream.on('data', data)\n upstream.once('error', failed)\n upstream.once('close', closed)\n })\n }\n\n private async handleUpgrade(request: IncomingMessage, client: Socket, head: Buffer): Promise<void> {\n const target = parseRequestTarget(request.url)\n const policy = this.requirePolicy()\n // Android WebView WebSockets do not consistently carry Fetch Metadata.\n // Exact Origin, direct CIDR, exact Host, and the short Session Cookie\n // remain mandatory; when Sec-Fetch-Site is present, assertExternalTrust\n // still requires it to be same-origin.\n assertExternalTrust(request, policy, false)\n if (!policy.acceptsOrigin(request.headers.origin)) throw new HttpError(403, 'forbidden')\n if (target.search !== '' || !WS_PATHS.has(target.decodedPathname)) throw new HttpError(404, 'not_found')\n if (request.method !== 'GET' || headerValue(request.headers, 'upgrade')?.toLowerCase() !== 'websocket'\n || !hasToken(headerValue(request.headers, 'connection'), 'upgrade')) {\n throw new HttpError(400, 'bad_request')\n }\n const key = headerValue(request.headers, 'sec-websocket-key')\n if (key === undefined || headerValue(request.headers, 'sec-websocket-version') !== '13') {\n throw new HttpError(400, 'bad_request')\n }\n let decodedKey: Buffer\n try {\n decodedKey = Buffer.from(key, 'base64')\n } catch {\n throw new HttpError(400, 'bad_request')\n }\n if (decodedKey.length !== 16 || decodedKey.toString('base64') !== key) throw new HttpError(400, 'bad_request')\n const authorization = this.authorize(request)\n if (this.activeWebSockets.size >= this.config.maxWebSockets) throw new HttpError(429, 'busy')\n const upstreamCookie = await this.upstreamCookieHeader()\n\n const upstream = connect({\n host: stripIpv6Brackets(this.config.upstreamOrigin.hostname),\n port: Number(this.config.upstreamOrigin.port),\n })\n client.pause()\n const id = this.nextOperationId++\n const closeBoth = (): void => {\n client.destroy()\n upstream.destroy()\n }\n client.on('error', closeBoth)\n upstream.on('error', closeBoth)\n const timer = setTimeout(closeBoth, Math.max(1, authorization.expiresAt - Date.now()))\n timer.unref()\n const record: ActiveWebSocket = Object.freeze({ ...authorization, client, upstream, timer })\n this.activeWebSockets.set(id, record)\n const cleanup = (): void => {\n const active = this.activeWebSockets.get(id)\n if (active !== undefined) clearTimeout(active.timer)\n this.activeWebSockets.delete(id)\n }\n client.once('close', () => { upstream.destroy(); cleanup() })\n upstream.once('close', () => { client.destroy(); cleanup() })\n upstream.setTimeout(this.config.upstreamTimeoutMs, closeBoth)\n try {\n await new Promise<void>((resolve, reject) => {\n const connected = (): void => {\n upstream.off('error', failed)\n resolve()\n }\n const failed = (error: Error): void => {\n upstream.off('connect', connected)\n reject(error)\n }\n upstream.once('connect', connected)\n upstream.once('error', failed)\n })\n const requestLines = [\n `GET ${target.raw} HTTP/1.1`,\n `Host: ${this.config.upstreamOrigin.host}`,\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Origin: ${this.config.upstreamOrigin.origin}`,\n 'Sec-Fetch-Site: same-origin',\n `Sec-WebSocket-Key: ${key}`,\n 'Sec-WebSocket-Version: 13',\n ]\n if (upstreamCookie !== undefined) requestLines.push(`Cookie: ${upstreamCookie}`)\n const protocol = headerValue(request.headers, 'sec-websocket-protocol')\n const extensions = headerValue(request.headers, 'sec-websocket-extensions')\n if (protocol !== undefined) requestLines.push(`Sec-WebSocket-Protocol: ${protocol}`)\n if (extensions !== undefined) requestLines.push(`Sec-WebSocket-Extensions: ${extensions}`)\n requestLines.push('', '')\n upstream.write(requestLines.join('\\r\\n'))\n if (head.length > 0) upstream.write(head)\n const handshake = await this.readUpgradeResponse(upstream, websocketAccept(key))\n upstream.setTimeout(0)\n client.write(handshake.header)\n if (handshake.remainder.length > 0) client.write(handshake.remainder)\n upstream.pipe(client)\n client.pipe(upstream)\n client.resume()\n } catch (error) {\n closeBoth()\n if (error instanceof HttpError) throw error\n throw new HttpError(502, 'upstream_unavailable')\n }\n }\n\n /** Loopback-only DSH WebServer route for opening pairing and managing devices. */\n localAdminRoute(prefix: string = LOCAL_ADMIN_PREFIX): WebRoute {\n return {\n kind: 'prefix',\n path: prefix,\n handler: async (request, response) => {\n try {\n const target = parseRequestTarget(request.url)\n const mutation = request.method === 'POST'\n assertLocalAdminTrust(request, mutation)\n if (target.search !== '') throw new HttpError(400, 'bad_request')\n if (request.method === 'GET' && target.decodedPathname === `${prefix}/status`) {\n sendJson(response, 200, {\n gateway: this.address(),\n pairing: this.access.pairingStatus(),\n deviceCount: this.access.listDevices().length,\n resources: {\n connections: this.connectedSockets.size,\n activeRequests: this.activeRequests.size,\n webSockets: this.activeWebSockets.size,\n },\n }, false)\n return\n }\n if (request.method === 'GET' && target.decodedPathname === `${prefix}/devices`) {\n sendJson(response, 200, { devices: this.access.listDevices() }, false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${prefix}/pairing/open`) {\n const body = await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n if (body.ttlMs !== undefined && typeof body.ttlMs !== 'number') throw new HttpError(400, 'bad_request')\n const opened = await this.access.openPairing(body.ttlMs as number | undefined)\n const pairUrl = `${this.address().origin}/mobile-access/pair#instance=${this.config.instanceId}&token=${opened.token}`\n const appPairUrl = pairUrl\n // The QR code is an enhancement; a failed render must not waste an opened window.\n let qrSvg = ''\n try {\n qrSvg = await QRCode.toString(appPairUrl, { type: 'svg', margin: 1 })\n } catch {\n // keep qrSvg empty\n }\n sendJson(response, 201, {\n ...opened,\n appKey: `dsh1.${this.config.instanceId}.${opened.token}`,\n pairUrl,\n appPairUrl,\n qrSvg,\n }, false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${prefix}/devices/revoke`) {\n const body = await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n if (typeof body.deviceId !== 'string' || !/^[a-f\\d]{32}$/u.test(body.deviceId)) {\n throw new HttpError(400, 'bad_request')\n }\n const revoked = await this.access.revokeDevice(body.deviceId)\n if (!revoked) throw new HttpError(404, 'not_found')\n sendJson(response, 200, { revoked: true }, false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${prefix}/devices/reset`) {\n const body = await readJsonObject(request, MAX_CONTROL_BODY_BYTES)\n if (body.confirm !== true) throw new HttpError(400, 'bad_request')\n await this.access.resetDevices()\n sendJson(response, 200, { reset: true }, false)\n return\n }\n throw new HttpError(404, 'not_found')\n } catch (error) {\n const mapped = mapError(error)\n if (response.headersSent) response.destroy()\n else sendFailure(response, mapped.status, mapped.code, false)\n }\n },\n }\n }\n\n /** Close listeners and abort all accepted work before resolving teardown. */\n async close(): Promise<void> {\n if (this.closeTask !== undefined) return this.closeTask\n this.closeTask = this.performClose()\n return this.closeTask\n }\n\n private async performClose(): Promise<void> {\n this.closing = true\n if (this.extensionChangeTimer !== undefined) clearInterval(this.extensionChangeTimer)\n this.extensionChangeTimer = undefined\n this.removeExtensionContentListener()\n this.upstreamAuthRequest?.destroy()\n this.upstreamAuthRequest = undefined\n this.removeSessionListener()\n const accessClose = this.access.close()\n for (const request of this.activeRequests.values()) request.abort()\n for (const websocket of this.activeWebSockets.values()) {\n websocket.client.destroy()\n websocket.upstream.destroy()\n }\n for (const socket of this.connectedSockets) socket.destroy()\n if (this.discoveryTimer !== undefined) clearInterval(this.discoveryTimer)\n this.discoveryTimer = undefined\n await this.closeBonjour()\n const discoverySocket = this.discoverySocket\n this.discoverySocket = undefined\n if (discoverySocket !== undefined) {\n await new Promise<void>(resolve => { discoverySocket.close(() => resolve()) })\n }\n const server = this.server\n this.server = undefined\n if (server !== undefined && server.listening) {\n server.closeAllConnections()\n await new Promise<void>(resolve => { server.close(() => resolve()) })\n }\n await accessClose\n this.activeRequests.clear()\n this.activeWebSockets.clear()\n this.connectedSockets.clear()\n this.policy = undefined\n this.listenerPort = undefined\n }\n\n /** Safe metadata helper for direct loopback integrations. */\n devices(): readonly DeviceSummary[] {\n return this.access.listDevices()\n }\n\n /** Status shown by the loopback mobile-access control card. */\n extensionStatus(): { readonly loaded: number; readonly failed: number } {\n return this.extensions?.status() ?? { loaded: 0, failed: 0 }\n }\n}\n","import { lstat, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join } from 'node:path'\nimport { randomBytes } from 'node:crypto'\nimport { restrictPrivateFile } from './private-file.js'\n\n/** Persistent record containing only a digest of the long-lived device credential. */\nexport interface StoredDevice {\n readonly id: string\n readonly label: string\n readonly tokenDigest: string\n readonly createdAt: number\n readonly expiresAt: number\n readonly lastSeenAt: number\n readonly revokedAt?: number\n}\n\n/** Versioned device state. Raw device and Session credentials are never members. */\nexport interface DeviceSnapshot {\n readonly version: 1\n readonly devices: readonly StoredDevice[]\n}\n\n/** Persistence seam for device-token digests and revocation metadata. */\nexport interface DeviceStore {\n load(): Promise<DeviceSnapshot>\n save(snapshot: DeviceSnapshot): Promise<void>\n}\n\nfunction assertInteger(value: unknown, name: string): asserts value is number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {\n throw new Error(`device state ${name} must be a non-negative integer`)\n }\n}\n\nfunction parseDevice(value: unknown): StoredDevice {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('device state contains an invalid device')\n const record = value as Record<string, unknown>\n if (typeof record.id !== 'string' || !/^[a-f\\d]{32}$/u.test(record.id)) throw new Error('device state contains an invalid id')\n if (typeof record.label !== 'string' || record.label.length < 1 || record.label.length > 64 || /[\\u0000-\\u001f\\u007f]/u.test(record.label)) {\n throw new Error('device state contains an invalid label')\n }\n if (typeof record.tokenDigest !== 'string' || !/^[a-f\\d]{64}$/u.test(record.tokenDigest)) {\n throw new Error('device state contains an invalid credential digest')\n }\n assertInteger(record.createdAt, 'createdAt')\n assertInteger(record.expiresAt, 'expiresAt')\n assertInteger(record.lastSeenAt, 'lastSeenAt')\n if (record.revokedAt !== undefined) assertInteger(record.revokedAt, 'revokedAt')\n if (record.expiresAt <= record.createdAt || record.lastSeenAt < record.createdAt) {\n throw new Error('device state contains inconsistent timestamps')\n }\n return Object.freeze({\n id: record.id,\n label: record.label,\n tokenDigest: record.tokenDigest,\n createdAt: record.createdAt,\n expiresAt: record.expiresAt,\n lastSeenAt: record.lastSeenAt,\n ...(record.revokedAt === undefined ? {} : { revokedAt: record.revokedAt }),\n })\n}\n\n/** Validate durable data before it can authorize a device. */\nexport function parseDeviceSnapshot(value: unknown, maximumDevices = 256): DeviceSnapshot {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('device state must be an object')\n const snapshot = value as Record<string, unknown>\n if (snapshot.version !== 1 || !Array.isArray(snapshot.devices) || snapshot.devices.length > maximumDevices) {\n throw new Error('device state has an unsupported version or device count')\n }\n const devices = snapshot.devices.map(parseDevice)\n if (new Set(devices.map(device => device.id)).size !== devices.length\n || new Set(devices.map(device => device.tokenDigest)).size !== devices.length) {\n throw new Error('device state contains duplicate device identities')\n }\n return Object.freeze({ version: 1, devices: Object.freeze(devices) })\n}\n\n/** Atomic JSON implementation with symlink refusal and owner-only file creation. */\nexport class JsonDeviceStore implements DeviceStore {\n constructor(private readonly file: string, private readonly maximumDevices = 256) {}\n\n async load(): Promise<DeviceSnapshot> {\n let stat\n try {\n stat = await lstat(this.file)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return Object.freeze({ version: 1, devices: Object.freeze([]) })\n throw error\n }\n if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024) {\n throw new Error('device state must be a regular file no larger than 1 MiB')\n }\n await restrictPrivateFile(this.file)\n let parsed: unknown\n try {\n parsed = JSON.parse(await readFile(this.file, 'utf8')) as unknown\n } catch (error) {\n throw new Error('device state is not valid JSON', { cause: error })\n }\n return parseDeviceSnapshot(parsed, this.maximumDevices)\n }\n\n async save(snapshot: DeviceSnapshot): Promise<void> {\n const validated = parseDeviceSnapshot(snapshot, this.maximumDevices)\n const directory = dirname(this.file)\n await mkdir(directory, { recursive: true, mode: 0o700 })\n try {\n const current = await lstat(this.file)\n if (!current.isFile() || current.isSymbolicLink()) throw new Error('device state target must remain a regular file')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n const temporary = join(directory, `.${basename(this.file)}.${randomBytes(12).toString('hex')}.tmp`)\n try {\n await writeFile(temporary, `${JSON.stringify(validated)}\\n`, { encoding: 'utf8', flag: 'wx', mode: 0o600 })\n await rename(temporary, this.file)\n await restrictPrivateFile(this.file)\n } catch (error) {\n try {\n await rm(temporary, { force: true })\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'device state write and temporary cleanup both failed')\n }\n throw error\n }\n }\n}\n\n/** In-memory store useful for embedding and deterministic tests. */\nexport class MemoryDeviceStore implements DeviceStore {\n private snapshot: DeviceSnapshot\n\n constructor(initial: DeviceSnapshot = { version: 1, devices: [] }) {\n this.snapshot = parseDeviceSnapshot(initial)\n }\n\n async load(): Promise<DeviceSnapshot> {\n return structuredClone(this.snapshot)\n }\n\n async save(snapshot: DeviceSnapshot): Promise<void> {\n this.snapshot = structuredClone(parseDeviceSnapshot(snapshot))\n }\n\n /** Return a defensive copy for assertions or administrative export. */\n inspect(): DeviceSnapshot {\n return structuredClone(this.snapshot)\n }\n}\n","import { createHash, randomBytes } from 'node:crypto'\nimport { execFile } from 'node:child_process'\nimport {\n chmod,\n copyFile,\n lstat,\n mkdir,\n mkdtemp,\n readFile,\n rename,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises'\nimport { basename, isAbsolute, join, relative, resolve } from 'node:path'\n\nconst FRP_VERSION = '0.70.1'\nconst MAX_ARCHIVE_ENTRIES = 128\nconst MAX_ARCHIVE_LIST_BYTES = 256 * 1024\n\ninterface FrpArtifact {\n readonly platform: NodeJS.Platform\n readonly arch: string\n readonly downloadUrl: string\n readonly downloadBytes: number\n readonly downloadSha256: string\n readonly archiveName: string\n readonly executableName: string\n}\n\nconst releases = [\n {\n platform: 'win32', arch: 'x64', archiveName: 'frp.zip', executableName: 'frpc.exe',\n downloadBytes: 13_924_309,\n downloadSha256: '531f3cd3cc41c0b4f077b54fe6b7dd83c0ff727e7f0bf412a4c78fa279165de5',\n downloadUrl: `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_windows_amd64.zip`,\n },\n {\n platform: 'win32', arch: 'arm64', archiveName: 'frp.zip', executableName: 'frpc.exe',\n downloadBytes: 12_204_751,\n downloadSha256: '74d3acaf0f03ee190dd0462f9b49861dca50b0559c5488af4b36572fc951fcca',\n downloadUrl: `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_windows_arm64.zip`,\n },\n {\n platform: 'linux', arch: 'x64', archiveName: 'frp.tar.gz', executableName: 'frpc',\n downloadBytes: 13_924_042,\n downloadSha256: '333da23d1b9009d7c01638e9ba38cf4600f7d37d393f854e96ee1396adefa9a6',\n downloadUrl: `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_amd64.tar.gz`,\n },\n {\n platform: 'linux', arch: 'arm64', archiveName: 'frp.tar.gz', executableName: 'frpc',\n downloadBytes: 12_371_290,\n downloadSha256: '3990f396a9a490ee7f0e5f355287750ed41520064ed999eab443b5e9a78d773d',\n downloadUrl: `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_arm64.tar.gz`,\n },\n {\n platform: 'darwin', arch: 'x64', archiveName: 'frp.tar.gz', executableName: 'frpc',\n downloadBytes: 13_951_979,\n downloadSha256: 'cbf69cf26e5553e914e97d37f5d4367fa30f5f531d073a889465af4719281e25',\n downloadUrl: `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_darwin_amd64.tar.gz`,\n },\n {\n platform: 'darwin', arch: 'arm64', archiveName: 'frp.tar.gz', executableName: 'frpc',\n downloadBytes: 12_670_664,\n downloadSha256: 'cfa733b5a261c1647edee3c1fc4133d2542989b28f5602e81d47fc821d25c55f',\n downloadUrl: `https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_darwin_arm64.tar.gz`,\n },\n] as const satisfies readonly FrpArtifact[]\n\n/** Pinned official FRP release metadata for supported desktop targets. */\nexport const FRP_COMPONENT_RELEASES: Readonly<Record<string, FrpArtifact>> = Object.freeze(Object.fromEntries(\n releases.map(release => [`${release.platform}-${release.arch}`, Object.freeze(release)]),\n))\n\n/** Public, credential-free description of the managed FRP client. */\nexport interface FrpComponentStatus {\n readonly supported: boolean\n readonly installed: boolean\n readonly version: string\n readonly downloadBytes: number\n readonly installedBytes: number\n readonly sourceUrl: string\n readonly releasePage: string\n readonly storagePath: string\n readonly errorCode?: string\n}\n\ninterface FrpComponentManagerOptions {\n readonly stateDirectory: string\n readonly platform?: NodeJS.Platform\n readonly arch?: string\n readonly fetchArtifact?: (artifact: FrpArtifact, signal: AbortSignal) => Promise<Uint8Array>\n readonly extractArtifact?: (archive: string, destination: string, executableName: string) => Promise<void>\n readonly inspectExecutable?: (executable: string) => Promise<string>\n}\n\nfunction inside(parent: string, child: string): boolean {\n const candidate = relative(parent, child)\n return candidate !== '' && !candidate.startsWith('..') && !isAbsolute(candidate)\n}\n\nasync function regularFile(file: string): Promise<boolean> {\n try {\n const entry = await lstat(file)\n return entry.isFile() && !entry.isSymbolicLink()\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false\n throw error\n }\n}\n\nasync function replaceDirectory(target: string, candidate: string): Promise<void> {\n const backup = `${target}.previous-${randomBytes(12).toString('hex')}`\n let previous = false\n try {\n try {\n await rename(target, backup)\n previous = true\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n try {\n await rename(candidate, target)\n } catch (error) {\n if (previous) {\n try { await rename(backup, target) } catch (restoreError) {\n throw new AggregateError([error, restoreError], 'frp_component_replace_failed')\n }\n }\n throw error\n }\n if (previous) await rm(backup, { recursive: true, force: true })\n } finally {\n await rm(candidate, { recursive: true, force: true })\n }\n}\n\nfunction sha256(bytes: Uint8Array): string {\n return createHash('sha256').update(bytes).digest('hex')\n}\n\nasync function runCapture(file: string, args: readonly string[]): Promise<string> {\n return new Promise<string>((resolveRun, reject) => {\n execFile(file, [...args], {\n windowsHide: true,\n timeout: 120_000,\n maxBuffer: MAX_ARCHIVE_LIST_BYTES,\n encoding: 'utf8',\n }, (error, stdout) => {\n if (error === null) resolveRun(stdout)\n else reject(error)\n })\n })\n}\n\nfunction validatedArchiveEntry(rawEntry: string): readonly string[] {\n if (rawEntry.length === 0 || rawEntry.includes('\\\\') || rawEntry.includes('\\u0000')\n || rawEntry.startsWith('/') || /^[a-zA-Z]:/u.test(rawEntry)) {\n throw new Error('frp_archive_path_invalid')\n }\n const segments = rawEntry.replace(/\\/$/u, '').split('/')\n if (segments.some(segment => segment === '' || segment === '.' || segment === '..')) {\n throw new Error('frp_archive_path_invalid')\n }\n return segments\n}\n\n/** Select exactly one nested frpc executable from a safe archive listing. */\nexport function selectFrpExecutableEntry(entries: readonly string[], executableName: string): string {\n if (entries.length === 0 || entries.length > MAX_ARCHIVE_ENTRIES) throw new Error('frp_archive_entries_invalid')\n let executableEntry: string | undefined\n for (const entry of entries) {\n const segments = validatedArchiveEntry(entry)\n if (segments.length >= 2 && segments.at(-1) === executableName) {\n if (executableEntry !== undefined) throw new Error('frp_archive_executable_ambiguous')\n executableEntry = entry.replace(/\\/$/u, '')\n }\n }\n if (executableEntry === undefined) throw new Error('frp_archive_executable_missing')\n return executableEntry\n}\n\nasync function defaultExtractArtifact(archive: string, destination: string, executableName: string): Promise<void> {\n const tar = process.platform === 'win32' ? 'tar.exe' : 'tar'\n const listing = await runCapture(tar, ['-tf', archive])\n const entries = listing.split(/\\r?\\n/u).filter(entry => entry.length > 0)\n const executableEntry = selectFrpExecutableEntry(entries, executableName)\n const unpacked = join(destination, 'archive')\n await mkdir(unpacked, { recursive: true, mode: 0o700 })\n await runCapture(tar, ['-xf', archive, '-C', unpacked, executableEntry])\n const extracted = join(unpacked, ...validatedArchiveEntry(executableEntry))\n if (!await regularFile(extracted)) throw new Error('frp_archive_executable_invalid')\n await copyFile(extracted, join(destination, executableName))\n}\n\nasync function defaultFetchArtifact(artifact: FrpArtifact, signal: AbortSignal): Promise<Uint8Array> {\n const response = await fetch(artifact.downloadUrl, { redirect: 'follow', signal })\n if (!response.ok) throw new Error(`frp_download_http_${String(response.status)}`)\n const finalUrl = new URL(response.url)\n const officialHost = finalUrl.hostname === 'github.com' || finalUrl.hostname.endsWith('.githubusercontent.com')\n if (finalUrl.protocol !== 'https:' || !officialHost) throw new Error('frp_download_origin_invalid')\n const lengthHeader = response.headers.get('content-length')\n const declaredLength = lengthHeader === null ? undefined : Number(lengthHeader)\n if (declaredLength !== undefined && (!Number.isFinite(declaredLength) || declaredLength !== artifact.downloadBytes)) {\n throw new Error('frp_download_size_mismatch')\n }\n if (response.body === null) throw new Error('frp_download_empty')\n const chunks: Uint8Array[] = []\n let received = 0\n const reader = response.body.getReader()\n while (true) {\n const result = await reader.read()\n if (result.done) break\n received += result.value.byteLength\n if (received > artifact.downloadBytes) {\n await reader.cancel()\n throw new Error('frp_download_size_mismatch')\n }\n chunks.push(result.value)\n }\n if (received !== artifact.downloadBytes) throw new Error('frp_download_size_mismatch')\n const bytes = new Uint8Array(received)\n let offset = 0\n for (const chunk of chunks) {\n bytes.set(chunk, offset)\n offset += chunk.byteLength\n }\n return bytes\n}\n\nasync function defaultInspectExecutable(executable: string): Promise<string> {\n return (await runCapture(executable, ['--version'])).trim()\n}\n\n/** Owns the optional official frpc binary inside the DSH Mobile state directory. */\nexport class FrpComponentManager {\n readonly executable: string\n readonly componentRoot: string\n readonly componentStorage: string\n readonly logRoot: string\n private readonly stagingRoot: string\n private readonly artifact: FrpArtifact | undefined\n private readonly fetchArtifact: (artifact: FrpArtifact, signal: AbortSignal) => Promise<Uint8Array>\n private readonly extractArtifact: (archive: string, destination: string, executableName: string) => Promise<void>\n private readonly inspectExecutable: (executable: string) => Promise<string>\n private installed = false\n private installedBytes = 0\n private errorCode: string | undefined\n private queue: Promise<void> = Promise.resolve()\n\n constructor(options: FrpComponentManagerOptions) {\n const stateDirectory = resolve(options.stateDirectory)\n if (!isAbsolute(stateDirectory)) throw new Error('frp state directory must be absolute')\n const platform = options.platform ?? process.platform\n const arch = options.arch ?? process.arch\n this.artifact = FRP_COMPONENT_RELEASES[`${platform}-${arch}`]\n this.componentRoot = join(stateDirectory, 'components', 'frp')\n this.componentStorage = join(this.componentRoot, FRP_VERSION)\n this.executable = join(this.componentStorage, platform === 'win32' ? 'frpc.exe' : 'frpc')\n this.logRoot = join(stateDirectory, 'logs', 'frp')\n this.stagingRoot = join(stateDirectory, 'staging', 'frp')\n for (const child of [this.componentRoot, this.componentStorage, this.logRoot, this.stagingRoot]) {\n if (!inside(stateDirectory, child)) throw new Error('frp component path escaped its state directory')\n }\n this.fetchArtifact = options.fetchArtifact ?? defaultFetchArtifact\n this.extractArtifact = options.extractArtifact ?? defaultExtractArtifact\n this.inspectExecutable = options.inspectExecutable ?? defaultInspectExecutable\n }\n\n /** Inspect the managed executable without relying on global FRP installations. */\n async initialize(): Promise<void> {\n this.installed = await regularFile(this.executable)\n this.installedBytes = this.installed ? (await stat(this.executable)).size : 0\n if (this.installed) {\n try {\n const version = await this.inspectExecutable(this.executable)\n if (version !== FRP_VERSION) throw new Error('frp_component_version_mismatch')\n this.errorCode = undefined\n } catch {\n this.installed = false\n this.errorCode = 'frp_component_invalid'\n }\n }\n }\n\n /** Return component metadata without exposing configuration or credentials. */\n status(): FrpComponentStatus {\n return Object.freeze({\n supported: this.artifact !== undefined,\n installed: this.installed,\n version: FRP_VERSION,\n downloadBytes: this.artifact?.downloadBytes ?? 0,\n installedBytes: this.installedBytes,\n sourceUrl: this.artifact?.downloadUrl ?? 'https://github.com/fatedier/frp/releases',\n releasePage: `https://github.com/fatedier/frp/releases/tag/v${FRP_VERSION}`,\n storagePath: this.componentRoot,\n ...(this.errorCode === undefined ? {} : { errorCode: this.errorCode }),\n })\n }\n\n /** Download, verify, and extract only frpc after explicit confirmation. */\n install(): Promise<FrpComponentStatus> {\n return this.enqueue(async () => {\n const artifact = this.artifact\n if (artifact === undefined) throw new Error('frp_component_unsupported')\n await mkdir(this.stagingRoot, { recursive: true, mode: 0o700 })\n const staging = await mkdtemp(join(this.stagingRoot, 'install-'))\n try {\n const controller = new AbortController()\n const timeout = setTimeout(() => { controller.abort() }, 120_000)\n timeout.unref()\n let bytes: Uint8Array\n try { bytes = await this.fetchArtifact(artifact, controller.signal) } finally { clearTimeout(timeout) }\n if (bytes.byteLength !== artifact.downloadBytes) throw new Error('frp_download_size_mismatch')\n if (sha256(bytes) !== artifact.downloadSha256) throw new Error('frp_download_hash_mismatch')\n const archive = join(staging, artifact.archiveName)\n await writeFile(archive, bytes, { flag: 'wx', mode: 0o600 })\n await this.extractArtifact(archive, staging, artifact.executableName)\n const extracted = join(staging, artifact.executableName)\n if (!await regularFile(extracted)) throw new Error('frp_executable_missing')\n await chmod(extracted, 0o700)\n const version = await this.inspectExecutable(extracted)\n if (version !== FRP_VERSION) throw new Error('frp_component_version_mismatch')\n const candidate = join(this.componentRoot, `.install-${randomBytes(12).toString('hex')}`)\n await mkdir(candidate, { recursive: true, mode: 0o700 })\n const candidateExecutable = join(candidate, artifact.executableName)\n await copyFile(extracted, candidateExecutable)\n await chmod(candidateExecutable, 0o700)\n await replaceDirectory(this.componentStorage, candidate)\n this.installed = true\n this.installedBytes = (await stat(this.executable)).size\n this.errorCode = undefined\n } finally {\n await rm(staging, { recursive: true, force: true })\n }\n })\n }\n\n /** Remove all FRP executable, staging, and log files owned by DSH Mobile. */\n purge(): Promise<FrpComponentStatus> {\n return this.enqueue(async () => {\n await Promise.all([\n rm(this.componentRoot, { recursive: true, force: true }),\n rm(this.logRoot, { recursive: true, force: true }),\n rm(this.stagingRoot, { recursive: true, force: true }),\n ])\n this.installed = false\n this.installedBytes = 0\n this.errorCode = undefined\n })\n }\n\n private enqueue(operation: () => Promise<void>): Promise<FrpComponentStatus> {\n const task = this.queue.then(operation, operation)\n this.queue = task.then(() => undefined, () => undefined)\n return task.then(() => this.status())\n }\n}\n","/** Loopback-only HTTP vhost port used between Caddy and frps. */\nexport const FRP_VHOST_HTTP_PORT = 7080\n\nfunction publicDnsHostname(value: string): boolean {\n return value.length <= 253 && value.includes('.') && !/^[0-9.]+$/u.test(value)\n && !value.includes(':') && value.split('.').every(label => label.length >= 1 && label.length <= 63\n && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label))\n}\n\n/** Build the only supported frps and Caddy configuration from validated user inputs. */\nexport function createRestrictedFrpServerTemplate(serverPort: number, token: string, publicOrigin: string): string {\n if (!Number.isSafeInteger(serverPort) || serverPort < 1 || serverPort > 65_535\n || token.length < 16 || token.length > 512 || /[\\s\\u0000-\\u001f\\u007f]/u.test(token)) {\n throw new Error('frp_template_input_invalid')\n }\n let url: URL\n try { url = new URL(publicOrigin) } catch { throw new Error('frp_template_input_invalid') }\n if (url.protocol !== 'https:' || url.port !== '' || url.pathname !== '/' || url.search !== '' || url.hash !== ''\n || url.username !== '' || url.password !== '' || !publicDnsHostname(url.hostname)) {\n throw new Error('frp_template_input_invalid')\n }\n return [\n '# frps.toml',\n `bindPort = ${String(serverPort)}`,\n 'proxyBindAddr = \"127.0.0.1\"',\n `vhostHTTPPort = ${String(FRP_VHOST_HTTP_PORT)}`,\n 'auth.method = \"token\"',\n `auth.token = ${JSON.stringify(token)}`,\n '',\n '# Caddyfile',\n `${url.hostname} {`,\n ` reverse_proxy 127.0.0.1:${String(FRP_VHOST_HTTP_PORT)}`,\n '}',\n '',\n ].join('\\n')\n}\n","import { randomBytes } from 'node:crypto'\nimport { isIP } from 'node:net'\nimport { lstat, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, join, resolve } from 'node:path'\nimport { restrictPrivateFile } from './private-file.js'\nimport { createRestrictedFrpServerTemplate, FRP_VHOST_HTTP_PORT } from './frp-template.js'\n\nconst MAX_SETTINGS_BYTES = 8 * 1024\n\n/** Credentials and endpoints required by the restricted FRP provider. */\nexport interface FrpSettings {\n readonly version: 1\n readonly serverAddress: string\n readonly serverPort: number\n readonly token: string\n readonly publicOrigin: string\n}\n\n/** Safe FRP configuration fields returned to the desktop UI. */\nexport interface FrpConfigurationStatus {\n readonly configured: boolean\n readonly serverAddress?: string\n readonly serverPort?: number\n readonly publicOrigin?: string\n readonly vhostHttpPort: number\n readonly storagePath: string\n readonly errorCode?: string\n}\n\nfunction hostname(value: string): boolean {\n if (value.length > 253 || !value.includes('.')) return false\n return value.split('.').every(label => label.length >= 1 && label.length <= 63\n && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label))\n}\n\n/** Validate the FRP server hostname or IP address. */\nexport function validateFrpServerAddress(value: unknown): string {\n if (typeof value !== 'string' || value !== value.trim() || value.length === 0 || value.length > 253\n || /[\\s\\u0000-\\u001f\\u007f/\\\\@?#]/u.test(value)) throw new Error('frp_server_address_invalid')\n const normalized = value.toLowerCase().replace(/\\.$/u, '')\n if (isIP(normalized) === 0 && !hostname(normalized)) throw new Error('frp_server_address_invalid')\n return normalized\n}\n\n/** Validate the FRP control port. */\nexport function validateFrpServerPort(value: unknown): number {\n if (!Number.isSafeInteger(value) || Number(value) < 1 || Number(value) > 65_535) {\n throw new Error('frp_server_port_invalid')\n }\n return Number(value)\n}\n\n/** Validate a high-entropy FRP token before durable storage. */\nexport function validateFrpToken(value: unknown): string {\n if (typeof value !== 'string' || value.length < 16 || value.length > 512\n || /[\\s\\u0000-\\u001f\\u007f]/u.test(value)) throw new Error('frp_token_invalid')\n return value\n}\n\n/** Validate the public HTTPS origin used by Caddy and Android pairing. */\nexport function validateFrpPublicOrigin(value: unknown): string {\n if (typeof value !== 'string' || value.length > 512) throw new Error('frp_public_origin_invalid')\n let url: URL\n try { url = new URL(value) } catch { throw new Error('frp_public_origin_invalid') }\n if (url.protocol !== 'https:' || url.port !== '' || url.pathname !== '/' || url.search !== '' || url.hash !== ''\n || url.username !== '' || url.password !== '' || isIP(url.hostname) !== 0 || !hostname(url.hostname)) {\n throw new Error('frp_public_origin_invalid')\n }\n return url.origin\n}\n\n/** Parse FRP settings at the loopback request and filesystem boundaries. */\nexport function parseFrpSettings(value: unknown): FrpSettings {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('frp_settings_invalid')\n const record = value as Record<string, unknown>\n if (Reflect.ownKeys(record).some(key => !['version', 'serverAddress', 'serverPort', 'token', 'publicOrigin'].includes(String(key)))) {\n throw new Error('frp_settings_invalid')\n }\n if (record.version !== undefined && record.version !== 1) throw new Error('frp_settings_invalid')\n return Object.freeze({\n version: 1,\n serverAddress: validateFrpServerAddress(record.serverAddress),\n serverPort: validateFrpServerPort(record.serverPort),\n token: validateFrpToken(record.token),\n publicOrigin: validateFrpPublicOrigin(record.publicOrigin),\n })\n}\n\nfunction tomlString(value: string): string {\n return JSON.stringify(value)\n}\n\n/** Build the single-purpose frpc configuration for the current loopback gateway. */\nexport function createFrpcToml(settings: FrpSettings, localPort: number): string {\n if (!Number.isSafeInteger(localPort) || localPort < 1 || localPort > 65_535) throw new Error('frp_local_port_invalid')\n const hostnameValue = new URL(settings.publicOrigin).hostname\n return [\n `serverAddr = ${tomlString(settings.serverAddress)}`,\n `serverPort = ${String(settings.serverPort)}`,\n 'auth.method = \"token\"',\n `auth.token = ${tomlString(settings.token)}`,\n 'transport.tls.enable = true',\n '',\n '[[proxies]]',\n 'name = \"dsh-mobile\"',\n 'type = \"http\"',\n 'localIP = \"127.0.0.1\"',\n `localPort = ${String(localPort)}`,\n `customDomains = [${tomlString(hostnameValue)}]`,\n 'transport.useEncryption = true',\n 'transport.useCompression = true',\n '',\n ].join('\\n')\n}\n\n/** Build the matching restricted frps and Caddy templates for one VPS. */\nexport function createFrpServerTemplate(settings: FrpSettings): string {\n return createRestrictedFrpServerTemplate(settings.serverPort, settings.token, settings.publicOrigin)\n}\n\nasync function atomicPrivateWrite(file: string, body: string): Promise<void> {\n const directory = dirname(file)\n await mkdir(directory, { recursive: true, mode: 0o700 })\n try {\n const current = await lstat(file)\n if (!current.isFile() || current.isSymbolicLink()) throw new Error('frp_config_target_invalid')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n const temporary = join(directory, `.${basename(file)}.${randomBytes(12).toString('hex')}.tmp`)\n try {\n await writeFile(temporary, body, { encoding: 'utf8', flag: 'wx', mode: 0o600 })\n await rename(temporary, file)\n await restrictPrivateFile(file)\n } catch (error) {\n await rm(temporary, { force: true })\n throw error\n }\n}\n\n/** Owns private FRP settings and generation-specific frpc configuration. */\nexport class FrpConfigStore {\n readonly stateRoot: string\n readonly settingsFile: string\n readonly runtimeConfigFile: string\n private settingsValue: FrpSettings | undefined\n private errorCode: string | undefined\n\n constructor(stateDirectory: string) {\n if (!isAbsolute(stateDirectory)) throw new Error('frp config state directory must be absolute')\n this.stateRoot = resolve(stateDirectory)\n this.settingsFile = join(this.stateRoot, 'settings.json')\n this.runtimeConfigFile = join(this.stateRoot, 'frpc.toml')\n }\n\n /** Load private settings while rejecting links, oversized files, and unknown fields. */\n async initialize(): Promise<void> {\n let entry\n try { entry = await lstat(this.settingsFile) } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return\n throw error\n }\n if (!entry.isFile() || entry.isSymbolicLink() || entry.size > MAX_SETTINGS_BYTES) {\n this.errorCode = 'frp_config_invalid'\n return\n }\n await restrictPrivateFile(this.settingsFile)\n try {\n this.settingsValue = parseFrpSettings(JSON.parse(await readFile(this.settingsFile, 'utf8')) as unknown)\n this.errorCode = undefined\n } catch {\n this.settingsValue = undefined\n this.errorCode = 'frp_config_invalid'\n }\n }\n\n /** Return configuration metadata without exposing the FRP token. */\n status(): FrpConfigurationStatus {\n const settings = this.settingsValue\n return Object.freeze({\n configured: settings !== undefined,\n ...(settings === undefined ? {} : {\n serverAddress: settings.serverAddress,\n serverPort: settings.serverPort,\n publicOrigin: settings.publicOrigin,\n }),\n vhostHttpPort: FRP_VHOST_HTTP_PORT,\n storagePath: this.stateRoot,\n ...(this.errorCode === undefined ? {} : { errorCode: this.errorCode }),\n })\n }\n\n /** Return private settings only to the provider lifecycle. */\n settings(): FrpSettings | undefined {\n return this.settingsValue\n }\n\n /** Atomically replace private FRP settings. */\n async configure(value: unknown): Promise<FrpConfigurationStatus> {\n const settings = parseFrpSettings(value)\n await atomicPrivateWrite(this.settingsFile, `${JSON.stringify(settings)}\\n`)\n await rm(this.runtimeConfigFile, { force: true })\n this.settingsValue = settings\n this.errorCode = undefined\n return this.status()\n }\n\n /** Materialize the private generation-specific frpc configuration. */\n async writeRuntimeConfig(localPort: number): Promise<string> {\n const settings = this.settingsValue\n if (settings === undefined) throw new Error('frp_config_missing')\n await atomicPrivateWrite(this.runtimeConfigFile, createFrpcToml(settings, localPort))\n return this.runtimeConfigFile\n }\n\n /** Remove only configuration files owned by the FRP provider. */\n async purge(): Promise<FrpConfigurationStatus> {\n await rm(this.stateRoot, { recursive: true, force: true })\n this.settingsValue = undefined\n this.errorCode = undefined\n return this.status()\n }\n}\n\nexport { FRP_VHOST_HTTP_PORT as DEFAULT_VHOST_HTTP_PORT }\n","import { randomBytes } from 'node:crypto'\nimport type { ChildProcess } from 'node:child_process'\nimport { lstat, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'\nimport { basename, dirname, join } from 'node:path'\nimport type { MobileAccessGateway } from './gateway.js'\nimport { restrictPrivateFile } from './private-file.js'\n\n/** Remote transports supported by the desktop plugin and Android client. */\nexport type RemoteProvider = 'tailscale' | 'cpolar' | 'frp'\n\n/** Common safe status returned by every remote provider controller. */\nexport interface RemoteProviderStatus {\n readonly enabled: boolean\n readonly state: string\n readonly origin?: string\n readonly loginUrl?: string\n readonly setupUrl?: string\n readonly errorCode?: string\n}\n\n/** Lifecycle shared by selectable remote providers. */\nexport interface RemoteProviderController {\n initialize(): Promise<void>\n gateway(): MobileAccessGateway | undefined\n status(): RemoteProviderStatus\n setEnabled(enabled: boolean): Promise<RemoteProviderStatus>\n reconnect(): Promise<RemoteProviderStatus>\n reset(): Promise<RemoteProviderStatus>\n close(): Promise<void>\n}\n\n/** Durable selection for the single active remote transport. */\nexport interface RemoteProviderState {\n readonly version: 1\n readonly provider: RemoteProvider\n}\n\nconst REMOTE_PROVIDERS: readonly RemoteProvider[] = ['tailscale', 'cpolar', 'frp']\n\n/** Persist only the selected remote provider. */\nexport interface RemoteProviderStore {\n save(state: RemoteProviderState): Promise<void>\n}\n\nfunction aggregateErrors(errors: readonly unknown[], message: string): Error | undefined {\n if (errors.length === 0) return undefined\n if (errors.length === 1 && errors[0] instanceof Error) return errors[0]\n return new AggregateError(errors, message)\n}\n\n/** Settle independent remote cleanup work before reporting any collected failure. */\nexport async function settleRemoteResources(\n steps: readonly (() => void | Promise<void>)[],\n message = 'remote resource cleanup failed',\n): Promise<void> {\n const results = await Promise.allSettled(steps.map(async step => step()))\n const errors = results\n .filter(result => result.status === 'rejected')\n .map(result => result.reason as unknown)\n const failure = aggregateErrors(errors, message)\n if (failure !== undefined) throw failure\n}\n\n/**\n * Serialize all provider mutations and preserve the single-provider invariant.\n * Operations read the selected controller only after reaching the front of the queue.\n */\nexport class RemoteProviderCoordinator {\n private selectedValue: RemoteProvider\n private queue: Promise<void> = Promise.resolve()\n\n constructor(\n selected: RemoteProvider,\n private readonly controllers: Readonly<Record<RemoteProvider, RemoteProviderController>>,\n private readonly store: RemoteProviderStore,\n ) {\n this.selectedValue = selected\n }\n\n /** Return the durable provider currently selected by the desktop UI. */\n get selected(): RemoteProvider {\n return this.selectedValue\n }\n\n /** Return the controller selected when this method is called. */\n controller(): RemoteProviderController {\n return this.controllers[this.selectedValue]\n }\n\n /** Run a provider-owned mutation after all earlier provider work settles. */\n mutate<T>(operation: (controller: RemoteProviderController) => Promise<T>): Promise<T> {\n return this.enqueue(() => operation(this.controller()))\n }\n\n /** Disable the previous provider, persist the new selection, and retain rollback on write failure. */\n select(provider: RemoteProvider): Promise<void> {\n return this.enqueue(async () => {\n if (provider === this.selectedValue) return\n const previous = this.controllers[this.selectedValue]\n const restore = previous.status().enabled\n if (restore) await previous.setEnabled(false)\n try {\n await this.store.save({ version: 1, provider })\n this.selectedValue = provider\n } catch (error) {\n if (restore) {\n try { await previous.setEnabled(true) }\n catch (restoreError) { throw new AggregateError([error, restoreError], 'remote provider selection rollback failed') }\n }\n throw error\n }\n })\n }\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const task = this.queue.then(\n () => this.runAndEnforce(operation),\n () => this.runAndEnforce(operation),\n )\n this.queue = task.then(() => undefined, () => undefined)\n return task\n }\n\n private async runAndEnforce<T>(operation: () => Promise<T>): Promise<T> {\n let value: T | undefined\n let operationError: unknown\n try { value = await operation() } catch (error) { operationError = error }\n const results = await Promise.allSettled(\n REMOTE_PROVIDERS\n .filter(provider => provider !== this.selectedValue)\n .map(provider => this.controllers[provider].setEnabled(false)),\n )\n const errors = [\n ...(operationError === undefined ? [] : [operationError]),\n ...results.filter(result => result.status === 'rejected').map(result => result.reason as unknown),\n ]\n const failure = aggregateErrors(errors, 'remote provider operation failed')\n if (failure !== undefined) throw failure\n return value as T\n }\n}\n\n/** Stop an owned provider process and do not report completion before its close event. */\nexport async function terminateRemoteProcess(\n child: ChildProcess,\n gracefulTimeoutMs = 1_500,\n forcedTimeoutMs = 1_500,\n): Promise<void> {\n if (child.exitCode !== null || child.signalCode !== null) return\n await new Promise<void>((resolveClose, rejectClose) => {\n let gracefulTimer: NodeJS.Timeout | undefined\n let forcedTimer: NodeJS.Timeout | undefined\n let settled = false\n const finish = (error?: Error): void => {\n if (settled) return\n settled = true\n if (gracefulTimer !== undefined) clearTimeout(gracefulTimer)\n if (forcedTimer !== undefined) clearTimeout(forcedTimer)\n child.off('close', onClose)\n if (error === undefined) resolveClose()\n else rejectClose(error)\n }\n const onClose = (): void => { finish() }\n child.once('close', onClose)\n try { child.kill('SIGTERM') } catch (error) {\n finish(error instanceof Error ? error : new Error(String(error)))\n return\n }\n if (settled) return\n gracefulTimer = setTimeout(() => {\n try {\n if (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL')\n } catch (error) {\n finish(error instanceof Error ? error : new Error(String(error)))\n return\n }\n if (settled) return\n forcedTimer = setTimeout(() => {\n finish(new Error('remote_process_stop_timeout'))\n }, forcedTimeoutMs)\n forcedTimer.unref()\n }, gracefulTimeoutMs)\n gracefulTimer.unref()\n })\n}\n\n/** Validate the provider selection loaded across the filesystem boundary. */\nexport function parseRemoteProviderState(value: unknown): RemoteProviderState {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error('remote provider state must be an object')\n }\n const record = value as Record<string, unknown>\n if (record.version !== 1\n || (record.provider !== 'tailscale' && record.provider !== 'cpolar' && record.provider !== 'frp')\n || Reflect.ownKeys(record).some(key => key !== 'version' && key !== 'provider')) {\n throw new Error('remote provider state has an unsupported format')\n }\n return Object.freeze({ version: 1, provider: record.provider })\n}\n\n/** Atomic selection store whose absent-file state uses the configured default. */\nexport class JsonRemoteProviderStore {\n constructor(private readonly file: string, private readonly defaultProvider: RemoteProvider) {}\n\n async load(): Promise<RemoteProviderState> {\n let stat\n try {\n stat = await lstat(this.file)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') {\n return Object.freeze({ version: 1, provider: this.defaultProvider })\n }\n throw error\n }\n if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 4096) {\n throw new Error('remote provider state must be a regular file no larger than 4 KiB')\n }\n await restrictPrivateFile(this.file)\n let parsed: unknown\n try { parsed = JSON.parse(await readFile(this.file, 'utf8')) as unknown } catch (error) {\n throw new Error('remote provider state is not valid JSON', { cause: error })\n }\n return parseRemoteProviderState(parsed)\n }\n\n async save(state: RemoteProviderState): Promise<void> {\n const validated = parseRemoteProviderState(state)\n const directory = dirname(this.file)\n await mkdir(directory, { recursive: true, mode: 0o700 })\n try {\n const current = await lstat(this.file)\n if (!current.isFile() || current.isSymbolicLink()) {\n throw new Error('remote provider state target must remain a regular file')\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n const temporary = join(directory, `.${basename(this.file)}.${randomBytes(12).toString('hex')}.tmp`)\n try {\n await writeFile(temporary, `${JSON.stringify(validated)}\\n`, { encoding: 'utf8', flag: 'wx', mode: 0o600 })\n await rename(temporary, this.file)\n await restrictPrivateFile(this.file)\n } catch (error) {\n await rm(temporary, { force: true })\n throw error\n }\n }\n}\n\n/** Resolve the first-run provider without letting environment values bypass validation. */\nexport function configuredRemoteProvider(environment: NodeJS.ProcessEnv): RemoteProvider {\n const value = environment.DSH_MOBILE_REMOTE_PROVIDER ?? 'tailscale'\n if (value !== 'tailscale' && value !== 'cpolar' && value !== 'frp') {\n throw new Error('DSH_MOBILE_REMOTE_PROVIDER must be tailscale, cpolar, or frp')\n }\n return value\n}\n","import { spawn, execFile, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport { lstat, rm } from 'node:fs/promises'\nimport { connect } from 'node:net'\nimport { isAbsolute } from 'node:path'\nimport type { MobileAccessControlStore } from './control.js'\nimport type { FrpConfigStore } from './frp-config.js'\nimport { DEFAULT_VHOST_HTTP_PORT } from './frp-config.js'\nimport type { MobileAccessGateway } from './gateway.js'\nimport { settleRemoteResources, terminateRemoteProcess, type RemoteProviderController } from './remote.js'\n\nconst START_TIMEOUT_MS = 45_000\nconst DISCOVERY_REQUEST_TIMEOUT_MS = 5_000\nconst DISCOVERY_RETRY_MS = 1_000\nconst MAX_DISCOVERY_BYTES = 16 * 1024\nconst VHOST_PROBE_TIMEOUT_MS = 1_500\n\n/** Product-facing states for the restricted self-hosted FRP transport. */\nexport type FrpState = 'off' | 'unavailable' | 'starting' | 'connecting' | 'ready' | 'error'\n\n/** Safe FRP state returned only through the loopback DSH control route. */\nexport interface FrpStatus {\n readonly enabled: boolean\n readonly state: FrpState\n readonly origin?: string\n readonly errorCode?: string\n}\n\n/** Inputs for one FRP client process and authenticated DSH gateway. */\nexport interface FrpControllerOptions {\n readonly store: MobileAccessControlStore\n readonly executable: string\n readonly config: FrpConfigStore\n readonly instanceId: string\n readonly createGateway: (origin: string) => Promise<MobileAccessGateway>\n readonly onStatus?: (status: FrpStatus) => void\n readonly verifyConfig?: (executable: string, configFile: string) => Promise<void>\n readonly launchClient?: (executable: string, configFile: string) => ChildProcessWithoutNullStreams\n readonly probeVhostExposure?: (serverAddress: string, port: number) => Promise<boolean>\n readonly probeDiscovery?: (origin: string, expectedInstanceId: string, signal: AbortSignal) => Promise<boolean>\n readonly startTimeoutMs?: number\n readonly retryIntervalMs?: number\n}\n\nfunction publicStatus(status: FrpStatus): FrpStatus {\n return Object.freeze({\n enabled: status.enabled,\n state: status.state,\n ...(status.origin === undefined ? {} : { origin: status.origin }),\n ...(status.errorCode === undefined ? {} : { errorCode: status.errorCode }),\n })\n}\n\nasync function defaultVerifyConfig(executable: string, configFile: string): Promise<void> {\n await new Promise<void>((resolveRun, reject) => {\n execFile(executable, ['verify', '-c', configFile], {\n windowsHide: true,\n timeout: 30_000,\n maxBuffer: 64 * 1024,\n }, error => {\n if (error === null) resolveRun()\n else reject(error)\n })\n })\n}\n\nfunction defaultLaunchClient(executable: string, configFile: string): ChildProcessWithoutNullStreams {\n return spawn(executable, ['-c', configFile], {\n shell: false,\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true,\n })\n}\n\nasync function defaultProbeVhostExposure(serverAddress: string, port: number): Promise<boolean> {\n return new Promise<boolean>(resolveProbe => {\n const socket = connect({ host: serverAddress, port })\n let finished = false\n const finish = (exposed: boolean): void => {\n if (finished) return\n finished = true\n clearTimeout(timer)\n socket.destroy()\n resolveProbe(exposed)\n }\n const timer = setTimeout(() => { finish(false) }, VHOST_PROBE_TIMEOUT_MS)\n timer.unref()\n socket.once('connect', () => { finish(true) })\n socket.once('error', () => { finish(false) })\n })\n}\n\nasync function boundedResponseBytes(response: Response): Promise<Uint8Array> {\n if (response.body === null) throw new Error('frp_discovery_invalid')\n const declaredLength = Number(response.headers.get('content-length'))\n if (Number.isFinite(declaredLength) && declaredLength > MAX_DISCOVERY_BYTES) throw new Error('frp_discovery_invalid')\n const reader = response.body.getReader()\n const chunks: Uint8Array[] = []\n let received = 0\n while (true) {\n const result = await reader.read()\n if (result.done) break\n received += result.value.byteLength\n if (received > MAX_DISCOVERY_BYTES) {\n await reader.cancel()\n throw new Error('frp_discovery_invalid')\n }\n chunks.push(result.value)\n }\n const bytes = new Uint8Array(received)\n let offset = 0\n for (const chunk of chunks) {\n bytes.set(chunk, offset)\n offset += chunk.byteLength\n }\n return bytes\n}\n\nasync function defaultProbeDiscovery(origin: string, expectedInstanceId: string, signal: AbortSignal): Promise<boolean> {\n const requestController = new AbortController()\n const abort = (): void => { requestController.abort() }\n signal.addEventListener('abort', abort, { once: true })\n const timeout = setTimeout(abort, DISCOVERY_REQUEST_TIMEOUT_MS)\n timeout.unref()\n try {\n const response = await fetch(`${origin}/mobile-access/discovery`, {\n method: 'GET',\n redirect: 'error',\n cache: 'no-store',\n signal: requestController.signal,\n headers: { accept: 'application/json' },\n })\n if (!response.ok) return false\n let value: unknown\n try { value = JSON.parse(new TextDecoder().decode(await boundedResponseBytes(response))) as unknown } catch {\n throw new Error('frp_discovery_invalid')\n }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('frp_discovery_invalid')\n const actual = (value as Record<string, unknown>).instanceId\n if (typeof actual !== 'string') throw new Error('frp_discovery_invalid')\n if (actual !== expectedInstanceId) throw new Error('frp_discovery_mismatch')\n return true\n } finally {\n clearTimeout(timeout)\n signal.removeEventListener('abort', abort)\n }\n}\n\n/** Owns frpc, its generation-specific configuration, and the remote gateway. */\nexport class FrpController implements RemoteProviderController {\n private enabled = false\n private initialized = false\n private disposed = false\n private child: ChildProcessWithoutNullStreams | undefined\n private gatewayValue: MobileAccessGateway | undefined\n private generation = 0\n private latest: FrpStatus = publicStatus({ enabled: false, state: 'off' })\n private queue: Promise<void> = Promise.resolve()\n private startupAbort: AbortController | undefined\n\n constructor(private readonly options: FrpControllerOptions) {\n if (!isAbsolute(options.executable)) throw new Error('frpc executable path must be absolute')\n if (!/^[a-f0-9]{64}$/u.test(options.instanceId)) throw new Error('FRP instance ID is invalid')\n }\n\n /** Restore the remembered FRP switch without changing LAN or other providers. */\n async initialize(): Promise<void> {\n const state = await this.options.store.load()\n this.enabled = state.enabled\n this.initialized = true\n if (this.enabled) await this.start()\n else this.publish({ enabled: false, state: 'off' })\n }\n\n /** Return the active FRP-backed DSH gateway. */\n gateway(): MobileAccessGateway | undefined {\n return this.gatewayValue\n }\n\n /** Return state safe for the desktop control UI. */\n status(): FrpStatus {\n return publicStatus(this.latest)\n }\n\n /** Enable or disable FRP without changing LAN or another provider. */\n async setEnabled(enabled: boolean): Promise<FrpStatus> {\n if (!this.initialized || this.disposed) throw new Error('FRP controller is unavailable')\n await this.enqueue(async () => {\n if (this.enabled === enabled && (enabled === false || this.child !== undefined)) return\n if (!enabled) await this.stop()\n this.enabled = enabled\n await this.options.store.save({ version: 1, enabled })\n if (enabled) await this.start()\n else this.publish({ enabled: false, state: 'off' })\n })\n return this.status()\n }\n\n /** Restart FRP while retaining its private server settings and devices. */\n async reconnect(): Promise<FrpStatus> {\n if (!this.initialized || this.disposed) throw new Error('FRP controller is unavailable')\n await this.enqueue(async () => {\n if (!this.enabled) {\n this.enabled = true\n await this.options.store.save({ version: 1, enabled: true })\n }\n await this.stop()\n await this.start()\n })\n return this.status()\n }\n\n /** Disable FRP without deleting its explicitly managed component or settings. */\n async reset(): Promise<FrpStatus> {\n if (!this.initialized || this.disposed) throw new Error('FRP controller is unavailable')\n await this.enqueue(async () => {\n await this.stop()\n this.enabled = false\n await this.options.store.save({ version: 1, enabled: false })\n this.publish({ enabled: false, state: 'off' })\n })\n return this.status()\n }\n\n /** Stop all FRP resources without changing the remembered switch. */\n async close(): Promise<void> {\n if (this.disposed) return\n this.disposed = true\n await this.enqueue(() => this.stop())\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const task = this.queue.then(operation, operation)\n this.queue = task.then(() => undefined, () => undefined)\n return task\n }\n\n private publish(status: FrpStatus): void {\n this.latest = publicStatus(status)\n try { this.options.onStatus?.(this.status()) } catch { /* UI observation cannot own runtime state. */ }\n }\n\n private async start(): Promise<void> {\n const generation = ++this.generation\n let executableEntry\n try { executableEntry = await lstat(this.options.executable) } catch {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'frp_component_missing' })\n return\n }\n if (!executableEntry.isFile() || executableEntry.isSymbolicLink()) {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'frp_component_invalid' })\n return\n }\n const settings = this.options.config.settings()\n if (settings === undefined) {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'frp_config_missing' })\n return\n }\n this.publish({ enabled: true, state: 'starting', origin: settings.publicOrigin })\n let exposed: boolean\n try {\n exposed = await (this.options.probeVhostExposure ?? defaultProbeVhostExposure)(\n settings.serverAddress,\n DEFAULT_VHOST_HTTP_PORT,\n )\n } catch {\n this.publish({ enabled: true, state: 'error', origin: settings.publicOrigin, errorCode: 'frp_vhost_probe_failed' })\n return\n }\n if (exposed) {\n this.publish({ enabled: true, state: 'error', origin: settings.publicOrigin, errorCode: 'frp_vhost_publicly_reachable' })\n return\n }\n let gateway: MobileAccessGateway\n try { gateway = await this.options.createGateway(settings.publicOrigin) } catch {\n this.publish({ enabled: true, state: 'error', origin: settings.publicOrigin, errorCode: 'gateway_start_failed' })\n return\n }\n if (generation !== this.generation || !this.enabled) {\n await gateway.close()\n return\n }\n this.gatewayValue = gateway\n let configFile: string\n try {\n configFile = await this.options.config.writeRuntimeConfig(gateway.address().port)\n await (this.options.verifyConfig ?? defaultVerifyConfig)(this.options.executable, configFile)\n } catch {\n await this.failGeneration(generation, 'frp_config_verify_failed')\n return\n }\n if (generation !== this.generation || !this.enabled) return\n let child: ChildProcessWithoutNullStreams\n try { child = (this.options.launchClient ?? defaultLaunchClient)(this.options.executable, configFile) } catch {\n await this.failGeneration(generation, 'frp_launch_failed')\n return\n }\n this.child = child\n child.stdout.resume()\n child.stderr.resume()\n child.once('error', () => { void this.enqueue(() => this.failGeneration(generation, 'frp_launch_failed')) })\n child.once('close', code => {\n if (generation !== this.generation || this.child !== child) return\n this.child = undefined\n if (this.enabled) void this.enqueue(() => this.failGeneration(generation, code === 0 ? 'frp_stopped' : 'frp_exited'))\n })\n this.publish({ enabled: true, state: 'connecting', origin: settings.publicOrigin })\n const controller = new AbortController()\n this.startupAbort = controller\n void this.waitForDiscovery(generation, settings.publicOrigin, controller.signal)\n }\n\n private async waitForDiscovery(generation: number, origin: string, signal: AbortSignal): Promise<void> {\n const deadline = Date.now() + (this.options.startTimeoutMs ?? START_TIMEOUT_MS)\n const probe = this.options.probeDiscovery ?? defaultProbeDiscovery\n while (!signal.aborted && Date.now() < deadline) {\n try {\n if (await probe(origin, this.options.instanceId, signal)) {\n await this.enqueue(async () => {\n if (generation !== this.generation || signal.aborted || !this.enabled) return\n this.startupAbort = undefined\n this.publish({ enabled: true, state: 'ready', origin })\n })\n return\n }\n } catch (error) {\n if (signal.aborted) return\n if (error instanceof Error && (error.message === 'frp_discovery_mismatch' || error.message === 'frp_discovery_invalid')) {\n await this.enqueue(() => this.failGeneration(generation, error.message))\n return\n }\n }\n await new Promise<void>(resolveWait => {\n let finished = false\n const finish = (): void => {\n if (finished) return\n finished = true\n clearTimeout(timer)\n signal.removeEventListener('abort', finish)\n resolveWait()\n }\n const timer = setTimeout(finish, this.options.retryIntervalMs ?? DISCOVERY_RETRY_MS)\n timer.unref()\n signal.addEventListener('abort', finish, { once: true })\n })\n }\n if (!signal.aborted) await this.enqueue(() => this.failGeneration(generation, 'frp_start_timeout'))\n }\n\n private async failGeneration(generation: number, code: string): Promise<void> {\n if (generation !== this.generation) return\n await this.stopProcessAndGateway()\n if (this.enabled) this.publish({ enabled: true, state: 'error', errorCode: code })\n }\n\n private async stop(): Promise<void> {\n ++this.generation\n await this.stopProcessAndGateway()\n }\n\n private async stopProcessAndGateway(): Promise<void> {\n this.startupAbort?.abort()\n this.startupAbort = undefined\n const child = this.child\n this.child = undefined\n const gateway = this.gatewayValue\n this.gatewayValue = undefined\n await settleRemoteResources([\n () => child !== undefined && child.exitCode === null ? terminateRemoteProcess(child) : undefined,\n () => gateway?.close(),\n () => rm(this.options.config.runtimeConfigFile, { force: true }),\n ], 'FRP resource cleanup failed')\n }\n}\n","import { execFile as execFileCallback } from 'node:child_process'\nimport { lookup } from 'node:dns/promises'\nimport { promisify } from 'node:util'\nimport type { RemoteProvider } from './remote.js'\nimport { DSH_MOBILE_VERSION, MINIMUM_ANDROID_APP_VERSION } from './version.js'\n\nconst execFile = promisify(execFileCallback)\n\nexport type DiagnosticStatus = 'ok' | 'warning' | 'error' | 'info'\nexport type DiagnosticReason =\n | 'versions-current'\n | 'network-unavailable' | 'network-interface' | 'network-fixed'\n | 'lan-ready' | 'lan-off'\n | 'firewall-ready' | 'firewall-missing' | 'firewall-unknown'\n | 'remote-off' | 'remote-ready' | 'remote-rate-limited' | 'remote-fake-ip' | 'remote-unreachable'\n | 'remote-needs-login' | 'remote-connecting' | 'remote-controller-error'\n | 'phone-network-unknown'\n\nexport interface DiagnosticFacts {\n readonly provider?: RemoteProvider\n readonly latencyMs?: number\n readonly interfaceName?: string\n readonly endpointSuffix?: string\n readonly controllerCode?: string\n}\n\n/** One user-facing diagnostic result with stable localization data and server fallback copy. */\nexport interface DiagnosticCheck {\n readonly id: string\n readonly status: DiagnosticStatus\n readonly reason: DiagnosticReason\n readonly facts?: DiagnosticFacts\n readonly label: string\n readonly detail: string\n readonly action?: string\n}\n\n/** Runtime facts available without exposing credentials or local file paths. */\nexport interface DiagnosticSnapshot {\n readonly dshVersion: string\n readonly lan: {\n readonly running: boolean\n readonly origin?: string\n readonly configuredInterface?: string\n readonly interfaceName?: string\n readonly networkError?: string\n readonly port?: number\n }\n readonly remote: {\n readonly provider: RemoteProvider\n readonly running: boolean\n readonly state: string\n readonly origin?: string\n readonly errorCode?: string\n }\n}\n\ninterface FirewallObservation {\n readonly state: 'ready' | 'missing' | 'unknown' | 'not-applicable'\n}\n\ninterface RemoteObservation {\n readonly state: 'ready' | 'rate-limited' | 'unreachable' | 'not-applicable'\n readonly latencyMs?: number\n readonly fakeIp?: boolean\n}\n\n/** Injectable probes keep diagnostics deterministic in tests. */\nexport interface DiagnosticProbes {\n readonly firewall?: (port: number | undefined) => Promise<FirewallObservation>\n readonly remote?: (origin: string | undefined) => Promise<RemoteObservation>\n}\n\n/** Sanitized diagnostic response copied by the desktop UI. */\nexport interface ConnectionDiagnostics {\n readonly version: 1\n readonly generatedAt: number\n readonly overall: 'ok' | 'attention' | 'error'\n readonly versions: {\n readonly plugin: string\n readonly dsh: string\n readonly minimumAndroidApp: string\n }\n readonly summary: string\n readonly checks: readonly DiagnosticCheck[]\n readonly report: string\n}\n\nconst REMOTE_ERROR_GUIDANCE: Readonly<Record<string, string>> = Object.freeze({\n component_missing: '重新安装完整插件包。',\n funnel_permission_required: '继续完成 Tailscale Funnel 授权。',\n funnel_https_required: '继续完成 Tailscale HTTPS 授权。',\n funnel_start_failed: '重新打开授权页并允许 Funnel。',\n funnel_start_timeout: '检查网络后点击“重新连接”。',\n tailscale_dns_missing: '确认 Tailscale 登录仍有效后重新连接。',\n sidecar_launch_failed: '重新安装完整插件包后重试。',\n sidecar_stopped: '点击“重新连接”。',\n sidecar_exited: '点击“重新连接”;仍失败时复制诊断报告。',\n control_channel_failed: '点击“重新连接”。',\n cpolar_component_missing: '先安装 cpolar 官方组件。',\n cpolar_component_invalid: '彻底移除 cpolar 组件后重新安装。',\n cpolar_config_missing: '保存 cpolar Authtoken 后重试。',\n cpolar_config_invalid: '重新保存 cpolar Authtoken。',\n cpolar_start_timeout: '检查网络后点击“重新连接”。',\n cpolar_stopped: '点击“重新连接”。',\n cpolar_exited: '点击“重新连接”;仍失败时复制诊断报告。',\n frp_component_missing: '先安装 FRP 官方组件。',\n frp_component_invalid: '彻底清理 FRP 组件后重新安装。',\n frp_config_missing: '先保存自建 FRP 连接配置。',\n frp_config_verify_failed: '检查服务器地址、端口、Token 和公开域名。',\n frp_vhost_publicly_reachable: '将 frps 的 HTTP vhost 监听限制到 127.0.0.1。',\n frp_vhost_probe_failed: '确认 VPS 地址可解析后重新连接。',\n frp_launch_failed: '重新安装 FRP 官方组件后重试。',\n frp_start_timeout: '确认 frps、Caddy 和域名解析正常后重新连接。',\n frp_discovery_mismatch: '公开域名连接到了另一台电脑,请核对 Caddy 与 frps 配置。',\n frp_discovery_invalid: '公开域名返回了非 DSH Mobile 响应。',\n frp_stopped: '点击“重新连接”。',\n frp_exited: '检查 VPS 配置后重新连接;仍失败时复制诊断报告。',\n gateway_start_failed: '确认 DSH 正在运行后重新连接。',\n})\n\nfunction check(\n id: string,\n status: DiagnosticStatus,\n reason: DiagnosticReason,\n label: string,\n detail: string,\n action?: string,\n facts?: DiagnosticFacts,\n): DiagnosticCheck {\n return Object.freeze({ id, status, reason, ...(facts === undefined ? {} : { facts: Object.freeze(facts) }), label, detail, ...(action === undefined ? {} : { action }) })\n}\n\nfunction maskLanOrigin(origin: string | undefined): string {\n if (origin === undefined) return '未分配'\n try {\n const url = new URL(origin)\n const octets = url.hostname.split('.')\n const host = octets.length === 4 ? `${octets[0]}.${octets[1]}.${octets[2]}.x` : '局域网地址'\n return `${url.protocol}//${host}${url.port === '' ? '' : `:${url.port}`}`\n } catch {\n return '地址格式无效'\n }\n}\n\nfunction remoteSuffix(origin: string | undefined): string {\n if (origin === undefined) return '未分配'\n try {\n const hostname = new URL(origin).hostname\n if (hostname.endsWith('.ts.net')) return '*.ts.net'\n for (const suffix of ['.cpolar.cn', '.cpolar.io', '.cpolar.top', '.cpolar.com']) {\n if (hostname.endsWith(suffix)) return `*${suffix}`\n }\n return '公共 HTTPS 地址'\n } catch {\n return '地址格式无效'\n }\n}\n\nfunction defaultFirewallProbe(platform: NodeJS.Platform = process.platform): (port: number | undefined) => Promise<FirewallObservation> {\n return async (port) => {\n if (platform !== 'win32') return { state: 'not-applicable' }\n if (port === undefined) return { state: 'unknown' }\n const script = [\n \"$specs = @(@{ Name = 'DSH Mobile HTTPS'; Protocol = 'TCP' }, @{ Name = 'DSH Mobile Discovery'; Protocol = 'UDP' })\",\n '$ready = $true',\n '$specs | ForEach-Object {',\n ' $spec = $_',\n \" $rule = Get-NetFirewallRule -DisplayName $spec.Name -ErrorAction SilentlyContinue | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' } | Select-Object -First 1\",\n ' if ($null -eq $rule) { $ready = $false; return }',\n ' $filters = @($rule | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue)',\n ` $matching = @($filters | Where-Object { $_.Protocol -eq $spec.Protocol -and ($_.LocalPort -eq 'Any' -or $_.LocalPort -eq '${String(port)}') })`,\n ' if ($matching.Count -eq 0) { $ready = $false }',\n '}',\n \"if ($ready) { 'ready' } else { 'missing' }\",\n ].join('; ')\n try {\n const result = await execFile('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], {\n encoding: 'utf8',\n timeout: 3_000,\n windowsHide: true,\n })\n return { state: result.stdout.trim() === 'ready' ? 'ready' : 'missing' }\n } catch {\n return { state: 'unknown' }\n }\n }\n}\n\n/** Allow remote relays enough time to answer without making diagnostics unbounded. */\nexport function remoteDiagnosticTimeoutMs(origin: string): number {\n const hostname = new URL(origin).hostname.toLowerCase()\n if (hostname.endsWith('.ts.net') || hostname.includes('.cpolar.')) return 10_000\n return 10_000\n}\n\nasync function defaultRemoteProbe(origin: string | undefined): Promise<RemoteObservation> {\n if (origin === undefined) return { state: 'not-applicable' }\n const hostname = new URL(origin).hostname\n const started = performance.now()\n try {\n const response = await fetch(new URL('/mobile-access/health', origin), {\n cache: 'no-store',\n redirect: 'error',\n signal: AbortSignal.timeout(remoteDiagnosticTimeoutMs(origin)),\n })\n const latencyMs = Math.max(0, Math.round(performance.now() - started))\n if (response.status === 429) return { state: 'rate-limited', latencyMs }\n return response.ok ? { state: 'ready', latencyMs } : { state: 'unreachable', latencyMs }\n } catch {\n let fakeIp = false\n try {\n const addresses = await lookup(hostname, { all: true })\n fakeIp = addresses.some(({ address }) => {\n const [first, second] = address.split('.').map(Number)\n return first === 198 && (second === 18 || second === 19)\n })\n } catch {\n // DNS lookup is supplementary; the failed HTTPS probe remains authoritative.\n }\n return { state: 'unreachable', ...(fakeIp ? { fakeIp: true } : {}) }\n }\n}\n\nfunction reportLine(entry: DiagnosticCheck): string {\n return `[${entry.status.toUpperCase()}] ${entry.label}: ${entry.detail}${entry.action === undefined ? '' : ` ${entry.action}`}`\n}\n\n/** Run bounded read-only checks and return a report safe to paste into an issue. */\nexport async function collectConnectionDiagnostics(\n snapshot: DiagnosticSnapshot,\n probes: DiagnosticProbes = {},\n): Promise<ConnectionDiagnostics> {\n const checks: DiagnosticCheck[] = []\n const remoteProbe = snapshot.remote.running && snapshot.remote.state === 'ready' && snapshot.remote.origin !== undefined\n ? (probes.remote ?? defaultRemoteProbe)(snapshot.remote.origin)\n : Promise.resolve<RemoteObservation>({ state: 'not-applicable' })\n const [firewall, remoteObservation] = await Promise.all([\n (probes.firewall ?? defaultFirewallProbe())(snapshot.lan.port),\n remoteProbe,\n ])\n checks.push(check(\n 'versions',\n 'ok',\n 'versions-current',\n '版本兼容',\n `插件 ${DSH_MOBILE_VERSION},DSH ${snapshot.dshVersion},Android App 最低 ${MINIMUM_ANDROID_APP_VERSION}。`,\n ))\n\n if (snapshot.lan.networkError !== undefined) {\n checks.push(check('network', 'error', 'network-unavailable', '局域网网卡', '已保存的网卡当前不可用。', '重新运行 dsh-mobile setup。'))\n } else if (snapshot.lan.configuredInterface !== undefined) {\n const interfaceName = snapshot.lan.interfaceName ?? snapshot.lan.configuredInterface\n checks.push(check(\n 'network',\n 'ok',\n 'network-interface',\n '局域网网卡',\n `正在跟随 ${interfaceName}。`,\n undefined,\n { interfaceName },\n ))\n } else {\n checks.push(check('network', 'info', 'network-fixed', '局域网网卡', '当前使用固定网络配置。'))\n }\n\n if (snapshot.lan.running && snapshot.lan.origin !== undefined) {\n const endpointSuffix = maskLanOrigin(snapshot.lan.origin)\n checks.push(check('lan', 'ok', 'lan-ready', '局域网网关', `已监听 ${endpointSuffix},配对入口可用。`, undefined, { endpointSuffix }))\n } else {\n checks.push(check('lan', 'info', 'lan-off', '局域网网关', '当前未开启。', '需要手机直连时开启局域网访问。'))\n }\n\n if (firewall.state === 'ready') {\n checks.push(check('firewall', 'ok', 'firewall-ready', 'Windows 防火墙', '局域网 TCP 与发现规则已启用。'))\n } else if (firewall.state === 'missing') {\n checks.push(check('firewall', 'warning', 'firewall-missing', 'Windows 防火墙', '未找到完整的局域网放行规则。', '以管理员身份重新运行 dsh-mobile setup。'))\n } else if (firewall.state === 'unknown') {\n checks.push(check('firewall', 'info', 'firewall-unknown', 'Windows 防火墙', '系统未允许插件读取防火墙状态。', '若手机找不到电脑,以管理员身份重新运行 setup。'))\n }\n\n if (!snapshot.remote.running || snapshot.remote.state === 'off') {\n checks.push(check('remote', 'info', 'remote-off', '远程通道', '当前未启用。', undefined, { provider: snapshot.remote.provider }))\n } else if (snapshot.remote.state === 'ready' && snapshot.remote.origin !== undefined) {\n const endpointSuffix = remoteSuffix(snapshot.remote.origin)\n const facts = { provider: snapshot.remote.provider, endpointSuffix, ...(remoteObservation.latencyMs === undefined ? {} : { latencyMs: remoteObservation.latencyMs }) }\n if (remoteObservation.state === 'ready') {\n checks.push(check('remote', 'ok', 'remote-ready', '远程通道', `${snapshot.remote.provider} 公共地址 ${endpointSuffix} 可达,往返约 ${String(remoteObservation.latencyMs ?? 0)} ms。`, undefined, facts))\n } else if (remoteObservation.state === 'rate-limited') {\n checks.push(check('remote', 'warning', 'remote-rate-limited', '远程通道', '公共地址可达,但本次检查观察到服务限流。', '稍后重试;旧会话会按需加载以减少流量。', facts))\n } else if (snapshot.remote.provider === 'tailscale' && remoteObservation.fakeIp === true) {\n checks.push(check(\n 'remote',\n 'error',\n 'remote-fake-ip',\n '远程通道',\n 'Tailscale 地址被当前 VPN 或 DNS 代理接管,但 TLS 链路未建立。',\n '切换 VPN 节点或代理模式;仍失败时改用 cpolar。',\n facts,\n ))\n } else {\n checks.push(check('remote', 'error', 'remote-unreachable', '远程通道', '提供方显示已就绪,但公共地址暂不可达。', '点击“重新连接”;仍失败时检查提供方状态。', facts))\n }\n } else if (snapshot.remote.state === 'starting' || snapshot.remote.state === 'connecting' || snapshot.remote.state === 'needs-login') {\n const needsLogin = snapshot.remote.state === 'needs-login'\n checks.push(check(\n 'remote',\n 'warning',\n needsLogin ? 'remote-needs-login' : 'remote-connecting',\n '远程通道',\n needsLogin ? '等待完成 Tailscale 登录。' : '仍在建立连接。',\n needsLogin ? '返回远程页继续登录。' : '等待片刻后重新检查。',\n { provider: snapshot.remote.provider },\n ))\n } else {\n const controllerCode = snapshot.remote.errorCode ?? snapshot.remote.state\n checks.push(check(\n 'remote',\n 'error',\n 'remote-controller-error',\n '远程通道',\n `连接未建立(${controllerCode})。`,\n REMOTE_ERROR_GUIDANCE[controllerCode] ?? '返回远程页点击“重新连接”。',\n { provider: snapshot.remote.provider, controllerCode },\n ))\n }\n\n checks.push(check(\n 'phone-network',\n 'info',\n 'phone-network-unknown',\n '手机网络',\n '电脑无法判断路由器是否隔离了手机。',\n '局域网仍失败时,确认手机与电脑在同一网络,并关闭访客网络或 AP 隔离。',\n ))\n\n const overall = checks.some(entry => entry.status === 'error')\n ? 'error'\n : checks.some(entry => entry.status === 'warning') ? 'attention' : 'ok'\n const summary = overall === 'ok' ? '连接基础检查正常。' : overall === 'attention' ? '发现需要留意的项目。' : '发现会影响连接的问题。'\n const report = [\n 'DSH Mobile 诊断报告',\n `生成时间: ${new Date().toISOString()}`,\n `版本: plugin=${DSH_MOBILE_VERSION}; dsh=${snapshot.dshVersion}; min-app=${MINIMUM_ANDROID_APP_VERSION}`,\n `LAN: ${snapshot.lan.running ? 'on' : 'off'}; endpoint=${maskLanOrigin(snapshot.lan.origin)}`,\n `Remote: provider=${snapshot.remote.provider}; state=${snapshot.remote.state}; endpoint=${remoteSuffix(snapshot.remote.origin)}`,\n ...checks.map(reportLine),\n ].join('\\n')\n return Object.freeze({\n version: 1,\n generatedAt: Date.now(),\n overall,\n versions: Object.freeze({ plugin: DSH_MOBILE_VERSION, dsh: snapshot.dshVersion, minimumAndroidApp: MINIMUM_ANDROID_APP_VERSION }),\n summary,\n checks: Object.freeze(checks),\n report,\n })\n}\n","/**\n * Instructions handed to the DSH agent when the user runs `/mobile <task>`.\n * The agent edits files under the DSH home; this text is what tells it the\n * layout of the mobile-access customization surface so it does not guess.\n */\nexport const MOBILE_CUSTOMIZATION_GUIDE = `你在为用户定制 DSH Mobile 的手机端。DSH Mobile 是一个把电脑上的 DeepSeek Harness 带到手机浏览器的插件,手机端界面和能力都来自本机文件。\n\n所有改动只允许在 $DSH_HOME/mobile-access/ 目录内进行,绝不修改 DeepSeek Harness 的源码或其他目录。$DSH_HOME 是 DeepSeek Harness 的配置目录(通常为 ~/.dsh),先确认它的实际路径再操作。\n\n手机端的能力分两层,按用户需求选择改动目标:\n\n1. 界面与交互 —— 只改外观和交互,不需要碰电脑的文件或程序:\n - $DSH_HOME/mobile-access/mobile.css:手机端样式\n - $DSH_HOME/mobile-access/mobile.js:手机端脚本,用 window.dshMobile.register(({ root }) => { ... }) 把内容挂载到 root,返回清理函数\n - 保存后手机端几秒内自动应用,无需重启\n\n2. 电脑端能力 —— 手机需要读电脑文件、执行命令或访问硬件时,创建扩展:\n - 目录:$DSH_HOME/mobile-access/extensions/<id>/,id 用小写字母数字和连字符(如 media-remote)\n - extension.json:{\"schemaVersion\":1,\"id\":\"<id>\",\"name\":\"显示名\",\"version\":\"0.1.0\",\"description\":\"说明\"}\n - host.mjs:电脑端 Node.js 代码(可信本地代码,可读写文件、执行命令)。导出默认函数 (api) => { ... },用 api.action('名称', { input, run }) 注册动作、api.route({ method, path, handle }) 注册路由、api.effect(fn) 注册清理\n - mobile.js:手机端脚本,用 window.dshMobile.define({ apiVersion:1, id:'<id>', activate(api) { ... } }),activate 返回清理函数\n - mobile.css:手机端样式(可选)\n - assets/:手机端静态资源(可选)\n - mobile.js 里用 api.host.invoke('动作名', 输入) 调 host.mjs 的 action,api.host.fetch('/路由路径') 调 route,api.host.assetUrl('相对路径') 生成与当前版本绑定的资源地址\n - 也可以先用命令生成模板:dsh plugin --profile web exec dsh-mobile extension create <id> --name \"<名称>\",再在模板上改\n\n安全约束:\n- host.mjs 拥有电脑用户的完整权限,绝不能放入不可信代码,也不要让手机端无条件执行任意命令\n- 所有改动只限 $DSH_HOME/mobile-access/,不要动 DeepSeek Harness 源码\n\n请执行用户需求:外观或交互类改 mobile.css / mobile.js;需要电脑能力的创建或修改扩展。完成后简要说明改了什么、手机端会有什么变化。`\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport { lstat, rm } from 'node:fs/promises'\nimport { isAbsolute, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { MobileAccessControlStore } from './control.js'\nimport type { MobileAccessGateway } from './gateway.js'\nimport { settleRemoteResources, terminateRemoteProcess, type RemoteProviderController } from './remote.js'\n\nconst MAX_PROTOCOL_LINE_BYTES = 16 * 1024\nconst FUNNEL_START_TIMEOUT_MS = 45_000\n\n/** Product-facing states for the independent Tailscale Funnel transport. */\nexport type FunnelState = 'off' | 'unavailable' | 'starting' | 'needs-login' | 'connecting' | 'ready' | 'error'\n\n/** Safe state returned only through the loopback DSH control route. */\nexport interface FunnelStatus {\n readonly enabled: boolean\n readonly state: FunnelState\n readonly origin?: string\n readonly loginUrl?: string\n readonly setupUrl?: string\n readonly errorCode?: string\n}\n\ninterface FunnelEvent {\n readonly version: 1\n readonly type: 'login' | 'ready' | 'serving' | 'error'\n readonly url?: string\n readonly origin?: string\n readonly code?: string\n}\n\n/** Construction inputs for one Funnel lifecycle independent from the LAN gateway. */\nexport interface FunnelControllerOptions {\n readonly store: MobileAccessControlStore\n readonly executable: string\n readonly stateDirectory: string\n readonly hostname: string\n readonly createGateway: (origin: string) => Promise<MobileAccessGateway>\n readonly onStatus?: (status: FunnelStatus) => void\n}\n\nfunction publicStatus(status: FunnelStatus): FunnelStatus {\n return Object.freeze({\n enabled: status.enabled,\n state: status.state,\n ...(status.origin === undefined ? {} : { origin: status.origin }),\n ...(status.loginUrl === undefined ? {} : { loginUrl: status.loginUrl }),\n ...(status.setupUrl === undefined ? {} : { setupUrl: status.setupUrl }),\n ...(status.errorCode === undefined ? {} : { errorCode: status.errorCode }),\n })\n}\n\nconst FUNNEL_SETUP_URLS = new Set([\n 'https://tailscale.com/s/no-funnel',\n 'https://tailscale.com/s/https',\n])\n\nfunction parseSetupUrl(value: unknown): string | undefined {\n if (value === undefined) return undefined\n if (typeof value !== 'string' || value.length > 2048) throw new Error('invalid_sidecar_protocol')\n const url = new URL(value)\n const normalized = url.toString().replace(/\\/$/u, '')\n const officialInteractive = url.protocol === 'https:' && url.hostname === 'login.tailscale.com'\n && url.port === '' && url.username === '' && url.password === ''\n if (!FUNNEL_SETUP_URLS.has(normalized) && !officialInteractive) throw new Error('invalid_sidecar_protocol')\n return officialInteractive ? url.toString() : normalized\n}\n\nfunction parseOrigin(value: unknown): string {\n if (typeof value !== 'string' || value.length > 512) throw new Error('invalid_funnel_origin')\n let url: URL\n try { url = new URL(value) } catch { throw new Error('invalid_funnel_origin') }\n if (url.protocol !== 'https:' || !url.hostname.endsWith('.ts.net') || url.port !== ''\n || url.pathname !== '/' || url.search !== '' || url.hash !== ''\n || url.username !== '' || url.password !== '') throw new Error('invalid_funnel_origin')\n return url.origin\n}\n\n/** Parse one sidecar protocol line while restricting every browser-opened URL. */\nexport function parseFunnelEvent(line: string): FunnelEvent {\n if (Buffer.byteLength(line, 'utf8') === 0 || Buffer.byteLength(line, 'utf8') > MAX_PROTOCOL_LINE_BYTES) {\n throw new Error('invalid_sidecar_protocol')\n }\n let value: unknown\n try { value = JSON.parse(line) as unknown } catch { throw new Error('invalid_sidecar_protocol') }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new Error('invalid_sidecar_protocol')\n const record = value as Record<string, unknown>\n if (record.version !== 1 || typeof record.type !== 'string') throw new Error('invalid_sidecar_protocol')\n if (record.type === 'login') {\n if (typeof record.url !== 'string' || record.url.length > 2048) throw new Error('invalid_sidecar_protocol')\n const url = new URL(record.url)\n if (url.protocol !== 'https:' || url.hostname !== 'login.tailscale.com') throw new Error('invalid_sidecar_protocol')\n return Object.freeze({ version: 1, type: 'login', url: url.toString() })\n }\n if (record.type === 'ready' || record.type === 'serving') {\n return Object.freeze({ version: 1, type: record.type, origin: parseOrigin(record.origin) })\n }\n if (record.type === 'error') {\n if (typeof record.code !== 'string' || !/^[a-z][a-z0-9_]{0,63}$/u.test(record.code)) {\n throw new Error('invalid_sidecar_protocol')\n }\n const setupUrl = parseSetupUrl(record.url)\n return Object.freeze({ version: 1, type: 'error', code: record.code, ...(setupUrl === undefined ? {} : { url: setupUrl }) })\n }\n throw new Error('invalid_sidecar_protocol')\n}\n\nfunction withoutProvisioningSecrets(environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const blocked = new Set(['TS_AUTHKEY', 'TAILSCALE_AUTHKEY', 'TS_OAUTH_CLIENT_SECRET'])\n return Object.fromEntries(Object.entries(environment).filter(([name]) => !blocked.has(name.toUpperCase())))\n}\n\n/** Owns the source-built tsnet sidecar, remote gateway, and persisted remote switch. */\nexport class FunnelController implements RemoteProviderController {\n private enabled = false\n private initialized = false\n private disposed = false\n private child: ChildProcessWithoutNullStreams | undefined\n private gatewayValue: MobileAccessGateway | undefined\n private generation = 0\n private buffer = ''\n private latest: FunnelStatus = publicStatus({ enabled: false, state: 'off' })\n private queue: Promise<void> = Promise.resolve()\n private startTimer: NodeJS.Timeout | undefined\n\n constructor(private readonly options: FunnelControllerOptions) {\n if (!isAbsolute(options.executable) || !isAbsolute(options.stateDirectory)) {\n throw new Error('Funnel paths must be absolute')\n }\n }\n\n /** Restore the remote switch without coupling it to LAN availability. */\n async initialize(): Promise<void> {\n const state = await this.options.store.load()\n this.enabled = state.enabled\n this.initialized = true\n if (this.enabled) await this.start()\n else this.publish({ enabled: false, state: 'off' })\n }\n\n /** Return the currently attached authenticated remote gateway. */\n gateway(): MobileAccessGateway | undefined {\n return this.gatewayValue\n }\n\n /** Return state safe for the local desktop control UI. */\n status(): FunnelStatus {\n return publicStatus(this.latest)\n }\n\n /** Enable or disable Funnel without changing the LAN listener. */\n async setEnabled(enabled: boolean): Promise<FunnelStatus> {\n if (!this.initialized || this.disposed) throw new Error('Funnel controller is unavailable')\n await this.enqueue(async () => {\n if (this.enabled === enabled && (enabled === false || this.child !== undefined)) return\n if (!enabled) await this.stop()\n this.enabled = enabled\n await this.options.store.save({ version: 1, enabled })\n if (enabled) await this.start()\n else this.publish({ enabled: false, state: 'off' })\n })\n return this.status()\n }\n\n /** Restart a failed or interrupted Funnel session while retaining sign-in state. */\n async reconnect(): Promise<FunnelStatus> {\n if (!this.initialized || this.disposed) throw new Error('Funnel controller is unavailable')\n await this.enqueue(async () => {\n if (!this.enabled) {\n this.enabled = true\n await this.options.store.save({ version: 1, enabled: true })\n }\n await this.stop()\n await this.start()\n })\n return this.status()\n }\n\n /** Disable Funnel and remove only its private Tailscale node state. */\n async reset(): Promise<FunnelStatus> {\n if (!this.initialized || this.disposed) throw new Error('Funnel controller is unavailable')\n await this.enqueue(async () => {\n await this.stop()\n this.enabled = false\n await this.options.store.save({ version: 1, enabled: false })\n await rm(resolve(this.options.stateDirectory), { recursive: true, force: true })\n this.publish({ enabled: false, state: 'off' })\n })\n return this.status()\n }\n\n /** Stop all remote resources without modifying the remembered switch. */\n async close(): Promise<void> {\n if (this.disposed) return\n this.disposed = true\n await this.enqueue(() => this.stop())\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const task = this.queue.then(operation, operation)\n this.queue = task.then(() => undefined, () => undefined)\n return task\n }\n\n private publish(status: FunnelStatus): void {\n this.latest = publicStatus(status)\n try { this.options.onStatus?.(this.status()) } catch { /* UI observation cannot own runtime state. */ }\n }\n\n private async start(): Promise<void> {\n const generation = ++this.generation\n let entry\n try { entry = await lstat(this.options.executable) } catch {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'component_missing' })\n return\n }\n if (!entry.isFile() || entry.isSymbolicLink()) {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'component_invalid' })\n return\n }\n this.buffer = ''\n this.publish({ enabled: true, state: 'starting' })\n const child = spawn(this.options.executable, [\n '--state-dir', resolve(this.options.stateDirectory),\n '--hostname', this.options.hostname,\n ], {\n env: withoutProvisioningSecrets(process.env),\n shell: false,\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true,\n })\n this.child = child\n this.clearStartTimer()\n this.startTimer = setTimeout(() => {\n void this.enqueue(() => this.failGeneration(generation, 'funnel_start_timeout'))\n }, FUNNEL_START_TIMEOUT_MS)\n this.startTimer.unref()\n child.stderr.resume()\n child.stdout.setEncoding('utf8')\n child.stdout.on('data', chunk => { this.consume(generation, String(chunk)) })\n child.once('error', () => {\n void this.enqueue(() => this.failGeneration(generation, 'sidecar_launch_failed'))\n })\n child.once('close', code => {\n if (generation !== this.generation || this.child !== child) return\n this.child = undefined\n if (this.enabled) {\n void this.enqueue(() => this.failGeneration(generation, code === 0 ? 'sidecar_stopped' : 'sidecar_exited'))\n }\n })\n }\n\n private consume(generation: number, chunk: string): void {\n if (generation !== this.generation) return\n this.buffer += chunk\n if (Buffer.byteLength(this.buffer, 'utf8') > MAX_PROTOCOL_LINE_BYTES && !this.buffer.includes('\\n')) {\n void this.enqueue(() => this.failGeneration(generation, 'invalid_sidecar_protocol'))\n return\n }\n while (true) {\n const newline = this.buffer.indexOf('\\n')\n if (newline < 0) return\n const line = this.buffer.slice(0, newline).replace(/\\r$/u, '')\n this.buffer = this.buffer.slice(newline + 1)\n let event: FunnelEvent\n try { event = parseFunnelEvent(line) } catch {\n void this.enqueue(() => this.failGeneration(generation, 'invalid_sidecar_protocol'))\n return\n }\n void this.enqueue(() => this.handleEvent(generation, event))\n }\n }\n\n private async handleEvent(generation: number, event: FunnelEvent): Promise<void> {\n if (generation !== this.generation || !this.enabled) return\n this.clearStartTimer()\n if (event.type === 'login') {\n this.publish({ enabled: true, state: 'needs-login', loginUrl: event.url! })\n return\n }\n if (event.type === 'error') {\n await this.failGeneration(generation, event.code ?? 'funnel_failed', event.url)\n return\n }\n const origin = parseOrigin(event.origin)\n if (event.type === 'ready') {\n let gateway: MobileAccessGateway\n try {\n await this.gatewayValue?.close()\n this.gatewayValue = undefined\n gateway = await this.options.createGateway(origin)\n } catch {\n await this.failGeneration(generation, 'gateway_start_failed')\n return\n }\n if (generation !== this.generation || !this.enabled) {\n await gateway.close()\n return\n }\n this.gatewayValue = gateway\n const address = gateway.address()\n const child = this.child\n if (child === undefined) {\n await this.failGeneration(generation, 'sidecar_stopped')\n return\n }\n child.stdin.write(\n `${JSON.stringify({ version: 1, type: 'serve', target: `http://${address.host}:${String(address.port)}` })}\\n`,\n error => {\n if (error !== null && error !== undefined) {\n void this.enqueue(() => this.failGeneration(generation, 'control_channel_failed'))\n }\n },\n )\n this.publish({ enabled: true, state: 'connecting', origin })\n return\n }\n this.publish({ enabled: true, state: 'ready', origin })\n }\n\n private async failGeneration(generation: number, code: string, setupUrl?: string): Promise<void> {\n if (generation !== this.generation) return\n await this.stopProcessAndGateway()\n if (this.enabled) this.publish({ enabled: true, state: 'error', errorCode: code, ...(setupUrl === undefined ? {} : { setupUrl }) })\n }\n\n private async stop(): Promise<void> {\n ++this.generation\n await this.stopProcessAndGateway()\n }\n\n private async stopProcessAndGateway(): Promise<void> {\n this.clearStartTimer()\n const child = this.child\n this.child = undefined\n const gateway = this.gatewayValue\n this.gatewayValue = undefined\n await settleRemoteResources([\n async () => {\n child?.stdin.end()\n if (child !== undefined && child.exitCode === null) await terminateRemoteProcess(child)\n },\n () => gateway?.close(),\n ], 'Funnel resource cleanup failed')\n }\n\n private clearStartTimer(): void {\n if (this.startTimer === undefined) return\n clearTimeout(this.startTimer)\n this.startTimer = undefined\n }\n}\n\n/** Locate the current platform's bundled Funnel executable, with one local development override. */\nexport function funnelExecutable(importMetaUrl: string, environment: NodeJS.ProcessEnv = process.env): string {\n const override = environment.DSH_MOBILE_FUNNEL_SIDECAR\n if (override !== undefined) {\n if (!isAbsolute(override)) throw new Error('DSH_MOBILE_FUNNEL_SIDECAR must be an absolute path')\n return resolve(override)\n }\n const suffix = process.platform === 'win32' ? '.exe' : ''\n const file = `dsh-mobile-funnel-${process.platform}-${process.arch}${suffix}`\n return resolve(fileURLToPath(new URL(`../bin/${file}`, importMetaUrl)))\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport { lstat } from 'node:fs/promises'\nimport { createServer, type Server } from 'node:net'\nimport { isAbsolute, resolve } from 'node:path'\nimport type { MobileAccessControlStore } from './control.js'\nimport type { MobileAccessGateway } from './gateway.js'\nimport { settleRemoteResources, terminateRemoteProcess, type RemoteProviderController } from './remote.js'\n\nconst MAX_LOG_BUFFER_BYTES = 64 * 1024\nconst START_TIMEOUT_MS = 45_000\nconst CPOLAR_HOST_SUFFIXES = Object.freeze(['.cpolar.cn', '.cpolar.io', '.cpolar.top', '.cpolar.com'])\n\n/** Product-facing states for the optional cpolar remote transport. */\nexport type CpolarState = 'off' | 'unavailable' | 'starting' | 'connecting' | 'ready' | 'error'\n\n/** Safe cpolar state returned only through the loopback DSH control route. */\nexport interface CpolarStatus {\n readonly enabled: boolean\n readonly state: CpolarState\n readonly origin?: string\n readonly errorCode?: string\n}\n\n/** Inputs for one cpolar process and its authenticated DSH gateway. */\nexport interface CpolarControllerOptions {\n readonly store: MobileAccessControlStore\n readonly executable: string\n readonly configFile: string\n readonly region?: string\n readonly createGateway: (origin: string, listenPort: number) => Promise<MobileAccessGateway>\n readonly onStatus?: (status: CpolarStatus) => void\n}\n\ninterface PortReservation {\n readonly port: number\n readonly release: () => Promise<void>\n}\n\nfunction publicStatus(status: CpolarStatus): CpolarStatus {\n return Object.freeze({\n enabled: status.enabled,\n state: status.state,\n ...(status.origin === undefined ? {} : { origin: status.origin }),\n ...(status.errorCode === undefined ? {} : { errorCode: status.errorCode }),\n })\n}\n\nfunction isCpolarHost(hostname: string): boolean {\n return CPOLAR_HOST_SUFFIXES.some(suffix => hostname.endsWith(suffix))\n}\n\n/** Extract a validated public HTTPS origin from one cpolar log line. */\nexport function parseCpolarOrigin(line: string): string | undefined {\n if (!line.includes('Tunnel established at ')) return undefined\n const match = /Tunnel established at (https:\\/\\/[^\"\\s]+)/u.exec(line)\n if (match === null) return undefined\n let url: URL\n try { url = new URL(match[1]!) } catch { throw new Error('invalid_cpolar_origin') }\n if (url.protocol !== 'https:' || url.port !== '' || !isCpolarHost(url.hostname)\n || url.pathname !== '/' || url.search !== '' || url.hash !== ''\n || url.username !== '' || url.password !== '') throw new Error('invalid_cpolar_origin')\n return url.origin\n}\n\nasync function reserveLoopbackPort(): Promise<PortReservation> {\n const server: Server = createServer(socket => { socket.destroy() })\n await new Promise<void>((resolveListen, reject) => {\n server.once('error', reject)\n server.listen(0, '127.0.0.1', () => {\n server.off('error', reject)\n resolveListen()\n })\n })\n const address = server.address()\n if (address === null || typeof address === 'string') {\n server.close()\n throw new Error('cpolar_port_reservation_failed')\n }\n let released = false\n return {\n port: address.port,\n release: async () => {\n if (released) return\n released = true\n await new Promise<void>(resolveClose => { server.close(() => resolveClose()) })\n },\n }\n}\n\nfunction withoutProxyEnvironment(environment: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const blocked = new Set(['HTTP_PROXY', 'HTTPS_PROXY', 'ALL_PROXY', 'NO_PROXY'])\n return Object.fromEntries(Object.entries(environment).filter(([name]) => !blocked.has(name.toUpperCase())))\n}\n\n/** Owns an installed cpolar client and a provider-specific DSH remote gateway. */\nexport class CpolarController implements RemoteProviderController {\n private enabled = false\n private initialized = false\n private disposed = false\n private child: ChildProcessWithoutNullStreams | undefined\n private gatewayValue: MobileAccessGateway | undefined\n private reservation: PortReservation | undefined\n private generation = 0\n private buffer = ''\n private latest: CpolarStatus = publicStatus({ enabled: false, state: 'off' })\n private queue: Promise<void> = Promise.resolve()\n private startupTimer: NodeJS.Timeout | undefined\n\n constructor(private readonly options: CpolarControllerOptions) {\n if (!isAbsolute(options.executable) || !isAbsolute(options.configFile)) {\n throw new Error('cpolar paths must be absolute')\n }\n if (options.region !== undefined && !/^[a-z][a-z0-9_]{0,31}$/u.test(options.region)) {\n throw new Error('cpolar region is invalid')\n }\n }\n\n /** Restore the remembered cpolar switch independently from LAN and Funnel state. */\n async initialize(): Promise<void> {\n const state = await this.options.store.load()\n this.enabled = state.enabled\n this.initialized = true\n if (this.enabled) await this.start()\n else this.publish({ enabled: false, state: 'off' })\n }\n\n /** Return the active cpolar-backed DSH gateway. */\n gateway(): MobileAccessGateway | undefined {\n return this.gatewayValue\n }\n\n /** Return state safe for the desktop control UI. */\n status(): CpolarStatus {\n return publicStatus(this.latest)\n }\n\n /** Enable or disable cpolar without changing LAN or Tailscale state. */\n async setEnabled(enabled: boolean): Promise<CpolarStatus> {\n if (!this.initialized || this.disposed) throw new Error('cpolar controller is unavailable')\n await this.enqueue(async () => {\n if (this.enabled === enabled && (enabled === false || this.child !== undefined)) return\n if (!enabled) await this.stop()\n this.enabled = enabled\n await this.options.store.save({ version: 1, enabled })\n if (enabled) await this.start()\n else this.publish({ enabled: false, state: 'off' })\n })\n return this.status()\n }\n\n /** Restart cpolar while retaining its account configuration and DSH device store. */\n async reconnect(): Promise<CpolarStatus> {\n if (!this.initialized || this.disposed) throw new Error('cpolar controller is unavailable')\n await this.enqueue(async () => {\n if (!this.enabled) {\n this.enabled = true\n await this.options.store.save({ version: 1, enabled: true })\n }\n await this.stop()\n await this.start()\n })\n return this.status()\n }\n\n /** Disable cpolar without modifying the user's cpolar account or global tunnels. */\n async reset(): Promise<CpolarStatus> {\n if (!this.initialized || this.disposed) throw new Error('cpolar controller is unavailable')\n await this.enqueue(async () => {\n await this.stop()\n this.enabled = false\n await this.options.store.save({ version: 1, enabled: false })\n this.publish({ enabled: false, state: 'off' })\n })\n return this.status()\n }\n\n /** Stop owned resources without changing the remembered switch. */\n async close(): Promise<void> {\n if (this.disposed) return\n this.disposed = true\n await this.enqueue(() => this.stop())\n }\n\n private enqueue(operation: () => Promise<void>): Promise<void> {\n const task = this.queue.then(operation, operation)\n this.queue = task.then(() => undefined, () => undefined)\n return task\n }\n\n private publish(status: CpolarStatus): void {\n this.latest = publicStatus(status)\n try { this.options.onStatus?.(this.status()) } catch { /* UI observation cannot own runtime state. */ }\n }\n\n private async start(): Promise<void> {\n const generation = ++this.generation\n let executableEntry\n try { executableEntry = await lstat(this.options.executable) } catch {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'cpolar_component_missing' })\n return\n }\n if (!executableEntry.isFile() || executableEntry.isSymbolicLink()) {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'cpolar_component_invalid' })\n return\n }\n let configEntry\n try { configEntry = await lstat(this.options.configFile) } catch {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'cpolar_config_missing' })\n return\n }\n if (!configEntry.isFile() || configEntry.isSymbolicLink()) {\n this.publish({ enabled: true, state: 'unavailable', errorCode: 'cpolar_config_invalid' })\n return\n }\n\n let reservation: PortReservation\n try { reservation = await reserveLoopbackPort() } catch {\n this.publish({ enabled: true, state: 'error', errorCode: 'cpolar_port_unavailable' })\n return\n }\n this.reservation = reservation\n this.buffer = ''\n this.publish({ enabled: true, state: 'starting' })\n const args = [\n 'http',\n `-config=${resolve(this.options.configFile)}`,\n `-region=${this.options.region ?? 'cn'}`,\n '-inspect-addr=false',\n '-redirect-https=true',\n '-log=stdout',\n '-log-level=INFO',\n String(reservation.port),\n ]\n const child = spawn(this.options.executable, args, {\n env: withoutProxyEnvironment(process.env),\n shell: false,\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true,\n })\n this.child = child\n child.stdout.setEncoding('utf8')\n child.stderr.setEncoding('utf8')\n child.stdout.on('data', chunk => { this.consume(generation, String(chunk)) })\n child.stderr.on('data', chunk => { this.consume(generation, String(chunk)) })\n child.once('error', () => { void this.enqueue(() => this.failGeneration(generation, 'cpolar_launch_failed')) })\n child.once('close', code => {\n if (generation !== this.generation || this.child !== child) return\n this.child = undefined\n if (this.enabled) void this.enqueue(() => this.failGeneration(generation, code === 0 ? 'cpolar_stopped' : 'cpolar_exited'))\n })\n this.startupTimer = setTimeout(() => {\n void this.enqueue(() => this.failGeneration(generation, 'cpolar_start_timeout'))\n }, START_TIMEOUT_MS)\n this.startupTimer.unref()\n }\n\n private consume(generation: number, chunk: string): void {\n if (generation !== this.generation) return\n this.buffer += chunk\n if (Buffer.byteLength(this.buffer, 'utf8') > MAX_LOG_BUFFER_BYTES && !this.buffer.includes('\\n')) {\n void this.enqueue(() => this.failGeneration(generation, 'cpolar_invalid_output'))\n return\n }\n while (true) {\n const newline = this.buffer.indexOf('\\n')\n if (newline < 0) return\n const line = this.buffer.slice(0, newline).replace(/\\r$/u, '')\n this.buffer = this.buffer.slice(newline + 1)\n let origin: string | undefined\n try { origin = parseCpolarOrigin(line) } catch {\n void this.enqueue(() => this.failGeneration(generation, 'cpolar_invalid_origin'))\n return\n }\n if (origin !== undefined) void this.enqueue(() => this.attachGateway(generation, origin))\n }\n }\n\n private async attachGateway(generation: number, origin: string): Promise<void> {\n if (generation !== this.generation || !this.enabled || this.gatewayValue !== undefined) return\n const reservation = this.reservation\n if (reservation === undefined) return\n this.publish({ enabled: true, state: 'connecting', origin })\n await reservation.release()\n if (this.reservation === reservation) this.reservation = undefined\n let gateway: MobileAccessGateway\n try { gateway = await this.options.createGateway(origin, reservation.port) } catch {\n await this.failGeneration(generation, 'gateway_start_failed')\n return\n }\n if (generation !== this.generation || !this.enabled) {\n await gateway.close()\n return\n }\n this.gatewayValue = gateway\n if (this.startupTimer !== undefined) clearTimeout(this.startupTimer)\n this.startupTimer = undefined\n this.publish({ enabled: true, state: 'ready', origin })\n }\n\n private async failGeneration(generation: number, code: string): Promise<void> {\n if (generation !== this.generation) return\n await this.stopProcessAndGateway()\n if (this.enabled) this.publish({ enabled: true, state: 'error', errorCode: code })\n }\n\n private async stop(): Promise<void> {\n ++this.generation\n await this.stopProcessAndGateway()\n }\n\n private async stopProcessAndGateway(): Promise<void> {\n if (this.startupTimer !== undefined) clearTimeout(this.startupTimer)\n this.startupTimer = undefined\n const reservation = this.reservation\n this.reservation = undefined\n const child = this.child\n this.child = undefined\n const gateway = this.gatewayValue\n this.gatewayValue = undefined\n await settleRemoteResources([\n () => reservation?.release(),\n () => child !== undefined && child.exitCode === null ? terminateRemoteProcess(child) : undefined,\n () => gateway?.close(),\n ], 'cpolar resource cleanup failed')\n }\n}\n","import { createHash, randomBytes } from 'node:crypto'\nimport { execFile } from 'node:child_process'\nimport {\n chmod,\n copyFile,\n lstat,\n mkdir,\n mkdtemp,\n readFile,\n readdir,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'\nimport { restrictPrivateFile } from './private-file.js'\n\n/** Pinned cpolar Windows component fetched only after an explicit user action. */\nexport const CPOLAR_COMPONENT_RELEASE = Object.freeze({\n version: '3.3.18',\n platform: 'win32',\n arch: 'x64',\n downloadUrl: 'https://www.cpolar.com/static/downloads/releases/3.3.18/cpolar-stable-windows-amd64-setup.zip',\n downloadBytes: 7_603_505,\n downloadSha256: 'fb8cf60289058ee26079f995d2eeea0b21768a742d90c93015afe96e83428830',\n executableBytes: 19_637_680,\n executableSha256: 'b2d865ee505e842d22ceca5493a872efa893a79b079a7a8ee2bd3aa5343a5c41',\n downloadPage: 'https://www.cpolar.com/download',\n signupUrl: 'https://dashboard.cpolar.com/signup',\n dashboardUrl: 'https://dashboard.cpolar.com/auth',\n termsUrl: 'https://www.cpolar.com/tos',\n})\n\n/** Public, credential-free description of the managed cpolar component. */\nexport interface CpolarComponentStatus {\n readonly supported: boolean\n readonly installed: boolean\n readonly configured: boolean\n readonly version: string\n readonly downloadBytes: number\n readonly installedBytes: number\n readonly sourceUrl: string\n readonly downloadPage: string\n readonly signupUrl: string\n readonly dashboardUrl: string\n readonly termsUrl: string\n readonly storagePath: string\n readonly errorCode?: string\n}\n\ninterface CpolarComponentManagerOptions {\n readonly stateDirectory: string\n readonly platform?: NodeJS.Platform\n readonly arch?: string\n readonly fetchArtifact?: (url: string, signal: AbortSignal) => Promise<Uint8Array>\n readonly extractArtifact?: (archive: string, destination: string) => Promise<void>\n}\n\nfunction inside(parent: string, child: string): boolean {\n const candidate = relative(parent, child)\n return candidate !== '' && !candidate.startsWith('..') && !isAbsolute(candidate)\n}\n\nasync function sha256(file: string): Promise<string> {\n return createHash('sha256').update(await readFile(file)).digest('hex')\n}\n\nasync function regularFile(file: string, expectedBytes?: number): Promise<boolean> {\n try {\n const stat = await lstat(file)\n return stat.isFile() && !stat.isSymbolicLink() && (expectedBytes === undefined || stat.size === expectedBytes)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false\n throw error\n }\n}\n\nasync function run(file: string, args: readonly string[]): Promise<void> {\n await new Promise<void>((resolveRun, reject) => {\n execFile(file, [...args], { windowsHide: true, timeout: 120_000 }, (error) => {\n if (error === null) resolveRun()\n else reject(error)\n })\n })\n}\n\nasync function defaultFetchArtifact(url: string, signal: AbortSignal): Promise<Uint8Array> {\n const response = await fetch(url, { redirect: 'error', signal })\n if (!response.ok) throw new Error(`cpolar_download_http_${String(response.status)}`)\n const length = Number(response.headers.get('content-length'))\n if (Number.isFinite(length) && length !== CPOLAR_COMPONENT_RELEASE.downloadBytes) {\n throw new Error('cpolar_download_size_mismatch')\n }\n const bytes = new Uint8Array(await response.arrayBuffer())\n if (bytes.byteLength !== CPOLAR_COMPONENT_RELEASE.downloadBytes) {\n throw new Error('cpolar_download_size_mismatch')\n }\n return bytes\n}\n\nasync function defaultExtractArtifact(archive: string, destination: string): Promise<void> {\n if (process.platform !== 'win32') throw new Error('cpolar_component_unsupported')\n const unpacked = join(destination, 'archive')\n const administrative = join(destination, 'administrative')\n await mkdir(unpacked, { recursive: true, mode: 0o700 })\n await mkdir(administrative, { recursive: true, mode: 0o700 })\n await run('tar.exe', ['-xf', archive, '-C', unpacked])\n const archiveEntries = await readdir(unpacked, { recursive: true })\n const msiRelative = archiveEntries.find(entry => entry.toLowerCase().endsWith('.msi'))\n if (msiRelative === undefined) throw new Error('cpolar_installer_missing')\n await run('msiexec.exe', ['/a', join(unpacked, msiRelative), '/qn', `TARGETDIR=${administrative}`])\n const installedEntries = await readdir(administrative, { recursive: true })\n const executableRelative = installedEntries.find(entry => basename(entry).toLowerCase() === 'cpolar.exe')\n if (executableRelative === undefined) throw new Error('cpolar_executable_missing')\n await copyFile(join(administrative, executableRelative), join(destination, 'cpolar.exe'))\n}\n\n/** Validate a cpolar Authtoken before it crosses the durable-file boundary. */\nexport function validateCpolarAuthtoken(value: unknown): string {\n if (typeof value !== 'string' || value.length < 20 || value.length > 512\n || /[\\s\\u0000-\\u001f\\u007f]/u.test(value)) {\n throw new Error('cpolar_authtoken_invalid')\n }\n return value\n}\n\n/** Owns the optional cpolar binary and account configuration inside DSH Mobile state. */\nexport class CpolarComponentManager {\n readonly executable: string\n readonly configFile: string\n readonly componentRoot: string\n readonly componentStorage: string\n readonly stateRoot: string\n readonly logRoot: string\n private readonly stagingRoot: string\n private readonly platform: NodeJS.Platform\n private readonly arch: string\n private readonly fetchArtifact: (url: string, signal: AbortSignal) => Promise<Uint8Array>\n private readonly extractArtifact: (archive: string, destination: string) => Promise<void>\n private installed = false\n private configured = false\n private errorCode: string | undefined\n private queue: Promise<void> = Promise.resolve()\n\n constructor(options: CpolarComponentManagerOptions) {\n const stateDirectory = resolve(options.stateDirectory)\n if (!isAbsolute(stateDirectory)) throw new Error('cpolar state directory must be absolute')\n this.platform = options.platform ?? process.platform\n this.arch = options.arch ?? process.arch\n this.componentRoot = join(stateDirectory, 'components', 'cpolar')\n this.componentStorage = join(this.componentRoot, CPOLAR_COMPONENT_RELEASE.version)\n this.executable = join(this.componentStorage, 'cpolar.exe')\n this.stateRoot = join(stateDirectory, 'state', 'cpolar')\n this.configFile = join(this.stateRoot, 'cpolar.yml')\n this.logRoot = join(stateDirectory, 'logs', 'cpolar')\n this.stagingRoot = join(stateDirectory, 'staging', 'cpolar')\n for (const child of [this.componentRoot, this.componentStorage, this.stateRoot, this.logRoot, this.stagingRoot]) {\n if (!inside(stateDirectory, child)) throw new Error('cpolar component path escaped its state directory')\n }\n this.fetchArtifact = options.fetchArtifact ?? defaultFetchArtifact\n this.extractArtifact = options.extractArtifact ?? defaultExtractArtifact\n }\n\n /** Inspect the managed binary and configuration without using global cpolar state. */\n async initialize(): Promise<void> {\n this.installed = await regularFile(this.executable, CPOLAR_COMPONENT_RELEASE.executableBytes)\n if (this.installed && await sha256(this.executable) !== CPOLAR_COMPONENT_RELEASE.executableSha256) {\n this.installed = false\n this.errorCode = 'cpolar_component_invalid'\n }\n this.configured = await regularFile(this.configFile)\n if (this.configured) await restrictPrivateFile(this.configFile)\n }\n\n /** Return a safe status that never includes the account token. */\n status(): CpolarComponentStatus {\n return Object.freeze({\n supported: this.platform === CPOLAR_COMPONENT_RELEASE.platform && this.arch === CPOLAR_COMPONENT_RELEASE.arch,\n installed: this.installed,\n configured: this.configured,\n version: CPOLAR_COMPONENT_RELEASE.version,\n downloadBytes: CPOLAR_COMPONENT_RELEASE.downloadBytes,\n installedBytes: CPOLAR_COMPONENT_RELEASE.executableBytes,\n sourceUrl: CPOLAR_COMPONENT_RELEASE.downloadUrl,\n downloadPage: CPOLAR_COMPONENT_RELEASE.downloadPage,\n signupUrl: CPOLAR_COMPONENT_RELEASE.signupUrl,\n dashboardUrl: CPOLAR_COMPONENT_RELEASE.dashboardUrl,\n termsUrl: CPOLAR_COMPONENT_RELEASE.termsUrl,\n storagePath: this.componentRoot,\n ...(this.errorCode === undefined ? {} : { errorCode: this.errorCode }),\n })\n }\n\n /** Download, verify, and administratively extract cpolar after explicit confirmation. */\n install(): Promise<CpolarComponentStatus> {\n return this.enqueue(async () => {\n if (this.platform !== CPOLAR_COMPONENT_RELEASE.platform || this.arch !== CPOLAR_COMPONENT_RELEASE.arch) {\n throw new Error('cpolar_component_unsupported')\n }\n await mkdir(this.stagingRoot, { recursive: true, mode: 0o700 })\n const staging = await mkdtemp(join(this.stagingRoot, 'install-'))\n try {\n const controller = new AbortController()\n const timeout = setTimeout(() => { controller.abort() }, 120_000)\n timeout.unref()\n let bytes: Uint8Array\n try { bytes = await this.fetchArtifact(CPOLAR_COMPONENT_RELEASE.downloadUrl, controller.signal) } finally { clearTimeout(timeout) }\n const digest = createHash('sha256').update(bytes).digest('hex')\n if (digest !== CPOLAR_COMPONENT_RELEASE.downloadSha256) throw new Error('cpolar_download_hash_mismatch')\n const archive = join(staging, 'cpolar.zip')\n await writeFile(archive, bytes, { flag: 'wx', mode: 0o600 })\n await this.extractArtifact(archive, staging)\n const extracted = join(staging, 'cpolar.exe')\n if (!await regularFile(extracted, CPOLAR_COMPONENT_RELEASE.executableBytes)\n || await sha256(extracted) !== CPOLAR_COMPONENT_RELEASE.executableSha256) {\n throw new Error('cpolar_executable_hash_mismatch')\n }\n const candidate = join(this.componentRoot, `.install-${randomBytes(12).toString('hex')}`)\n await mkdir(candidate, { recursive: true, mode: 0o700 })\n await copyFile(extracted, join(candidate, 'cpolar.exe'))\n await chmod(join(candidate, 'cpolar.exe'), 0o700)\n await rm(this.componentStorage, { recursive: true, force: true })\n await rename(candidate, this.componentStorage)\n this.installed = true\n this.errorCode = undefined\n } finally {\n await rm(staging, { recursive: true, force: true })\n }\n })\n }\n\n /** Store only the cpolar token in a private, self-update-disabled configuration. */\n configure(authtoken: unknown): Promise<CpolarComponentStatus> {\n return this.enqueue(async () => {\n const token = validateCpolarAuthtoken(authtoken)\n await mkdir(this.stateRoot, { recursive: true, mode: 0o700 })\n const temporary = join(this.stateRoot, `.cpolar.${randomBytes(12).toString('hex')}.tmp`)\n const body = `authtoken: ${JSON.stringify(token)}\\nconsole_ui: false\\nupdate: false\\ninspect_db_size: -1\\n`\n try {\n await writeFile(temporary, body, { encoding: 'utf8', flag: 'wx', mode: 0o600 })\n await rename(temporary, this.configFile)\n await restrictPrivateFile(this.configFile)\n } catch (error) {\n await rm(temporary, { force: true })\n throw error\n }\n this.configured = true\n this.errorCode = undefined\n })\n }\n\n /** Remove every cpolar file owned by DSH Mobile without touching global state. */\n purge(): Promise<CpolarComponentStatus> {\n return this.enqueue(async () => {\n await Promise.all([\n rm(this.componentRoot, { recursive: true, force: true }),\n rm(this.stateRoot, { recursive: true, force: true }),\n rm(this.logRoot, { recursive: true, force: true }),\n rm(this.stagingRoot, { recursive: true, force: true }),\n ])\n this.installed = false\n this.configured = false\n this.errorCode = undefined\n })\n }\n\n private enqueue(operation: () => Promise<void>): Promise<CpolarComponentStatus> {\n const task = this.queue.then(operation, operation)\n this.queue = task.then(() => undefined, () => undefined)\n return task.then(() => this.status())\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process'\nimport { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { createRequire } from 'node:module'\nimport { DSH_MOBILE_VERSION } from './version.js'\n\nconst PACKAGE_NAME = 'dsh-mobile'\nconst NPM_LATEST_URL = 'https://registry.npmjs.org/dsh-mobile/latest'\nconst GITHUB_LATEST_URL = 'https://github.com/saya-ch/dsh-mobile/releases/latest'\nconst GITHUB_RELEASES_URL = 'https://github.com/saya-ch/dsh-mobile/releases'\nconst STATUS_CACHE_MS = 10 * 60_000\nconst REQUEST_TIMEOUT_MS = 8_000\nconst UPDATE_TIMEOUT_MS = 120_000\nconst UPDATE_TERMINATION_GRACE_MS = 1_500\n\nconst NUMERIC_VERSION_IDENTIFIER = '(?:0|[1-9]\\\\d*)'\nconst WILDCARD_VERSION_IDENTIFIER = '(?:[xX*])'\nconst PARTIAL_VERSION = `(?:${WILDCARD_VERSION_IDENTIFIER}|${NUMERIC_VERSION_IDENTIFIER}(?:\\\\.(?:${WILDCARD_VERSION_IDENTIFIER}|${NUMERIC_VERSION_IDENTIFIER}(?:\\\\.(?:${WILDCARD_VERSION_IDENTIFIER}|${NUMERIC_VERSION_IDENTIFIER}))?))?)`\nconst FULL_VERSION = `${NUMERIC_VERSION_IDENTIFIER}\\\\.${NUMERIC_VERSION_IDENTIFIER}\\\\.${NUMERIC_VERSION_IDENTIFIER}(?:-[0-9A-Za-z-]+(?:\\\\.[0-9A-Za-z-]+)*)?(?:\\\\+[0-9A-Za-z-]+(?:\\\\.[0-9A-Za-z-]+)*)?`\nconst RANGE_VERSION = `(?:${FULL_VERSION}|${PARTIAL_VERSION})`\nconst COMPARATOR = new RegExp(`^(?:<=|>=|<|>|=|~|\\\\^)?${RANGE_VERSION}$`, 'u')\nconst HYPHEN_RANGE = new RegExp(`^${RANGE_VERSION} +[-] +${RANGE_VERSION}$`, 'u')\nconst DIST_TAG = /^[A-Za-z][A-Za-z0-9._-]{0,127}$/u\n\ninterface Semver {\n readonly core: readonly [number, number, number]\n readonly prerelease: readonly (number | string)[]\n}\n\n/** Release information safe to return through the loopback administration API. */\nexport interface PluginReleaseStatus {\n readonly installedVersion: string\n readonly latestVersion?: string\n readonly updateAvailable: boolean\n readonly updateSupported: boolean\n readonly androidVersion?: string\n readonly androidDownloadUrl: string\n}\n\n/** Result returned after the profile package has been replaced successfully. */\nexport interface PluginUpdateResult {\n readonly installedVersion: string\n readonly restartRequired: true\n}\n\ninterface PluginReleaseManagerOptions {\n readonly profileDirectory: string\n readonly installedVersion?: string\n readonly fetch?: typeof globalThis.fetch\n readonly runUpdate?: (profileDirectory: string, version: string) => Promise<void>\n readonly readInstalledVersion?: (profileDirectory: string) => Promise<string | undefined>\n readonly now?: () => number\n readonly updateProcess?: PnpmUpdateRuntime\n}\n\ninterface UpdateProcessExit {\n readonly code: number | null\n readonly signal: NodeJS.Signals | null\n}\n\ninterface UpdateProcessRequest {\n readonly command: string\n readonly args: readonly string[]\n readonly cwd: string\n readonly detached: boolean\n readonly platform: NodeJS.Platform\n readonly shell: false\n}\n\ninterface ManagedUpdateProcess {\n readonly completion: Promise<UpdateProcessExit>\n readonly stderr?: NodeJS.ReadableStream\n terminateTree(): Promise<void>\n}\n\ninterface UpdateDeadline {\n readonly promise: Promise<void>\n cancel(): void\n}\n\ninterface PnpmUpdateRuntime {\n readonly platform?: NodeJS.Platform\n readonly timeoutMs?: number\n readonly windowsCommandInterpreter?: string\n readonly start?: (request: UpdateProcessRequest) => ManagedUpdateProcess\n readonly deadline?: (timeoutMs: number) => UpdateDeadline\n}\n\nfunction parseSemver(value: string): Semver | undefined {\n const match = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/u.exec(value)\n if (match === null) return undefined\n const core = [Number(match[1]), Number(match[2]), Number(match[3])] as const\n if (core.some(part => !Number.isSafeInteger(part))) return undefined\n const prerelease = match[4] === undefined\n ? []\n : match[4].split('.').map((part): number | string => /^\\d+$/u.test(part) ? Number(part) : part)\n if (prerelease.some(part => typeof part === 'number' && !Number.isSafeInteger(part))) return undefined\n return Object.freeze({ core, prerelease: Object.freeze(prerelease) })\n}\n\n/** Compare two strict SemVer strings, including prerelease precedence. */\nexport function comparePluginVersions(left: string, right: string): number | undefined {\n const a = parseSemver(left)\n const b = parseSemver(right)\n if (a === undefined || b === undefined) return undefined\n for (let index = 0; index < a.core.length; index += 1) {\n const difference = a.core[index]! - b.core[index]!\n if (difference !== 0) return Math.sign(difference)\n }\n if (a.prerelease.length === 0 || b.prerelease.length === 0) {\n return a.prerelease.length === b.prerelease.length ? 0 : a.prerelease.length === 0 ? 1 : -1\n }\n const length = Math.max(a.prerelease.length, b.prerelease.length)\n for (let index = 0; index < length; index += 1) {\n const leftPart = a.prerelease[index]\n const rightPart = b.prerelease[index]\n if (leftPart === undefined || rightPart === undefined) return leftPart === undefined ? -1 : 1\n if (leftPart === rightPart) continue\n if (typeof leftPart === 'number' && typeof rightPart === 'number') return Math.sign(leftPart - rightPart)\n if (typeof leftPart === 'number') return -1\n if (typeof rightPart === 'number') return 1\n return leftPart < rightPart ? -1 : 1\n }\n return 0\n}\n\nfunction isComparatorSet(value: string): boolean {\n if (HYPHEN_RANGE.test(value)) return true\n const normalized = value.replace(/(<=|>=|<|>|=|~|\\^) +/gu, '$1')\n const comparators = normalized.split(/ +/u)\n return comparators.length > 0 && comparators.every(comparator => COMPARATOR.test(comparator))\n}\n\nfunction isNpmVersionRange(value: string): boolean {\n if (!/^[0-9xX*<>=~^|.+\\- ]+$/u.test(value)) return false\n const alternatives = value.split(/ *\\|\\| */u)\n return alternatives.length > 0 && alternatives.every(alternative => alternative !== '' && isComparatorSet(alternative))\n}\n\n/** Return whether pnpm may safely replace this profile dependency from an npm version, range, or tag. */\nexport function isRegistryPluginSpec(value: unknown): value is string {\n if (typeof value !== 'string' || value.trim() !== value || value === '' || /[\\u0000-\\u001f\\u007f]/u.test(value)) return false\n if (/\\.(?:tgz|tar(?:\\.gz)?)$/iu.test(value)) return false\n return parseSemver(value) !== undefined || isNpmVersionRange(value) || DIST_TAG.test(value)\n}\n\n/** Resolve the DSH profile named by the current launcher arguments. */\nexport function launchedProfileName(argv: readonly string[]): string {\n for (let index = 0; index < argv.length; index += 1) {\n if (argv[index] === '--profile') {\n const candidate = argv[index + 1]\n if (candidate !== undefined && /^[\\w.-]+$/u.test(candidate)) return candidate\n }\n const match = /^--profile=([\\w.-]+)$/u.exec(argv[index] ?? '')\n if (match?.[1] !== undefined) return match[1]\n }\n return 'web'\n}\n\nasync function profileDependencySpec(profileDirectory: string): Promise<string | undefined> {\n try {\n const manifest = JSON.parse(await readFile(join(profileDirectory, 'package.json'), 'utf8')) as {\n readonly dependencies?: Readonly<Record<string, unknown>>\n }\n const value = manifest.dependencies?.[PACKAGE_NAME]\n return typeof value === 'string' ? value : undefined\n } catch {\n return undefined\n }\n}\n\nasync function fetchNpmVersion(fetcher: typeof globalThis.fetch): Promise<string | undefined> {\n const response = await fetcher(NPM_LATEST_URL, {\n headers: { accept: 'application/json', 'user-agent': 'dsh-mobile-release-check' },\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n })\n if (!response.ok) return undefined\n const payload = await response.json() as { readonly version?: unknown }\n return typeof payload.version === 'string' && parseSemver(payload.version) !== undefined\n ? payload.version\n : undefined\n}\n\nfunction githubReleaseVersion(location: string | null, responseUrl: string): string | undefined {\n let url: URL\n try { url = new URL(location ?? responseUrl, GITHUB_LATEST_URL) }\n catch { return undefined }\n if (url.origin !== 'https://github.com' || url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '') return undefined\n const prefix = '/saya-ch/dsh-mobile/releases/tag/v'\n if (!url.pathname.startsWith(prefix)) return undefined\n let version: string\n try { version = decodeURIComponent(url.pathname.slice(prefix.length)) } catch { return undefined }\n return parseSemver(version) === undefined ? undefined : version\n}\n\nfunction androidReleaseDownloadUrl(version: string | undefined): string {\n if (version === undefined) return GITHUB_RELEASES_URL\n const tag = `v${version}`\n return `https://github.com/saya-ch/dsh-mobile/releases/download/${encodeURIComponent(tag)}/dsh-mobile-android-${encodeURIComponent(tag)}.apk`\n}\n\nasync function fetchAndroidVersion(fetcher: typeof globalThis.fetch): Promise<string | undefined> {\n const response = await fetcher(GITHUB_LATEST_URL, {\n method: 'GET',\n redirect: 'manual',\n headers: { accept: 'text/html', 'user-agent': 'dsh-mobile-release-check' },\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n })\n return githubReleaseVersion(response.headers.get('location'), response.url)\n}\n\nasync function readProfileInstalledVersion(profileDirectory: string): Promise<string | undefined> {\n try {\n const manifestPath = createRequire(join(profileDirectory, 'package.json')).resolve(`${PACKAGE_NAME}/package.json`)\n const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as { readonly version?: unknown }\n return typeof manifest.version === 'string' ? manifest.version : undefined\n } catch {\n return undefined\n }\n}\n\nfunction childCompletion(child: ChildProcess): Promise<UpdateProcessExit> {\n return new Promise<UpdateProcessExit>((resolveCompletion, rejectCompletion) => {\n child.once('error', rejectCompletion)\n child.once('close', (code, signal) => { resolveCompletion({ code, signal }) })\n })\n}\n\nfunction createDeadline(timeoutMs: number): UpdateDeadline {\n let timer: NodeJS.Timeout | undefined\n const promise = new Promise<void>(resolveTimeout => {\n timer = setTimeout(resolveTimeout, timeoutMs)\n timer.unref()\n })\n return {\n promise,\n cancel: () => {\n if (timer !== undefined) clearTimeout(timer)\n timer = undefined\n },\n }\n}\n\nasync function taskkillProcessTree(pid: number): Promise<void> {\n const killer = spawn('taskkill.exe', ['/PID', String(pid), '/T', '/F'], {\n shell: false,\n windowsHide: true,\n stdio: 'ignore',\n })\n const result = await childCompletion(killer)\n if (result.code !== 0) throw new Error('plugin_update_tree_termination_failed')\n}\n\nasync function completionWithin(completion: Promise<UpdateProcessExit>, timeoutMs: number): Promise<boolean> {\n let timer: NodeJS.Timeout | undefined\n try {\n return await Promise.race([\n completion.then(() => true, () => true),\n new Promise<false>(resolveTimeout => {\n timer = setTimeout(() => { resolveTimeout(false) }, timeoutMs)\n timer.unref()\n }),\n ])\n } finally {\n if (timer !== undefined) clearTimeout(timer)\n }\n}\n\nfunction processMissing(error: unknown): boolean {\n return (error as NodeJS.ErrnoException).code === 'ESRCH'\n}\n\nasync function terminateProcessTree(child: ChildProcess, completion: Promise<UpdateProcessExit>, platform: NodeJS.Platform): Promise<void> {\n if (child.exitCode !== null || child.signalCode !== null) return\n const pid = child.pid\n if (pid === undefined) {\n child.kill('SIGKILL')\n if (!await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) {\n throw new Error('plugin_update_tree_termination_timeout')\n }\n return\n }\n if (platform === 'win32') {\n try { await taskkillProcessTree(pid) } catch (error) {\n if (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL')\n if (!await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) {\n throw new AggregateError([error, new Error('plugin_update_tree_termination_timeout')], 'plugin update tree termination failed')\n }\n throw error\n }\n if (!await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) {\n if (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL')\n if (!await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) {\n throw new Error('plugin_update_tree_termination_timeout')\n }\n }\n return\n }\n try { process.kill(-pid, 'SIGTERM') } catch (error) {\n if (!processMissing(error)) throw error\n if (!await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) {\n throw new Error('plugin_update_tree_termination_timeout')\n }\n return\n }\n if (await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) return\n try { process.kill(-pid, 'SIGKILL') } catch (error) {\n if (!processMissing(error)) throw error\n }\n if (!await completionWithin(completion, UPDATE_TERMINATION_GRACE_MS)) {\n throw new Error('plugin_update_tree_termination_timeout')\n }\n}\n\nfunction startUpdateProcess(request: UpdateProcessRequest): ManagedUpdateProcess {\n const child = spawn(request.command, [...request.args], {\n cwd: request.cwd,\n detached: request.detached,\n shell: request.shell,\n windowsHide: true,\n stdio: ['ignore', 'ignore', 'pipe'],\n })\n const completion = childCompletion(child)\n return {\n completion,\n ...(child.stderr === null ? {} : { stderr: child.stderr }),\n terminateTree: async () => terminateProcessTree(child, completion, request.platform),\n }\n}\n\nfunction updateFailure(cause?: unknown): Error {\n return cause === undefined ? new Error('plugin_update_failed') : new Error('plugin_update_failed', { cause })\n}\n\nasync function runPnpmUpdate(profileDirectory: string, version: string, runtime: PnpmUpdateRuntime = {}): Promise<void> {\n if (parseSemver(version) === undefined) throw new Error('plugin_update_unavailable')\n const platform = runtime.platform ?? process.platform\n const packageSpec = `${PACKAGE_NAME}@${version}`\n const managed = (runtime.start ?? startUpdateProcess)({\n command: platform === 'win32'\n ? (runtime.windowsCommandInterpreter ?? process.env.ComSpec ?? 'cmd.exe')\n : 'pnpm',\n args: platform === 'win32'\n ? ['/d', '/s', '/c', 'pnpm.cmd', 'add', packageSpec]\n : ['add', packageSpec],\n cwd: profileDirectory,\n detached: platform !== 'win32',\n platform,\n shell: false,\n })\n let diagnostics = ''\n managed.stderr?.on('data', chunk => {\n if (diagnostics.length < 4096) diagnostics += Buffer.from(chunk).toString('utf8').slice(0, 4096 - diagnostics.length)\n })\n const completion = managed.completion.then(\n result => ({ kind: 'exit' as const, result }),\n error => ({ kind: 'error' as const, error }),\n )\n const deadline = (runtime.deadline ?? createDeadline)(runtime.timeoutMs ?? UPDATE_TIMEOUT_MS)\n const first = await Promise.race([\n completion,\n deadline.promise.then(() => ({ kind: 'timeout' as const })),\n ])\n deadline.cancel()\n if (first.kind === 'error') throw updateFailure(first.error)\n if (first.kind === 'exit') {\n if (first.result.code === 0) return\n const detail = diagnostics.trim() || `pnpm exited with ${first.result.signal ?? String(first.result.code)}`\n throw updateFailure(new Error(detail))\n }\n let terminationError: unknown\n try { await managed.terminateTree() } catch (error) { terminationError = error }\n if (terminationError !== undefined) throw updateFailure(terminationError)\n const stopped = await completion\n if (stopped.kind === 'error') throw updateFailure(stopped.error)\n throw updateFailure(new Error('plugin update timed out'))\n}\n\n/** Cached npm/GitHub release lookup and guarded profile-local package update. */\nexport class PluginReleaseManager {\n private readonly profileDirectory: string\n private readonly installedVersion: string\n private readonly fetcher: typeof globalThis.fetch\n private readonly runner: (profileDirectory: string, version: string) => Promise<void>\n private readonly installedVersionReader: (profileDirectory: string) => Promise<string | undefined>\n private readonly now: () => number\n private cache: { readonly expiresAt: number; readonly status: PluginReleaseStatus } | undefined\n private activeUpdate: Promise<PluginUpdateResult> | undefined\n\n constructor(options: PluginReleaseManagerOptions) {\n this.profileDirectory = options.profileDirectory\n this.installedVersion = options.installedVersion ?? DSH_MOBILE_VERSION\n this.fetcher = options.fetch ?? globalThis.fetch\n this.runner = options.runUpdate ?? ((profileDirectory, version) => runPnpmUpdate(profileDirectory, version, options.updateProcess))\n this.installedVersionReader = options.readInstalledVersion ?? readProfileInstalledVersion\n this.now = options.now ?? Date.now\n }\n\n /** Read cached release metadata and suppress external lookup failures. */\n async status(force = false): Promise<PluginReleaseStatus> {\n if (!force && this.cache !== undefined && this.cache.expiresAt > this.now()) return this.cache.status\n const dependencySpec = await profileDependencySpec(this.profileDirectory)\n const updateSupported = isRegistryPluginSpec(dependencySpec)\n const [npmResult, androidResult] = await Promise.allSettled([\n fetchNpmVersion(this.fetcher),\n fetchAndroidVersion(this.fetcher),\n ])\n const latestVersion = npmResult.status === 'fulfilled' ? npmResult.value : undefined\n const androidVersion = androidResult.status === 'fulfilled' ? androidResult.value : undefined\n const comparison = latestVersion === undefined\n ? undefined\n : comparePluginVersions(latestVersion, this.installedVersion)\n const status: PluginReleaseStatus = Object.freeze({\n installedVersion: this.installedVersion,\n ...(latestVersion === undefined ? {} : { latestVersion }),\n updateAvailable: updateSupported && comparison === 1,\n updateSupported,\n ...(androidVersion === undefined ? {} : { androidVersion }),\n androidDownloadUrl: androidReleaseDownloadUrl(androidVersion),\n })\n this.cache = { expiresAt: this.now() + STATUS_CACHE_MS, status }\n return status\n }\n\n /** Install the latest npm release into the active profile, then require a DSH restart. */\n async update(): Promise<PluginUpdateResult> {\n if (this.activeUpdate !== undefined) return this.activeUpdate\n this.activeUpdate = this.updateOnce()\n try { return await this.activeUpdate }\n finally { this.activeUpdate = undefined }\n }\n\n private async updateOnce(): Promise<PluginUpdateResult> {\n const status = await this.status(true)\n if (!status.updateSupported) throw new Error('plugin_update_unsupported')\n if (!status.updateAvailable || status.latestVersion === undefined) throw new Error('plugin_update_unavailable')\n await this.runner(this.profileDirectory, status.latestVersion)\n const installed = await this.installedVersionReader(this.profileDirectory)\n if (installed !== status.latestVersion) throw new Error('plugin_update_failed')\n this.cache = undefined\n return Object.freeze({ installedVersion: installed, restartRequired: true })\n }\n}\n","import {\n X509Certificate,\n createPrivateKey,\n createPublicKey,\n} from 'node:crypto'\nimport { execFile as execFileCallback } from 'node:child_process'\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises'\nimport { networkInterfaces, type NetworkInterfaceInfo } from 'node:os'\nimport { basename, dirname, join } from 'node:path'\nimport { promisify } from 'node:util'\nimport { generate } from 'selfsigned'\nimport { restrictPrivateFile } from './private-file.js'\n\n/** One active private IPv4 address tied to a stable operating-system interface name. */\nexport interface LanNetwork {\n readonly name: string\n readonly address: string\n readonly cidr: string\n}\n\n/** Versioned setup that survives DHCP address changes on the selected interface. */\nexport interface ManagedSetup {\n readonly version: 2\n readonly networkInterface: string\n readonly listenPort: number\n readonly upstreamOrigin: string\n readonly tls: {\n readonly mode: 'managed'\n readonly caCertFile: string\n readonly caKeyFile: string\n readonly certFile: string\n readonly keyFile: string\n }\n}\n\ntype InterfaceTable = NodeJS.Dict<NetworkInterfaceInfo[]>\ntype RouteCommand = (file: string, args: readonly string[]) => Promise<string>\n\nconst execFile = promisify(execFileCallback)\nconst VIRTUAL_INTERFACE_MARKERS = [\n 'bridge', 'docker', 'hyper-v', 'mihomo', 'radmin', 'tailscale', 'tap', 'tun',\n 'utun', 'vbox', 'veth', 'virtual', 'vmware', 'vpn', 'vethernet', 'wsl', 'zerotier',\n]\n\nfunction requiredString(value: unknown, name: string): string {\n if (typeof value !== 'string' || value.length === 0) throw new Error(`${name} must be a non-empty string`)\n return value\n}\n\n/** Validate the durable managed setup before it controls network and filesystem operations. */\nexport function parseManagedSetup(value: unknown): ManagedSetup {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error('mobile setup file must be an object')\n }\n const record = value as Record<string, unknown>\n if (record.version !== 2 || Reflect.ownKeys(record)\n .some(key => typeof key !== 'string' || !['version', 'networkInterface', 'listenPort', 'upstreamOrigin', 'tls'].includes(key))) {\n throw new Error('mobile setup file has an unsupported format')\n }\n if (!Number.isSafeInteger(record.listenPort) || (record.listenPort as number) < 1024\n || (record.listenPort as number) > 65535) {\n throw new Error('mobile setup listenPort must be from 1024 through 65535')\n }\n if (typeof record.tls !== 'object' || record.tls === null || Array.isArray(record.tls)) {\n throw new Error('mobile setup tls must be an object')\n }\n const tls = record.tls as Record<string, unknown>\n if (tls.mode !== 'managed' || Reflect.ownKeys(tls)\n .some(key => typeof key !== 'string' || !['mode', 'caCertFile', 'caKeyFile', 'certFile', 'keyFile'].includes(key))) {\n throw new Error('mobile setup tls has an unsupported format')\n }\n return Object.freeze({\n version: 2,\n networkInterface: requiredString(record.networkInterface, 'mobile setup networkInterface'),\n listenPort: record.listenPort as number,\n upstreamOrigin: requiredString(record.upstreamOrigin, 'mobile setup upstreamOrigin'),\n tls: Object.freeze({\n mode: 'managed',\n caCertFile: requiredString(tls.caCertFile, 'mobile setup tls.caCertFile'),\n caKeyFile: requiredString(tls.caKeyFile, 'mobile setup tls.caKeyFile'),\n certFile: requiredString(tls.certFile, 'mobile setup tls.certFile'),\n keyFile: requiredString(tls.keyFile, 'mobile setup tls.keyFile'),\n }),\n })\n}\n\nfunction privateIpv4(value: string): boolean {\n const parts = value.split('.').map(Number)\n return parts.length === 4 && parts.every(part => Number.isInteger(part) && part >= 0 && part <= 255)\n && (parts[0] === 10\n || (parts[0] === 172 && parts[1]! >= 16 && parts[1]! <= 31)\n || (parts[0] === 192 && parts[1] === 168))\n}\n\nfunction networkCidr(address: string, cidr: string): string {\n const prefix = Number(cidr.slice(cidr.lastIndexOf('/') + 1))\n const value = address.split('.').reduce((total, part) => ((total << 8) | Number(part)) >>> 0, 0)\n const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0\n const network = (value & mask) >>> 0\n return `${[24, 16, 8, 0].map(shift => (network >>> shift) & 255).join('.')}/${String(prefix)}`\n}\n\n/** List current private IPv4 candidates with their interface identity. */\nexport function availableLanNetworks(table: InterfaceTable = networkInterfaces()): LanNetwork[] {\n const candidates = Object.entries(table).flatMap(([name, entries]) => (entries ?? [])\n .filter(entry => entry.family === 'IPv4' && !entry.internal && privateIpv4(entry.address) && entry.cidr !== null)\n .map(entry => ({ name, address: entry.address, cidr: networkCidr(entry.address, entry.cidr!) })))\n return [...new Map(candidates.map(entry => [`${entry.name}\\0${entry.address}`, entry])).values()]\n}\n\nfunction likelyVirtualInterface(name: string): boolean {\n const normalized = name.toLowerCase().replaceAll(/[^a-z0-9]+/gu, ' ')\n return VIRTUAL_INTERFACE_MARKERS.some(marker => normalized.includes(marker.replaceAll('-', ' ')))\n || /^(?:br|wg)\\d*\\b/u.test(normalized)\n}\n\nasync function runRouteCommand(file: string, args: readonly string[]): Promise<string> {\n const result = await execFile(file, [...args], { encoding: 'utf8', windowsHide: true })\n return result.stdout\n}\n\nfunction uniqueLines(output: string): string[] {\n return [...new Set(output.split(/\\r?\\n/gu).map(line => line.trim()).filter(Boolean))]\n}\n\n/** Return operating-system default-route interfaces in routing preference order. */\nexport async function preferredLanInterfaceNames(\n platform: NodeJS.Platform = process.platform,\n run: RouteCommand = runRouteCommand,\n): Promise<string[]> {\n try {\n if (platform === 'win32') {\n const script = [\n \"$routes = Get-NetRoute -AddressFamily IPv4 -DestinationPrefix '0.0.0.0/0' -ErrorAction Stop\",\n \"$ranked = $routes | Where-Object { $_.State -eq 'Alive' -and $_.NextHop -ne '0.0.0.0' } | ForEach-Object {\",\n ' $route = $_',\n ' $adapter = Get-NetAdapter -InterfaceIndex $route.InterfaceIndex -ErrorAction SilentlyContinue',\n ' $ip = Get-NetIPInterface -AddressFamily IPv4 -InterfaceIndex $route.InterfaceIndex -ErrorAction SilentlyContinue',\n \" if ($adapter -and $ip -and $adapter.Status -eq 'Up' -and $adapter.HardwareInterface -eq $true -and $adapter.Virtual -ne $true) {\",\n ' [pscustomobject]@{ Name = $route.InterfaceAlias; Metric = [int]$route.RouteMetric + [int]$ip.InterfaceMetric }',\n ' }',\n '}',\n '$ranked | Sort-Object Metric | Select-Object -ExpandProperty Name -Unique',\n ].join('; ')\n return uniqueLines(await run('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script]))\n }\n if (platform === 'linux') {\n const routes = uniqueLines(await run('ip', ['-o', '-4', 'route', 'show', 'default']))\n .map(line => ({\n name: /(?:^|\\s)dev\\s+(\\S+)/u.exec(line)?.[1],\n metric: Number(/(?:^|\\s)metric\\s+(\\d+)/u.exec(line)?.[1] ?? 0),\n }))\n .filter((route): route is { name: string; metric: number } => route.name !== undefined\n && !likelyVirtualInterface(route.name))\n .sort((left, right) => left.metric - right.metric)\n return [...new Set(routes.map(route => route.name))]\n }\n if (platform === 'darwin') {\n const name = /^\\s*interface:\\s*(\\S+)\\s*$/mu.exec(await run('route', ['-n', 'get', 'default']))?.[1]\n return name === undefined || likelyVirtualInterface(name) ? [] : [name]\n }\n } catch {\n // Route discovery is advisory; deterministic candidate checks below remain the fallback.\n }\n return []\n}\n\n/** Select an active LAN, optionally by address or by a previously saved interface name. */\nexport function selectLanNetwork(\n requestedAddress?: string,\n requestedInterface?: string,\n table?: InterfaceTable,\n preferredInterfaces: readonly string[] = [],\n): LanNetwork {\n const candidates = availableLanNetworks(table)\n if (requestedAddress !== undefined) {\n const match = candidates.find(candidate => candidate.address === requestedAddress)\n if (match === undefined) throw new Error(`--address ${requestedAddress} is not an active private LAN address`)\n return match\n }\n if (requestedInterface !== undefined) {\n const matches = candidates.filter(candidate => candidate.name === requestedInterface)\n if (matches.length === 1) return matches[0]!\n if (matches.length === 0) {\n throw new Error(`saved LAN interface ${JSON.stringify(requestedInterface)} is not connected`)\n }\n throw new Error(`saved LAN interface ${JSON.stringify(requestedInterface)} has more than one private IPv4 address`)\n }\n if (candidates.length === 1) return candidates[0]!\n if (candidates.length === 0) throw new Error('no active private LAN address was found; connect to Wi-Fi or Ethernet')\n for (const name of preferredInterfaces) {\n const matches = candidates.filter(candidate => candidate.name === name)\n if (matches.length === 1) return matches[0]!\n }\n const physicalCandidates = candidates.filter(candidate => !likelyVirtualInterface(candidate.name))\n if (physicalCandidates.length === 1) return physicalCandidates[0]!\n throw new Error(`more than one LAN address is active; rerun with --address and one of: ${candidates.map(entry => `${entry.name}=${entry.address}`).join(', ')}`)\n}\n\nfunction assertMatchingCa(certPem: string, keyPem: string): X509Certificate {\n const certificate = new X509Certificate(certPem)\n if (!certificate.ca || certificate.subject !== certificate.issuer\n || !certificate.verify(certificate.publicKey)) {\n throw new Error('managed TLS CA must be a self-signed CA certificate')\n }\n const privatePublic = createPublicKey(createPrivateKey(keyPem)).export({ format: 'der', type: 'spki' })\n const certificatePublic = certificate.publicKey.export({ format: 'der', type: 'spki' })\n if (!privatePublic.equals(certificatePublic)) throw new Error('managed TLS CA certificate and key do not match')\n if (Date.parse(certificate.validFrom) > Date.now() || Date.parse(certificate.validTo) <= Date.now()) {\n throw new Error('managed TLS CA certificate is not currently valid')\n }\n return certificate\n}\n\nasync function atomicWrite(file: string, contents: string | Uint8Array): Promise<void> {\n const directory = dirname(file)\n await mkdir(directory, { recursive: true, mode: 0o700 })\n const temporary = join(directory, `.${basename(file)}.${process.pid}.tmp`)\n await writeFile(temporary, contents, { mode: 0o600 })\n await rename(temporary, file)\n await restrictPrivateFile(file)\n}\n\n/** Create a long-lived CA or migrate the legacy self-signed server certificate as that CA. */\nexport async function ensureManagedCa(\n setup: ManagedSetup['tls'],\n legacy?: { readonly certFile: string; readonly keyFile: string },\n): Promise<X509Certificate> {\n let certPem: string | undefined\n let keyPem: string | undefined\n try {\n [certPem, keyPem] = await Promise.all([readFile(setup.caCertFile, 'utf8'), readFile(setup.caKeyFile, 'utf8')])\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n let migrated = false\n if (legacy !== undefined) {\n try {\n [certPem, keyPem] = await Promise.all([readFile(legacy.certFile, 'utf8'), readFile(legacy.keyFile, 'utf8')])\n assertMatchingCa(certPem, keyPem)\n migrated = true\n } catch (legacyError) {\n if ((legacyError as NodeJS.ErrnoException).code !== 'ENOENT') throw legacyError\n }\n }\n if (!migrated) {\n const now = new Date()\n const notAfter = new Date(now)\n notAfter.setFullYear(notAfter.getFullYear() + 5)\n const generated = await generate([{ name: 'commonName', value: 'DeepSeek Harness Mobile CA' }], {\n keyType: 'ec',\n curve: 'P-256',\n algorithm: 'sha256',\n notBeforeDate: new Date(now.getTime() - 5 * 60_000),\n notAfterDate: notAfter,\n extensions: [\n { name: 'basicConstraints', cA: true, critical: true },\n { name: 'keyUsage', digitalSignature: true, keyCertSign: true, cRLSign: true, critical: true },\n ],\n })\n certPem = generated.cert\n keyPem = generated.private\n }\n if (certPem === undefined || keyPem === undefined) throw new Error('managed TLS CA creation did not produce key material')\n await Promise.all([atomicWrite(setup.caCertFile, certPem), atomicWrite(setup.caKeyFile, keyPem)])\n }\n if (certPem === undefined || keyPem === undefined) throw new Error('managed TLS CA creation did not produce key material')\n await Promise.all([restrictPrivateFile(setup.caCertFile), restrictPrivateFile(setup.caKeyFile)])\n return assertMatchingCa(certPem, keyPem)\n}\n\n/** Sign and atomically install a server leaf for the interface's current address. */\nexport async function refreshManagedServerCertificate(setup: ManagedSetup, address: string): Promise<void> {\n await Promise.all([restrictPrivateFile(setup.tls.caCertFile), restrictPrivateFile(setup.tls.caKeyFile)])\n const [caCert, caKey] = await Promise.all([\n readFile(setup.tls.caCertFile, 'utf8'),\n readFile(setup.tls.caKeyFile, 'utf8'),\n ])\n assertMatchingCa(caCert, caKey)\n const now = new Date()\n const notAfter = new Date(now)\n notAfter.setDate(notAfter.getDate() + 397)\n const server = await generate([{ name: 'commonName', value: 'DeepSeek Harness Mobile' }], {\n keyType: 'ec',\n curve: 'P-256',\n algorithm: 'sha256',\n notBeforeDate: new Date(now.getTime() - 5 * 60_000),\n notAfterDate: notAfter,\n ca: { cert: caCert, key: caKey },\n extensions: [\n { name: 'basicConstraints', cA: false, critical: true },\n { name: 'keyUsage', digitalSignature: true, critical: true },\n { name: 'extKeyUsage', serverAuth: true },\n { name: 'subjectAltName', altNames: [{ type: 7, ip: address }] },\n ],\n })\n await Promise.all([\n atomicWrite(setup.tls.certFile, server.cert),\n atomicWrite(setup.tls.keyFile, server.private),\n ])\n}\n\n/** Resolve the saved interface to the ordinary gateway config consumed by the Host plugin. */\nexport async function materializeManagedSetup(\n setup: ManagedSetup,\n table?: InterfaceTable,\n): Promise<Record<string, unknown>> {\n const network = selectLanNetwork(undefined, setup.networkInterface, table)\n await refreshManagedServerCertificate(setup, network.address)\n const ca = new X509Certificate(await readFile(setup.tls.caCertFile, 'utf8'))\n return {\n publicOrigin: `https://${network.address}:${String(setup.listenPort)}`,\n listenHost: network.address,\n upstreamOrigin: setup.upstreamOrigin,\n allowedCidrs: [network.cidr],\n instanceId: ca.fingerprint256.replaceAll(':', '').toLowerCase(),\n pairingCaFile: setup.tls.caCertFile,\n tls: {\n mode: 'provided',\n certFile: setup.tls.certFile,\n keyFile: setup.tls.keyFile,\n },\n }\n}\n","import type { Context } from '@deepseek-ai/cordis'\nimport { boundContextSummary, createUserMessage } from '@deepseek-ai/dsh-llm/message'\n// Side-effect type import: activates dsh-commands' Context augmentation so\n// `ctx.commands` and its handler types resolve without a runtime dependency.\nimport type {} from '@deepseek-ai/dsh-commands'\nimport type { WebRoute } from '@deepseek-ai/dsh-host-webserver'\nimport { createRequire } from 'node:module'\nimport { X509Certificate } from 'node:crypto'\nimport { copyFile, lstat, readFile, rm } from 'node:fs/promises'\nimport { dirname, isAbsolute, join, resolve } from 'node:path'\nimport { parseControlFile, parseGatewayConfig, type PluginConfig, type ResolvedGatewayConfig } from './config.js'\nimport { assertSupportedDshVersion } from './compatibility.js'\nimport { collectConnectionDiagnostics } from './diagnostics.js'\nimport { MOBILE_CUSTOMIZATION_GUIDE } from './mobile-guide.js'\nimport {\n FollowingMobileAccessRuntime,\n JsonMobileAccessControlStore,\n MobileAccessGatewayController,\n type MobileAccessRuntime,\n} from './control.js'\nimport { MobileAccessGateway } from './gateway.js'\nimport { createMobileAccessService, type MobileAccessService } from './extensions.js'\nimport { listComputerImages, readComputerImage } from './computer-images.js'\nimport {\n HttpError,\n LOCAL_ADMIN_PREFIX,\n assertLocalAdminTrust,\n parseRequestTarget,\n readJsonObject,\n sendFailure,\n sendJson,\n} from './http-security.js'\nimport { JsonDeviceStore } from './storage.js'\nimport { FunnelController, funnelExecutable } from './funnel.js'\nimport { CpolarController } from './cpolar.js'\nimport { CpolarComponentManager, type CpolarComponentStatus } from './cpolar-component.js'\nimport { FrpComponentManager, type FrpComponentStatus } from './frp-component.js'\nimport { FrpConfigStore, type FrpConfigurationStatus } from './frp-config.js'\nimport { FrpController } from './frp.js'\nimport { launchedProfileName, PluginReleaseManager } from './release-update.js'\nimport {\n configuredRemoteProvider,\n JsonRemoteProviderStore,\n RemoteProviderCoordinator,\n type RemoteProvider,\n type RemoteProviderController,\n type RemoteProviderStatus,\n} from './remote.js'\nimport { parseAuthority, parseCidr } from './network.js'\nimport {\n materializeManagedSetup,\n parseManagedSetup,\n selectLanNetwork,\n type ManagedSetup,\n} from './managed-setup.js'\n\n/** Stable Cordis plugin name. */\nexport const name = 'dsh-mobile'\n\n/** The stock WebServer serves the control card; Connection authenticates the loopback DSH origin. */\nexport const inject = ['webServer', 'commands', 'connection']\n\n/** Run cleanup steps in ownership order and report every failure after all steps settle. */\nexport async function settleCleanupSteps(steps: readonly (() => void | Promise<void>)[]): Promise<void> {\n const errors: unknown[] = []\n for (const step of steps) {\n try { await step() } catch (error) { errors.push(error) }\n }\n if (errors.length === 1 && errors[0] instanceof Error) throw errors[0]\n if (errors.length > 0) throw new AggregateError(errors, 'DSH Mobile cleanup failed')\n}\n\ninterface BrowserAuthenticatedConnection {\n authenticatedUrl?: (baseUrl: string) => string\n}\n\nfunction upstreamAuthenticatedUrl(ctx: Context, upstreamOrigin: URL): string | undefined {\n const connection = (ctx as Context & { readonly connection?: BrowserAuthenticatedConnection }).connection\n return typeof connection?.authenticatedUrl === 'function'\n ? connection.authenticatedUrl(upstreamOrigin.origin)\n : undefined\n}\n\nfunction installedDshVersion(): unknown {\n const manifest = createRequire(import.meta.url)('@deepseek-ai/dsh-host-webserver/package.json') as unknown\n if (manifest === null || typeof manifest !== 'object') return undefined\n return (manifest as { readonly version?: unknown }).version\n}\n\nfunction mapAdminError(error: unknown): HttpError {\n if (error instanceof HttpError) return error\n const code = (error as NodeJS.ErrnoException).code\n if (code === 'EADDRNOTAVAIL') return new HttpError(409, 'network_address_changed')\n if (code === 'EADDRINUSE') return new HttpError(409, 'listen_port_in_use')\n if (error instanceof Error && error.message.startsWith('saved LAN interface ')) {\n return new HttpError(409, 'network_interface_unavailable')\n }\n if (error instanceof Error && error.message === 'cpolar_authtoken_invalid') {\n return new HttpError(400, 'cpolar_authtoken_invalid')\n }\n if (error instanceof Error && error.message.startsWith('cpolar_')) {\n return new HttpError(409, error.message)\n }\n if (error instanceof Error && [\n 'frp_server_address_invalid',\n 'frp_server_port_invalid',\n 'frp_token_invalid',\n 'frp_public_origin_invalid',\n 'frp_settings_invalid',\n ].includes(error.message)) return new HttpError(400, error.message)\n if (error instanceof Error && error.message.startsWith('frp_')) {\n return new HttpError(409, error.message)\n }\n if (error instanceof Error && error.message === 'plugin_update_failed') {\n return new HttpError(500, error.message)\n }\n if (error instanceof Error && error.message.startsWith('plugin_update_')) {\n return new HttpError(409, error.message)\n }\n return new HttpError(500, 'internal_error')\n}\n\nconst SETUP_KEYS = new Set([\n 'version', 'publicOrigin', 'listenHost', 'listenPort', 'upstreamOrigin',\n 'publicAuthorities', 'allowedCidrs', 'instanceId', 'pairingCaFile', 'tls',\n])\n\ntype LoadedSetup = {\n readonly kind: 'fixed'\n readonly config: PluginConfig\n} | {\n readonly kind: 'managed'\n readonly config: PluginConfig\n readonly setup: ManagedSetup\n}\n\nfunction withoutSetupKeys(config: PluginConfig): PluginConfig {\n const merged = { ...config } as Record<string, unknown>\n for (const key of SETUP_KEYS) if (key !== 'version') delete merged[key]\n return merged as unknown as PluginConfig\n}\n\nasync function loadSetup(config: PluginConfig): Promise<LoadedSetup> {\n if (config.setupFile === undefined) return { kind: 'fixed', config }\n if (!isAbsolute(config.setupFile)) throw new Error('setupFile must be an absolute file path')\n let source: string\n try {\n source = await readFile(resolve(config.setupFile), 'utf8')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { kind: 'fixed', config }\n throw error\n }\n let parsed: unknown\n try { parsed = JSON.parse(source) as unknown }\n catch (error) { throw new Error('mobile setup file is not valid JSON', { cause: error }) }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('mobile setup file must be an object')\n }\n const record = parsed as Record<string, unknown>\n if (record.version === 2) {\n return { kind: 'managed', config: withoutSetupKeys(config), setup: parseManagedSetup(record) }\n }\n if (record.version !== 1 || Reflect.ownKeys(record).some(key => typeof key !== 'string' || !SETUP_KEYS.has(key))) {\n throw new Error('mobile setup file has an unsupported format')\n }\n const { version: _version, ...setup } = record\n return {\n kind: 'fixed',\n config: { ...withoutSetupKeys(config), ...setup } as unknown as PluginConfig,\n }\n}\n\nfunction loopbackTemplate(loaded: LoadedSetup): ResolvedGatewayConfig {\n const base = withoutSetupKeys(loaded.config)\n return parseGatewayConfig({\n ...base,\n ...(loaded.kind === 'managed'\n ? { upstreamOrigin: loaded.setup.upstreamOrigin }\n : loaded.config.upstreamOrigin === undefined ? {} : { upstreamOrigin: loaded.config.upstreamOrigin }),\n listenHost: '127.0.0.1',\n listenPort: 0,\n publicAuthorities: ['127.0.0.1'],\n allowedCidrs: ['127.0.0.0/8'],\n tls: { mode: 'disabled' },\n })\n}\n\nasync function stableInstanceId(loaded: LoadedSetup, template: ResolvedGatewayConfig): Promise<string> {\n if (loaded.kind !== 'managed') return loaded.config.instanceId ?? template.instanceId\n const certificate = new X509Certificate(await readFile(loaded.setup.tls.caCertFile))\n return certificate.fingerprint256.replaceAll(':', '').toLowerCase()\n}\n\nexport function remoteGatewayConfig(\n template: ResolvedGatewayConfig,\n publicOrigin: string,\n stateFile: string,\n instanceId: string,\n listenPort = 0,\n): ResolvedGatewayConfig {\n const origin = new URL(publicOrigin)\n if (origin.protocol !== 'https:' || origin.username !== '' || origin.password !== ''\n || origin.pathname !== '/' || origin.search !== '' || origin.hash !== '') {\n throw new Error('remote public origin must be an HTTPS origin')\n }\n // The gateway listens on an ephemeral loopback port behind Funnel, while the\n // public authority is HTTPS on 443. Keep that external port explicit so the\n // trust policy never substitutes the private listener port into QR URLs.\n const publicAuthority = origin.port === '' ? `${origin.hostname}:443` : origin.host\n const { pairingCaFile: _pairingCaFile, ...shared } = template\n return Object.freeze({\n ...shared,\n listenHost: '127.0.0.1',\n listenPort,\n authorities: Object.freeze([parseAuthority(publicAuthority)]),\n allowedCidrs: Object.freeze([parseCidr('127.0.0.0/8')]),\n stateFile,\n instanceId,\n tls: Object.freeze({ mode: 'disabled' }),\n publicTls: true,\n discovery: false,\n })\n}\n\nfunction remoteControlPayload(\n provider: RemoteProvider,\n status: RemoteProviderStatus,\n gateway: MobileAccessGateway | undefined,\n providerStatuses: Readonly<Record<RemoteProvider, RemoteProviderStatus>>,\n cpolarComponent: CpolarComponentStatus,\n frpComponent: FrpComponentStatus,\n frpConfiguration: FrpConfigurationStatus,\n): Record<string, unknown> {\n return {\n provider,\n running: status.enabled,\n state: status.state,\n ...(status.origin === undefined ? {} : { origin: status.origin }),\n ...(status.loginUrl === undefined ? {} : { loginUrl: status.loginUrl }),\n ...(status.setupUrl === undefined ? {} : { setupUrl: status.setupUrl }),\n ...(status.errorCode === undefined ? {} : { errorCode: status.errorCode }),\n ...(gateway === undefined ? {} : { extensions: gateway.extensionStatus() }),\n providers: {\n tailscale: { bundled: true, running: providerStatuses.tailscale.enabled, state: providerStatuses.tailscale.state },\n cpolar: {\n bundled: false,\n running: providerStatuses.cpolar.enabled,\n state: providerStatuses.cpolar.state,\n component: cpolarComponent,\n },\n frp: {\n bundled: false,\n running: providerStatuses.frp.enabled,\n state: providerStatuses.frp.state,\n component: frpComponent,\n configuration: frpConfiguration,\n },\n },\n }\n}\n\n/** Mount the resident control route and its optional authenticated LAN gateway. */\nexport async function apply(ctx: Context, config: PluginConfig): Promise<void> {\n const dshVersion = installedDshVersion()\n assertSupportedDshVersion(dshVersion)\n const loaded = await loadSetup(config)\n const mobileAccess: MobileAccessService = createMobileAccessService(ctx)\n const template = loopbackTemplate(loaded)\n const upstreamLoginUrl = upstreamAuthenticatedUrl(ctx, template.upstreamOrigin)\n const instanceId = await stableInstanceId(loaded, template)\n const stateDirectory = dirname(template.stateFile)\n const remoteDirectory = join(stateDirectory, 'remote')\n const configuredDshHome = process.env.DSH_HOME?.trim()\n const dshHome = configuredDshHome === undefined || configuredDshHome === ''\n ? dirname(stateDirectory)\n : resolve(configuredDshHome)\n const releaseManager = new PluginReleaseManager({\n profileDirectory: join(dshHome, 'profiles', launchedProfileName(process.argv.slice(2))),\n })\n const remoteProviderStore = new JsonRemoteProviderStore(\n join(remoteDirectory, 'provider.json'),\n configuredRemoteProvider(process.env),\n )\n const initialRemoteProvider = (await remoteProviderStore.load()).provider\n const cpolarComponent = new CpolarComponentManager({ stateDirectory })\n await cpolarComponent.initialize()\n const frpComponent = new FrpComponentManager({ stateDirectory })\n await frpComponent.initialize()\n const frpConfig = new FrpConfigStore(join(remoteDirectory, 'frp', 'config'))\n await frpConfig.initialize()\n const unregisterBuiltin = mobileAccess.registerExtension({\n schemaVersion: 1,\n id: 'computer-images',\n name: 'Computer images',\n version: '1.0.0',\n description: 'Authenticated computer-side image browser',\n routes: [\n {\n method: 'GET', path: 'list',\n async handle(request) {\n return { status: 200, contentType: 'application/json; charset=utf-8', body: JSON.stringify(await listComputerImages(request.query.get('path'))) }\n },\n },\n {\n method: 'GET', path: 'image',\n async handle(request) {\n const image = await readComputerImage(request.query.get('path'))\n return { status: 200, contentType: image.contentType, headers: { 'content-disposition': `inline; filename*=UTF-8''${encodeURIComponent(image.name)}` }, body: image.body }\n },\n },\n ],\n })\n let lanGateway: MobileAccessGateway | undefined\n const startGateway = async (candidateConfig: PluginConfig): Promise<MobileAccessRuntime> => {\n const resolved = parseGatewayConfig(candidateConfig)\n const candidate = new MobileAccessGateway(\n resolved,\n new JsonDeviceStore(resolved.stateFile, resolved.maxDevices),\n mobileAccess,\n upstreamLoginUrl,\n )\n await candidate.start()\n lanGateway = candidate\n return {\n close: async () => {\n if (lanGateway === candidate) lanGateway = undefined\n await candidate.close()\n },\n }\n }\n const startRuntime = async (): Promise<MobileAccessRuntime> => {\n if (loaded.kind === 'fixed') return startGateway(loaded.config)\n const following = new FollowingMobileAccessRuntime(async () => {\n const network = selectLanNetwork(undefined, loaded.setup.networkInterface)\n return {\n key: `${network.name}\\0${network.address}\\0${network.cidr}`,\n start: async () => startGateway({\n ...loaded.config,\n ...await materializeManagedSetup(loaded.setup),\n }),\n }\n }, (error) => {\n process.emitWarning(`DSH Mobile could not follow the current LAN address: ${error instanceof Error ? error.message : String(error)}`, {\n code: 'DSH_MOBILE_NETWORK_REFRESH',\n })\n })\n await following.initialize(2_000)\n return following\n }\n const lanController = new MobileAccessGatewayController(\n new JsonMobileAccessControlStore(parseControlFile(config.controlFile), config.initiallyEnabled),\n startRuntime,\n )\n const remoteDeviceFile = join(remoteDirectory, 'devices.json')\n const legacyCpolarDeviceFile = join(remoteDirectory, 'cpolar', 'devices.json')\n if (initialRemoteProvider === 'cpolar') {\n try {\n await lstat(remoteDeviceFile)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n try { await copyFile(legacyCpolarDeviceFile, remoteDeviceFile) } catch (copyError) {\n if ((copyError as NodeJS.ErrnoException).code !== 'ENOENT') throw copyError\n }\n }\n }\n const createRemoteGateway = async (publicOrigin: string, listenPort = 0): Promise<MobileAccessGateway> => {\n const resolved = remoteGatewayConfig(\n template,\n publicOrigin,\n remoteDeviceFile,\n instanceId,\n listenPort,\n )\n const candidate = new MobileAccessGateway(\n resolved,\n new JsonDeviceStore(resolved.stateFile, resolved.maxDevices),\n mobileAccess,\n upstreamLoginUrl,\n )\n await candidate.start()\n return candidate\n }\n const tailscaleStore = new JsonMobileAccessControlStore(join(remoteDirectory, 'control.json'), false)\n const cpolarStore = new JsonMobileAccessControlStore(join(remoteDirectory, 'cpolar', 'control.json'), false)\n const frpStore = new JsonMobileAccessControlStore(join(remoteDirectory, 'frp', 'control.json'), false)\n const remoteControllers: Record<RemoteProvider, RemoteProviderController> = {\n tailscale: new FunnelController({\n store: tailscaleStore,\n executable: funnelExecutable(import.meta.url),\n stateDirectory: join(remoteDirectory, 'tailscale'),\n hostname: `dsh-${instanceId.slice(0, 12)}`,\n createGateway: createRemoteGateway,\n }),\n cpolar: new CpolarController({\n store: cpolarStore,\n executable: cpolarComponent.executable,\n configFile: cpolarComponent.configFile,\n region: 'cn',\n createGateway: createRemoteGateway,\n }),\n frp: new FrpController({\n store: frpStore,\n executable: frpComponent.executable,\n config: frpConfig,\n instanceId,\n createGateway: createRemoteGateway,\n }),\n }\n const remoteProviders = new RemoteProviderCoordinator(initialRemoteProvider, remoteControllers, remoteProviderStore)\n const remoteController = () => remoteProviders.controller()\n const remotePayload = (): Record<string, unknown> => remoteControlPayload(\n remoteProviders.selected,\n remoteController().status(),\n remoteController().gateway(),\n {\n tailscale: remoteControllers.tailscale.status(),\n cpolar: remoteControllers.cpolar.status(),\n frp: remoteControllers.frp.status(),\n },\n cpolarComponent.status(),\n frpComponent.status(),\n frpConfig.status(),\n )\n const lanPayload = (): Record<string, unknown> => ({\n running: lanController.isRunning(),\n origin: lanGateway?.address().origin,\n ...(lanGateway === undefined ? {} : { extensions: lanGateway.extensionStatus() }),\n })\n const diagnosticsPayload = async (): Promise<Record<string, unknown>> => {\n let interfaceName: string | undefined\n let networkError: string | undefined\n if (loaded.kind === 'managed') {\n try { interfaceName = selectLanNetwork(undefined, loaded.setup.networkInterface).name }\n catch { networkError = 'network_interface_unavailable' }\n }\n const remote = remoteController().status()\n return collectConnectionDiagnostics({\n dshVersion,\n lan: {\n running: lanController.isRunning(),\n ...(lanGateway === undefined ? {} : { origin: lanGateway.address().origin, port: lanGateway.address().port }),\n ...(loaded.kind === 'managed' ? { configuredInterface: loaded.setup.networkInterface, port: loaded.setup.listenPort } : {}),\n ...(interfaceName === undefined ? {} : { interfaceName }),\n ...(networkError === undefined ? {} : { networkError }),\n },\n remote: {\n provider: remoteProviders.selected,\n running: remote.enabled,\n state: remote.state,\n ...(remote.origin === undefined ? {} : { origin: remote.origin }),\n ...(remote.errorCode === undefined ? {} : { errorCode: remote.errorCode }),\n },\n }) as unknown as Record<string, unknown>\n }\n\n const adminRoute: WebRoute = {\n kind: 'prefix',\n path: LOCAL_ADMIN_PREFIX,\n handler: async (request, response) => {\n try {\n const target = parseRequestTarget(request.url)\n assertLocalAdminTrust(request, request.method === 'POST')\n if (target.search !== '') throw new HttpError(400, 'bad_request')\n const lanControl = target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/control`\n || target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/lan/control`\n if (request.method === 'GET' && lanControl) {\n sendJson(response, 200, lanPayload(), false)\n return\n }\n if (request.method === 'GET' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/diagnostics`) {\n sendJson(response, 200, await diagnosticsPayload(), false)\n return\n }\n if (request.method === 'GET' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/release`) {\n sendJson(response, 200, await releaseManager.status(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/release/update`) {\n await readJsonObject(request, 4096)\n sendJson(response, 200, await releaseManager.update(), false)\n return\n }\n if (request.method === 'POST' && lanControl) {\n const body = await readJsonObject(request, 4096)\n if (typeof body.running !== 'boolean') throw new HttpError(400, 'bad_request')\n await lanController.setRunning(body.running)\n sendJson(response, 200, lanPayload(), false)\n return\n }\n if (request.method === 'GET' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/control`) {\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/provider`) {\n const body = await readJsonObject(request, 4096)\n if (body.provider !== 'tailscale' && body.provider !== 'cpolar' && body.provider !== 'frp') {\n throw new HttpError(400, 'bad_request')\n }\n await remoteProviders.select(body.provider)\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/cpolar/component/install`) {\n const body = await readJsonObject(request, 4096)\n if (body.confirm !== true) throw new HttpError(400, 'bad_request')\n await remoteProviders.mutate(async () => cpolarComponent.install())\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/cpolar/configure`) {\n const body = await readJsonObject(request, 4096)\n await remoteProviders.mutate(async () => cpolarComponent.configure(body.authtoken))\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/cpolar/component/purge`) {\n const body = await readJsonObject(request, 4096)\n if (body.confirm !== true) throw new HttpError(400, 'bad_request')\n await remoteProviders.mutate(async () => {\n await remoteControllers.cpolar.setEnabled(false)\n await cpolarComponent.purge()\n })\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/frp/component/install`) {\n const body = await readJsonObject(request, 4096)\n if (body.confirm !== true) throw new HttpError(400, 'bad_request')\n await remoteProviders.mutate(async () => frpComponent.install())\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/frp/configure`) {\n const body = await readJsonObject(request, 4096)\n await remoteProviders.mutate(async () => {\n await frpConfig.configure(body)\n if (remoteControllers.frp.status().enabled) await remoteControllers.frp.reconnect()\n })\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/frp/component/purge`) {\n const body = await readJsonObject(request, 4096)\n if (body.confirm !== true) throw new HttpError(400, 'bad_request')\n await remoteProviders.mutate(async () => {\n await remoteControllers.frp.setEnabled(false)\n await Promise.all([frpComponent.purge(), frpConfig.purge()])\n })\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/control`) {\n const body = await readJsonObject(request, 4096)\n const running = body.running\n if (typeof running !== 'boolean') throw new HttpError(400, 'bad_request')\n await remoteProviders.mutate(async controller => controller.setEnabled(running))\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/reconnect`) {\n await readJsonObject(request, 4096)\n await remoteProviders.mutate(async controller => controller.reconnect())\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (request.method === 'POST' && target.decodedPathname === `${LOCAL_ADMIN_PREFIX}/remote/reset`) {\n const body = await readJsonObject(request, 4096)\n if (body.confirm !== true) throw new HttpError(400, 'bad_request')\n await remoteProviders.mutate(async controller => {\n await controller.reset()\n await rm(remoteDeviceFile, { force: true })\n })\n sendJson(response, 200, remotePayload(), false)\n return\n }\n if (target.decodedPathname.startsWith(`${LOCAL_ADMIN_PREFIX}/remote/`)) {\n const active = remoteController().gateway()\n if (active === undefined) throw new HttpError(409, 'gateway_stopped')\n await active.localAdminRoute(`${LOCAL_ADMIN_PREFIX}/remote`).handler(request, response)\n return\n }\n if (target.decodedPathname.startsWith(`${LOCAL_ADMIN_PREFIX}/lan/`)) {\n const active = lanGateway\n if (active === undefined) throw new HttpError(409, 'gateway_stopped')\n await active.localAdminRoute(`${LOCAL_ADMIN_PREFIX}/lan`).handler(request, response)\n return\n }\n const active = lanGateway\n if (active === undefined) throw new HttpError(409, 'gateway_stopped')\n await active.localAdminRoute().handler(request, response)\n } catch (error) {\n const mapped = mapAdminError(error)\n if (response.headersSent) response.destroy()\n else sendFailure(response, mapped.status, mapped.code, false)\n }\n },\n }\n\n await ctx.effect(async () => {\n const unregister = ctx.webServer.register(adminRoute)\n const disposeMobileCommand = ctx.commands.register({\n name: 'mobile',\n description: '按需求修改 DSH Mobile 的手机端界面或添加电脑端能力',\n input: { hint: '<要做什么>' },\n handler: ({ agent, rawInput }) => {\n const task = rawInput.trim()\n if (task === '') return { kind: 'error', text: '请带上需求,例如:/mobile 把手机端改成深色主题' }\n // A plugin-source message renders as a collapsed context-injection row\n // (label \"dsh-mobile\", one-line notice summary) instead of a user bubble,\n // while steering still wakes the agent with the full guide as input.\n agent.steer(createUserMessage({\n content: [{ type: 'text', text: `${MOBILE_CUSTOMIZATION_GUIDE}\\n\\n用户需求:${task}` }],\n source: {\n kind: 'plugin',\n plugin: 'dsh-mobile',\n form: 'notice',\n summary: boundContextSummary(`/mobile ${task}`),\n },\n }))\n return { kind: 'success', text: '已把需求交给 DSH 处理,改动会在手机端几秒内生效。' }\n },\n })\n try {\n await mobileAccess.startLocal(template.extensionsDir, ctx)\n await lanController.initialize()\n const stores: Record<RemoteProvider, JsonMobileAccessControlStore> = {\n tailscale: tailscaleStore,\n cpolar: cpolarStore,\n frp: frpStore,\n }\n await Promise.all((Object.keys(stores) as RemoteProvider[])\n .filter(provider => provider !== remoteProviders.selected)\n .map(provider => stores[provider].save({ version: 1, enabled: false })))\n for (const provider of ['tailscale', 'cpolar', 'frp'] as const) await remoteControllers[provider].initialize()\n } catch (error) {\n try {\n await settleCleanupSteps([\n unregister,\n disposeMobileCommand,\n async () => {\n const results = await Promise.allSettled(Object.values(remoteControllers).map(controller => controller.close()))\n const failures = results.filter(result => result.status === 'rejected').map(result => result.reason as unknown)\n if (failures.length > 0) throw new AggregateError(failures, 'remote provider cleanup failed')\n },\n () => lanController.close(),\n () => mobileAccess.stopLocal(),\n unregisterBuiltin,\n ])\n } catch (cleanupError) {\n throw new AggregateError([error, cleanupError], 'DSH Mobile initialization and cleanup failed')\n }\n throw error\n }\n return async () => {\n await settleCleanupSteps([\n unregister,\n disposeMobileCommand,\n async () => {\n const results = await Promise.allSettled(Object.values(remoteControllers).map(controller => controller.close()))\n const failures = results.filter(result => result.status === 'rejected').map(result => result.reason as unknown)\n if (failures.length > 0) throw new AggregateError(failures, 'remote provider cleanup failed')\n },\n () => lanController.close(),\n () => mobileAccess.stopLocal(),\n unregisterBuiltin,\n ])\n }\n }, 'dsh-mobile: independent LAN and selectable remote providers with /mobile command')\n}\n"],"mappings":"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"}
|