Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/server/src/policy/ManagedPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,10 @@ const make = Effect.gen(function* () {
const policy = yield* Option.match(devPath, {
onSome: load,
onNone: () =>
readManagedPolicy(platform).pipe(
readManagedPolicy(
platform,
ManagedProviders.knownDriverLabels().map(({ driver }) => driver),
).pipe(
Effect.flatMap((found) =>
fromDocument(found?.source ?? managedPolicyPath(platform), found?.document),
),
Expand Down
15 changes: 11 additions & 4 deletions packages/shared/src/managedPolicyFile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ describe("readManagedPolicy", () => {
Effect.gen(function* () {
const organization = text("Organization", "Société 日本 ✓");
const document = (registry: RegistryAnswer) =>
readManagedPolicy("win32").pipe(
readManagedPolicy("win32", ["codex", "claudeAgent"]).pipe(
Effect.map((found): unknown => found?.document),
Effect.catchTags({
ManagedPolicyFileError: (error) => Effect.succeed(`error: ${error.reason}`),
Expand All @@ -233,7 +233,10 @@ describe("readManagedPolicy", () => {
dword("AllowedDrivers", 1),
],
// Registry names ignore case, so a subkey written in other case still counts.
{ clients: { desktop: 1, remote: 0 }, AllowedDrivers: { codex: 1, claudeAgent: 1 } },
{
clients: { Desktop: 1, "LOCAL-BROWSER": 1, REMOTE: 1 },
AllowedDrivers: { Codex: 1, CLAUDEAGENT: 1, UnknownDriver: 1 },
},
),
),
{
Expand All @@ -244,8 +247,8 @@ describe("readManagedPolicy", () => {
maxRuntimeMode: "auto-accept-edits",
telemetry: false,
updates: { mode: "off", allowNightly: true },
clients: ["desktop"],
providers: { allowedDrivers: ["codex", "claudeAgent"] },
clients: ["desktop", "local-browser", "remote"],
providers: { allowedDrivers: ["codex", "claudeAgent", "UnknownDriver"] },
},
},
);
Expand Down Expand Up @@ -295,6 +298,10 @@ describe("readManagedPolicy", () => {
],
[policyKey([organization, text("Settings", "{")]), "not valid JSON"],
[policyKey([organization, dword("Clients", 2)]), "DWORD of 0 or 1"],
[
policyKey([organization, dword("Clients", 1)], { Clients: { UnknownClient: 1 } }),
"does not match the policy schema",
],
[
policyKey([organization, dword("Clients", 1)], { Clients: { desktop: 0 } }),
"does not match the policy schema",
Expand Down
20 changes: 15 additions & 5 deletions packages/shared/src/managedPolicyFile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ManagedPolicyDocument } from "@t3tools/contracts";
import { ManagedPolicyClient, ManagedPolicyDocument } from "@t3tools/contracts";
import * as Cause from "effect/Cause";
import * as Context from "effect/Context";
import * as Duration from "effect/Duration";
Expand Down Expand Up @@ -369,6 +369,7 @@ const dwordBoolean = (value: RegistryValue) =>
*/
function windowsPolicyDocument(
values: ReadonlyArray<PolicyRegistryValue>,
knownDrivers: ReadonlyArray<string>,
): { readonly document: unknown } | { readonly error: string } {
// Registry names ignore case; a hand-written `organization` is still Organization.
const canonical = new Map(
Expand Down Expand Up @@ -407,7 +408,12 @@ function windowsPolicyDocument(
if (checked === undefined) return { error: `${where} must be a DWORD of 0 or 1` };
const list = lists.get(value.key) ?? [];
lists.set(value.key, list);
if (checked) list.push(value.name);
if (checked) {
const names = value.key === "Clients" ? ManagedPolicyClient.literals : knownDrivers;
list.push(
names.find((name) => name.toLowerCase() === value.name.toLowerCase()) ?? value.name,
);
}
continue;
}
if (Object.hasOwn(WINDOWS_POLICY_GROUPS, value.name)) continue;
Expand Down Expand Up @@ -476,7 +482,10 @@ function unwrapForced(json: string): unknown {
}

/** Read the policy a configuration profile or Group Policy set; absent means no such policy. */
const readPlatformPolicy = Effect.fnUntraced(function* (platform: NodeJS.Platform) {
const readPlatformPolicy = Effect.fnUntraced(function* (
platform: NodeJS.Platform,
knownDrivers: ReadonlyArray<string>,
) {
if (platform === "darwin") {
const path = MACOS_MANAGED_PREFERENCES_PATH;
const exists = yield* (yield* FileSystem.FileSystem)
Expand Down Expand Up @@ -543,7 +552,7 @@ const readPlatformPolicy = Effect.fnUntraced(function* (platform: NodeJS.Platfor
}
values.push(...checkboxes.values.map((value) => ({ ...value, key: list })));
}
const built = windowsPolicyDocument(values);
const built = windowsPolicyDocument(values, knownDrivers);
if ("error" in built) return yield* refuse(built.error);
// An empty key, or one holding only policies set to Disabled, sets nothing.
if (built.document === undefined) return undefined;
Expand All @@ -559,10 +568,11 @@ const readPlatformPolicy = Effect.fnUntraced(function* (platform: NodeJS.Platfor
*/
export const readManagedPolicy = Effect.fn("readManagedPolicy")(function* (
platform: NodeJS.Platform,
knownDrivers: ReadonlyArray<string> = [],
) {
const filePath = managedPolicyPath(platform);
const [platformPolicy, file] = yield* Effect.all([
readPlatformPolicy(platform),
readPlatformPolicy(platform, knownDrivers),
readManagedPolicyFile(filePath),
]);
if (platformPolicy !== undefined && file !== undefined) {
Expand Down
Loading