268 lines · 9.8 KB · TypeScript
RawDownload
import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, it } from "@effect/vitest";import * as Cause from "effect/Cause";import * as Deferred from "effect/Deferred";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Ref from "effect/Ref";import * as PlatformError from "effect/PlatformError"; import * as ServerConfig from "../config.ts";import * as ServerSecretStore from "./ServerSecretStore.ts"; const makeServerConfigLayer = () =>  ServerConfig.layerTest(process.cwd(), { prefix: "t3-secret-store-test-" }); const makeServerSecretStoreLayer = () =>  Layer.provide(ServerSecretStore.layer, makeServerConfigLayer()); const PermissionDeniedFileSystemLayer = Layer.effect(  FileSystem.FileSystem,  Effect.gen(function* () {    const fileSystem = yield* FileSystem.FileSystem;     return {      ...fileSystem,      readFile: (path) =>        Effect.fail(          PlatformError.systemError({            _tag: "PermissionDenied",            module: "FileSystem",            method: "readFile",            pathOrDescriptor: path,            description: "Permission denied while reading secret file.",          }),        ),    } satisfies FileSystem.FileSystem;  }),).pipe(Layer.provide(NodeServices.layer)); const makePermissionDeniedSecretStoreLayer = () =>  ServerSecretStore.layer.pipe(    Layer.provide(makeServerConfigLayer()),    Layer.provideMerge(PermissionDeniedFileSystemLayer),  ); const RenameFailureFileSystemLayer = Layer.effect(  FileSystem.FileSystem,  Effect.gen(function* () {    const fileSystem = yield* FileSystem.FileSystem;     return {      ...fileSystem,      rename: (from, to) =>        Effect.fail(          PlatformError.systemError({            _tag: "PermissionDenied",            module: "FileSystem",            method: "rename",            pathOrDescriptor: `${String(from)} -> ${String(to)}`,            description: "Permission denied while persisting secret file.",          }),        ),    } satisfies FileSystem.FileSystem;  }),).pipe(Layer.provide(NodeServices.layer)); const makeRenameFailureSecretStoreLayer = () =>  ServerSecretStore.layer.pipe(    Layer.provide(makeServerConfigLayer()),    Layer.provideMerge(RenameFailureFileSystemLayer),  ); const RemoveFailureFileSystemLayer = Layer.effect(  FileSystem.FileSystem,  Effect.gen(function* () {    const fileSystem = yield* FileSystem.FileSystem;     return {      ...fileSystem,      remove: (path, options) =>        Effect.fail(          PlatformError.systemError({            _tag: "PermissionDenied",            module: "FileSystem",            method: "remove",            pathOrDescriptor: String(path),            description: `Permission denied while removing secret file.${options ? " options-set" : ""}`,          }),        ),    } satisfies FileSystem.FileSystem;  }),).pipe(Layer.provide(NodeServices.layer)); const makeRemoveFailureSecretStoreLayer = () =>  ServerSecretStore.layer.pipe(    Layer.provide(makeServerConfigLayer()),    Layer.provideMerge(RemoveFailureFileSystemLayer),  ); const ConcurrentReadMissFileSystemLayer = Layer.effect(  FileSystem.FileSystem,  Effect.gen(function* () {    const fileSystem = yield* FileSystem.FileSystem;    const readCountRef = yield* Ref.make(0);    const readBarrier = yield* Deferred.make<void>();     return {      ...fileSystem,      readFile: (path) =>        String(path).endsWith("/session-signing-key.bin")          ? Ref.updateAndGet(readCountRef, (count) => count + 1).pipe(              Effect.flatMap((count) => {                if (count > 2) {                  return fileSystem.readFile(path);                }                return Effect.gen(function* () {                  if (count === 2) {                    yield* Deferred.succeed(readBarrier, void 0);                  }                  yield* Deferred.await(readBarrier);                  return yield* Effect.failCause(                    Cause.fail(                      PlatformError.systemError({                        _tag: "NotFound",                        module: "FileSystem",                        method: "readFile",                        pathOrDescriptor: String(path),                        description: "Secret file does not exist yet.",                      }),                    ),                  );                });              }),            )          : fileSystem.readFile(path),    } satisfies FileSystem.FileSystem;  }),).pipe(Layer.provide(NodeServices.layer)); const makeConcurrentCreateSecretStoreLayer = () =>  ServerSecretStore.layer.pipe(    Layer.provide(makeServerConfigLayer()),    Layer.provideMerge(ConcurrentReadMissFileSystemLayer),  ); it.layer(NodeServices.layer)("ServerSecretStore.layer", (it) => {  it.effect("returns Option.none when a secret file does not exist", () =>    Effect.gen(function* () {      const secretStore = yield* ServerSecretStore.ServerSecretStore;       const secret = yield* secretStore.get("missing-secret");       assert.isTrue(Option.isNone(secret));    }).pipe(Effect.provide(makeServerSecretStoreLayer())),  );   it.effect("reuses an existing secret instead of regenerating it", () =>    Effect.gen(function* () {      const secretStore = yield* ServerSecretStore.ServerSecretStore;       const first = yield* secretStore.getOrCreateRandom("session-signing-key", 32);      const second = yield* secretStore.getOrCreateRandom("session-signing-key", 32);       assert.deepEqual(Array.from(second), Array.from(first));    }).pipe(Effect.provide(makeServerSecretStoreLayer())),  );   it.effect("returns the persisted secret when concurrent creators race", () =>    Effect.gen(function* () {      const secretStore = yield* ServerSecretStore.ServerSecretStore;       const [first, second] = yield* Effect.all(        [          secretStore.getOrCreateRandom("session-signing-key", 32),          secretStore.getOrCreateRandom("session-signing-key", 32),        ],        { concurrency: "unbounded" },      );      const persisted = yield* secretStore.get("session-signing-key");      const persistedBytes = Option.getOrThrow(persisted);       assert.deepEqual(Array.from(first), Array.from(persistedBytes));      assert.deepEqual(Array.from(second), Array.from(persistedBytes));    }).pipe(Effect.provide(makeConcurrentCreateSecretStoreLayer())),  );   it.effect("uses restrictive permissions for the secret directory and files", () =>    Effect.gen(function* () {      const chmodCalls: Array<{ readonly path: string; readonly mode: number }> = [];      const recordingFileSystemLayer = Layer.effect(        FileSystem.FileSystem,        Effect.gen(function* () {          const fileSystem = yield* FileSystem.FileSystem;           return {            ...fileSystem,            makeDirectory: () => Effect.void,            writeFile: () => Effect.void,            rename: () => Effect.void,            chmod: (path, mode) =>              Effect.sync(() => {                chmodCalls.push({ path: String(path), mode });              }),          } satisfies FileSystem.FileSystem;        }),      ).pipe(Layer.provide(NodeServices.layer));       const secretStore = yield* Effect.service(ServerSecretStore.ServerSecretStore).pipe(        Effect.provide(          ServerSecretStore.layer.pipe(            Layer.provide(makeServerConfigLayer()),            Layer.provideMerge(recordingFileSystemLayer),          ),        ),      );       yield* secretStore.set("session-signing-key", Uint8Array.from([1, 2, 3]));       assert.isTrue(        chmodCalls.some((call) => call.mode === 0o700 && call.path.endsWith("/secrets")),      );      assert.isAtLeast(chmodCalls.filter((call) => call.mode === 0o600).length, 2);    }).pipe(Effect.provide(NodeServices.layer)),  );   it.effect("propagates read failures other than missing-file errors", () =>    Effect.gen(function* () {      const secretStore = yield* ServerSecretStore.ServerSecretStore;       const error = yield* Effect.flip(secretStore.getOrCreateRandom("session-signing-key", 32));       assert.instanceOf(error, ServerSecretStore.SecretStoreReadError);      assert.include(error.message, "Failed to read secret session-signing-key.");      assert.instanceOf(error.cause, PlatformError.PlatformError);      assert.equal((error.cause as PlatformError.PlatformError).reason._tag, "PermissionDenied");    }).pipe(Effect.provide(makePermissionDeniedSecretStoreLayer())),  );   it.effect("propagates write failures instead of treating them as success", () =>    Effect.gen(function* () {      const secretStore = yield* ServerSecretStore.ServerSecretStore;       const error = yield* Effect.flip(        secretStore.set("session-signing-key", Uint8Array.from([1, 2, 3])),      );       assert.instanceOf(error, ServerSecretStore.SecretStorePersistError);      assert.include(error.message, "Failed to persist secret session-signing-key.");      assert.instanceOf(error.cause, PlatformError.PlatformError);      assert.equal((error.cause as PlatformError.PlatformError).reason._tag, "PermissionDenied");    }).pipe(Effect.provide(makeRenameFailureSecretStoreLayer())),  );   it.effect("propagates remove failures other than missing-file errors", () =>    Effect.gen(function* () {      const secretStore = yield* ServerSecretStore.ServerSecretStore;       const error = yield* Effect.flip(secretStore.remove("session-signing-key"));       assert.instanceOf(error, ServerSecretStore.SecretStoreRemoveError);      assert.include(error.message, "Failed to remove secret session-signing-key.");      assert.instanceOf(error.cause, PlatformError.PlatformError);      assert.equal((error.cause as PlatformError.PlatformError).reason._tag, "PermissionDenied");    }).pipe(Effect.provide(makeRemoveFailureSecretStoreLayer())),  );});