307
*/
308
export function pickManagedSettings(nativeMdm: ManagedSettingsData | undefined, server: ManagedSettingsData | undefined, file: ManagedSettingsData | undefined): IManagedSettingsPick {
309
>
const bags: Record<ManagedSettingsChannel, ManagedSettingsData | undefined> = { nativeMdm, server, file };
copilotManagedSettings.ts
310
>
311
>
// Walk channels highest-precedence first: the first channel to supply a key wins, and later
312
>
// channels are appended as overridden contributions for provenance.
313
>
const resolutions = new Map<string, { value: ManagedSettingValue; source: ManagedSettingsChannel; contributions: IManagedSettingsContribution[] }>();
314
>
for (const channel of MANAGED_SETTINGS_CHANNELS) {
315
>
const bag = bags[channel];
316
>
if (!bag) {
317
continue;
318
}
320
>
// inherited enumerable properties the way `for...in` would.
321
>
for (const key of Object.keys(bag)) {
322
>
const value = bag[key];
323
>
if (value === undefined) {
324
continue;
325
}
327
>
if (existing) {
328
existing.contributions.push({ channel, value });
330
>
resolutions.set(key, { value, source: channel, contributions: [{ channel, value }] });
331
>
}
332
>
}
333
>
}
334
>
335
>
const activeSources = new Set<ManagedSettingsChannel>();
336
>
const entries: [string, ManagedSettingValue][] = [];
337
>
for (const [key, resolution] of resolutions) {
338
>
entries.push([key, resolution.value]);
339
>
activeSources.add(resolution.source);
340
>
}
341
>
342
>
return {
343
>
// Build via Object.fromEntries (define-property semantics) rather than bracket assignment so
344
>
// an untrusted `__proto__` key can't corrupt the merged bag's prototype chain.
345
>
values: Object.fromEntries(entries),
346
>
resolutions,
347
>
// Preserve precedence order for a stable, readable report.
348
>
activeSources: MANAGED_SETTINGS_CHANNELS.filter(channel => activeSources.has(channel)),
349
>
};
350
>
}
351
352
// --- File-based managed settings ---