import { expect, it } from "@effect/vitest";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option"; import * as AuthConnectClients from "../persistence/AuthConnectClients.ts";import * as ServerSecretStore from "./ServerSecretStore.ts";import * as ConnectClientStore from "./ConnectClientStore.ts"; const textEncoder = new TextEncoder();const requestedAt = DateTime.makeUnsafe("2026-06-27T12:00:00.000Z");const approvedAt = DateTime.makeUnsafe("2026-06-27T12:05:00.000Z");const rejectedAt = DateTime.makeUnsafe("2026-06-27T12:06:00.000Z"); const approvedRecord: AuthConnectClients.AuthConnectClientRecord = { clientProofKeyThumbprint: "client-thumbprint", cloudUserId: "cloud-user", deviceId: "device-1", status: "approved", client: { label: "Client", ipAddress: null, userAgent: null, deviceType: "desktop", os: "macOS", browser: null, }, requestedAt, updatedAt: approvedAt, approvedAt, rejectedAt: null, revokedAt: null, lastSeenAt: null,}; const makeSecretStoreLayer = (mode: string) => Layer.succeed( ServerSecretStore.ServerSecretStore, ServerSecretStore.ServerSecretStore.of({ get: () => Effect.succeed(Option.some(textEncoder.encode(mode))), set: () => Effect.void, create: () => Effect.void, getOrCreateRandom: () => Effect.succeed(new Uint8Array()), remove: () => Effect.void, }), ); const secretStoreLayer = makeSecretStoreLayer("client-approval"); const makeStoreOnlyLayer = (mode: string) => Layer.effect(ConnectClientStore.ConnectClientStore, ConnectClientStore.make).pipe( Layer.provide(makeSecretStoreLayer(mode)), Layer.provide( Layer.succeed( AuthConnectClients.AuthConnectClientRepository, AuthConnectClients.AuthConnectClientRepository.of({ upsertRequest: () => Effect.succeed(approvedRecord), updateStatus: () => Effect.succeed(Option.none()), revoke: () => Effect.succeed(false), markSeen: () => Effect.succeed(Option.some(approvedRecord)), listActive: () => Effect.succeed([]), }), ), ), ); const makeStoreLayer = ( overrides: Partial<AuthConnectClients.AuthConnectClientRepository["Service"]>,) => Layer.effect(ConnectClientStore.ConnectClientStore, ConnectClientStore.make).pipe( Layer.provide(secretStoreLayer), Layer.provide( Layer.succeed( AuthConnectClients.AuthConnectClientRepository, AuthConnectClients.AuthConnectClientRepository.of({ upsertRequest: () => Effect.succeed(approvedRecord), updateStatus: () => Effect.succeed(Option.none()), revoke: () => Effect.succeed(false), markSeen: () => Effect.succeed(Option.some(approvedRecord)), listActive: () => Effect.succeed([]), ...overrides, }), ), ), ); it.effect("fails closed when persisted security mode is invalid", () => Effect.gen(function* () { const store = yield* ConnectClientStore.ConnectClientStore; const error = yield* Effect.flip(store.getSecurityMode()); expect(error._tag).toBe("ConnectSecurityModeLoadError"); }).pipe(Effect.provide(makeStoreOnlyLayer("invalid-mode"))),); it.effect("returns rejected when an approved client is rejected before last-seen update", () => Effect.gen(function* () { const store = yield* ConnectClientStore.ConnectClientStore; const authorization = yield* store.requestClient({ cloudUserId: "cloud-user", clientProofKeyThumbprint: "client-thumbprint", }); expect(authorization.mode).toBe("client-approval"); expect(authorization.status).toBe("rejected"); }).pipe( Effect.provide( makeStoreLayer({ markSeen: () => Effect.succeed( Option.some({ ...approvedRecord, status: "rejected", updatedAt: rejectedAt, rejectedAt, }), ), }), ), ),); it.effect("returns pending when an approved client is revoked before last-seen update", () => Effect.gen(function* () { const store = yield* ConnectClientStore.ConnectClientStore; const authorization = yield* store.requestClient({ cloudUserId: "cloud-user", clientProofKeyThumbprint: "client-thumbprint", }); expect(authorization.mode).toBe("client-approval"); expect(authorization.status).toBe("pending"); if (authorization.mode === "client-approval") { expect(authorization.client.status).toBe("pending"); expect(authorization.client.approvedAt).toBeNull(); expect(authorization.client.lastSeenAt).toBeNull(); } }).pipe( Effect.provide( makeStoreLayer({ markSeen: () => Effect.succeed(Option.none()), }), ), ),);
import { expect, it } from "@effect/vitest";
import * as DateTime from "effect/DateTime";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as AuthConnectClients from "../persistence/AuthConnectClients.ts";
import * as ServerSecretStore from "./ServerSecretStore.ts";
import * as ConnectClientStore from "./ConnectClientStore.ts";
const textEncoder = new TextEncoder();
const requestedAt = DateTime.makeUnsafe("2026-06-27T12:00:00.000Z");
const approvedAt = DateTime.makeUnsafe("2026-06-27T12:05:00.000Z");
const rejectedAt = DateTime.makeUnsafe("2026-06-27T12:06:00.000Z");
const approvedRecord: AuthConnectClients.AuthConnectClientRecord = {
clientProofKeyThumbprint: "client-thumbprint",
cloudUserId: "cloud-user",
deviceId: "device-1",
status: "approved",
client: {
label: "Client",
ipAddress: null,
userAgent: null,
deviceType: "desktop",
os: "macOS",
browser: null,
},
requestedAt,
updatedAt: approvedAt,
approvedAt,
rejectedAt: null,
revokedAt: null,
lastSeenAt: null,
};
const makeSecretStoreLayer = (mode: string) =>
Layer.succeed(
ServerSecretStore.ServerSecretStore,
ServerSecretStore.ServerSecretStore.of({
get: () => Effect.succeed(Option.some(textEncoder.encode(mode))),
set: () => Effect.void,
create: () => Effect.void,
getOrCreateRandom: () => Effect.succeed(new Uint8Array()),
remove: () => Effect.void,
}),
);
const secretStoreLayer = makeSecretStoreLayer("client-approval");
const makeStoreOnlyLayer = (mode: string) =>
Layer.effect(ConnectClientStore.ConnectClientStore, ConnectClientStore.make).pipe(
Layer.provide(makeSecretStoreLayer(mode)),
Layer.provide(
Layer.succeed(
AuthConnectClients.AuthConnectClientRepository,
AuthConnectClients.AuthConnectClientRepository.of({
upsertRequest: () => Effect.succeed(approvedRecord),
updateStatus: () => Effect.succeed(Option.none()),
revoke: () => Effect.succeed(false),
markSeen: () => Effect.succeed(Option.some(approvedRecord)),
listActive: () => Effect.succeed([]),
}),
),
),
);
const makeStoreLayer = (
overrides: Partial<AuthConnectClients.AuthConnectClientRepository["Service"]>,
) =>
Layer.effect(ConnectClientStore.ConnectClientStore, ConnectClientStore.make).pipe(
Layer.provide(secretStoreLayer),
Layer.provide(
Layer.succeed(
AuthConnectClients.AuthConnectClientRepository,
AuthConnectClients.AuthConnectClientRepository.of({
upsertRequest: () => Effect.succeed(approvedRecord),
updateStatus: () => Effect.succeed(Option.none()),
revoke: () => Effect.succeed(false),
markSeen: () => Effect.succeed(Option.some(approvedRecord)),
listActive: () => Effect.succeed([]),
...overrides,
}),
),
),
);
it.effect("fails closed when persisted security mode is invalid", () =>
Effect.gen(function* () {
const store = yield* ConnectClientStore.ConnectClientStore;
const error = yield* Effect.flip(store.getSecurityMode());
expect(error._tag).toBe("ConnectSecurityModeLoadError");
}).pipe(Effect.provide(makeStoreOnlyLayer("invalid-mode"))),
);
it.effect("returns rejected when an approved client is rejected before last-seen update", () =>
Effect.gen(function* () {
const store = yield* ConnectClientStore.ConnectClientStore;
const authorization = yield* store.requestClient({
cloudUserId: "cloud-user",
clientProofKeyThumbprint: "client-thumbprint",
});
expect(authorization.mode).toBe("client-approval");
expect(authorization.status).toBe("rejected");
}).pipe(
Effect.provide(
makeStoreLayer({
markSeen: () =>
Effect.succeed(
Option.some({
...approvedRecord,
status: "rejected",
updatedAt: rejectedAt,
rejectedAt,
}),
),
}),
),
),
);
it.effect("returns pending when an approved client is revoked before last-seen update", () =>
Effect.gen(function* () {
const store = yield* ConnectClientStore.ConnectClientStore;
const authorization = yield* store.requestClient({
cloudUserId: "cloud-user",
clientProofKeyThumbprint: "client-thumbprint",
});
expect(authorization.mode).toBe("client-approval");
expect(authorization.status).toBe("pending");
if (authorization.mode === "client-approval") {
expect(authorization.client.status).toBe("pending");
expect(authorization.client.approvedAt).toBeNull();
expect(authorization.client.lastSeenAt).toBeNull();
}
}).pipe(
Effect.provide(
makeStoreLayer({
markSeen: () => Effect.succeed(Option.none()),
}),
),
),
);