From 4f7dc96badbdf8abdc70a40ebaafe4d06b3db859 Mon Sep 17 00:00:00 2001 From: gadzbi123 Date: Wed, 5 Aug 2026 22:31:57 +0200 Subject: [PATCH 1/2] fix(cli): repair bundled monitor permissions --- .../ResourceMonitorBinary.ts | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts b/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts index 1f14df51866..4c1ea531364 100644 --- a/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts +++ b/apps/server/src/resourceTelemetry/ResourceMonitorBinary.ts @@ -193,30 +193,41 @@ export const make = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(fu }); } - const candidates = [...overrideCandidates, ...bundledCandidates]; + const candidates = [ + ...overrideCandidates.map((path) => ({ path, bundled: false })), + ...bundledCandidates.map((path) => ({ path, bundled: true })), + ]; const resolve: ResourceMonitorBinary["Service"]["resolve"] = Effect.gen(function* () { for (const candidate of candidates) { - const exists = yield* fileSystem.exists(candidate).pipe(Effect.orElseSucceed(() => false)); + const exists = yield* fileSystem + .exists(candidate.path) + .pipe(Effect.orElseSucceed(() => false)); if (!exists) continue; if (platform !== "win32") { - const stat = yield* fileSystem.stat(candidate).pipe(Effect.option); + let stat = yield* fileSystem.stat(candidate.path).pipe(Effect.option); + if (candidate.bundled && Option.isSome(stat) && (stat.value.mode & 0o111) === 0) { + yield* fileSystem + .chmod(candidate.path, (stat.value.mode & 0o777) | 0o111) + .pipe(Effect.orElseSucceed(() => undefined)); + stat = yield* fileSystem.stat(candidate.path).pipe(Effect.option); + } if (Option.isSome(stat) && (stat.value.mode & 0o111) === 0) { return yield* new ResourceMonitorBinaryNotExecutable({ - path: candidate, + path: candidate.path, mode: stat.value.mode, }); } } - return candidate; + return candidate.path; } return yield* new ResourceMonitorBinaryNotFound({ platform, architecture, - candidates, + candidates: candidates.map((candidate) => candidate.path), }); }); From 20fe62294277a146dbf906f87a3f5c9b37b99af1 Mon Sep 17 00:00:00 2001 From: gadzbi123 Date: Wed, 5 Aug 2026 22:31:57 +0200 Subject: [PATCH 2/2] test(cli): cover bundled monitor permission repair --- .../ResourceMonitorBinary.test.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/server/src/resourceTelemetry/ResourceMonitorBinary.test.ts b/apps/server/src/resourceTelemetry/ResourceMonitorBinary.test.ts index 4c3afa97abf..55c02c074a2 100644 --- a/apps/server/src/resourceTelemetry/ResourceMonitorBinary.test.ts +++ b/apps/server/src/resourceTelemetry/ResourceMonitorBinary.test.ts @@ -7,11 +7,38 @@ import { import { assert, describe, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; +import * as Path from "effect/Path"; import { ServerConfig } from "../config.ts"; import * as ResourceMonitorBinary from "./ResourceMonitorBinary.ts"; describe("ResourceMonitorBinary", () => { + it.effect("repairs a non-executable bundled monitor", () => + Effect.gen(function* () { + const fileSystem = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const baseDir = yield* fileSystem.makeTempDirectoryScoped({ + prefix: "t3-resource-monitor-binary-", + }); + const binaryPath = `${baseDir}/t3-resource-monitor`; + yield* fileSystem.writeFileString(binaryPath, "binary"); + yield* fileSystem.chmod(binaryPath, 0o644); + + const service = yield* ResourceMonitorBinary.make().pipe( + Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)), + Effect.provideService(HostProcessPlatform, "linux"), + Effect.provideService(HostProcessArchitecture, "x64"), + Effect.provideService(ResourceMonitorBinary.ResourceMonitorHostLinuxLibc, "gnu"), + Effect.provideService(HostProcessEnvironment, {}), + Effect.provideService(Path.Path, { ...path, resolve: () => binaryPath }), + ); + + assert.equal(yield* service.resolve, binaryPath); + const stat = yield* fileSystem.stat(binaryPath); + assert.notEqual(stat.mode & 0o111, 0); + }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), + ); + it.effect("resolves an executable override", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem;