|
|
@@ -24,6 +24,9 @@ import type {} from '@deepseek-ai/dsh-host-webserver'
|
|
|
const PROFILE_DIR = '.dsh-tmp-profile'
|
|
|
const PROFILE_FILE = 'config.json'
|
|
|
|
|
|
+/** The session-telemetry row id the DSH_TELEMETRY_DISABLED switch targets (mounted in web.cordis.yml). */
|
|
|
+const TELEMETRY_ROW_ID = 'telemetry-otel'
|
|
|
+
|
|
|
/** The webserver schema's all-interfaces bind literal: gates LAN-authority derivation here and the printed LAN URL in web.ts. */
|
|
|
const ALL_INTERFACES_HOST = '0.0.0.0'
|
|
|
|
|
|
@@ -59,6 +62,24 @@ export function resolveLanTrust(
|
|
|
return { lanAddresses, trustedHosts: [...lanAddresses, ...extra] }
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Resolve the telemetry opt-out switch into its boot patch. ANY non-empty
|
|
|
+ * value (including `'0'`/`'false'`) disables: a privacy switch prefers
|
|
|
+ * off-by-mistake over on-by-mistake. Throws when the switch is set but the
|
|
|
+ * row is absent — a silently no-op "disabled" privacy switch would keep
|
|
|
+ * exporting while the user believes it is off.
|
|
|
+ * @param disabledEnv - the raw `DSH_TELEMETRY_DISABLED` value (`undefined` when unset).
|
|
|
+ * @param hasRow - whether the composition carries the {@link TELEMETRY_ROW_ID} row.
|
|
|
+ * @returns the disable patch, or `undefined` when telemetry stays enabled.
|
|
|
+ */
|
|
|
+export function resolveTelemetryPatch(disabledEnv: string | undefined, hasRow: boolean): PatchOptions | undefined {
|
|
|
+ if ((disabledEnv ?? '') === '') return undefined
|
|
|
+ if (!hasRow) {
|
|
|
+ throw new Error(`dsh: DSH_TELEMETRY_DISABLED is set but row "${TELEMETRY_ROW_ID}" is not in this composition`)
|
|
|
+ }
|
|
|
+ return { id: TELEMETRY_ROW_ID, disabled: true }
|
|
|
+}
|
|
|
+
|
|
|
/** One profile-json key mapped onto a yml row's config field. */
|
|
|
interface ProfileMapping {
|
|
|
jsonPath: string
|
|
|
@@ -207,9 +228,8 @@ export class AppCLIEntry {
|
|
|
// Telemetry opt-out: a row can only be turned off at the patch layer
|
|
|
// (config cannot disable an entry), and the switch must hold BEFORE the
|
|
|
// plugin constructs — its exporter.url validation is load-time fail-loud.
|
|
|
- if ((process.env.DSH_TELEMETRY_DISABLED ?? '') !== '') {
|
|
|
- this.patches.push({ id: 'telemetry-otel', disabled: true })
|
|
|
- }
|
|
|
+ const telemetryPatch = resolveTelemetryPatch(process.env.DSH_TELEMETRY_DISABLED, rows.has(TELEMETRY_ROW_ID))
|
|
|
+ if (telemetryPatch !== undefined) this.patches.push(telemetryPatch)
|
|
|
}
|
|
|
|
|
|
/** Shared Loader boot; the dev HMR row mounts before await so the fail-loud sweep covers it. */
|