170 lines · 5.8 KB · TypeScript
RawDownload
// Secrets endpoints — set / list / status / resolve / remove round-trip// and error fidelity within a single org. import { describe, expect, it } from "@effect/vitest";import { Effect } from "effect"; import { ScopeId, SecretId } from "@executor/sdk"; import { asOrg } from "./__test-harness__/api-harness"; describe("secrets api (HTTP)", () => {  it.effect("set → list → resolve round-trips a new secret", () =>    Effect.gen(function* () {      const org = `org_${crypto.randomUUID()}`;      const id = `sec_${crypto.randomUUID().slice(0, 8)}`;       const setRef = yield* asOrg(org, (client) =>        client.secrets.set({          path: { scopeId: ScopeId.make(org) },          payload: { id: SecretId.make(id), name: "My API Token", value: "sk-test-abc" },        }),      );      expect(setRef.id).toBe(id);      expect(setRef.scopeId).toBe(org);       const list = yield* asOrg(org, (client) =>        client.secrets.list({ path: { scopeId: ScopeId.make(org) } }),      );      expect(list.find((s) => s.id === id)?.name).toBe("My API Token");       const resolved = yield* asOrg(org, (client) =>        client.secrets.resolve({          path: { scopeId: ScopeId.make(org), secretId: SecretId.make(id) },        }),      );      expect(resolved.value).toBe("sk-test-abc");    }),  );   it.effect("status is resolved for an existing secret, missing for an unknown id", () =>    Effect.gen(function* () {      const org = `org_${crypto.randomUUID()}`;      const id = `sec_${crypto.randomUUID().slice(0, 8)}`;       yield* asOrg(org, (client) =>        client.secrets.set({          path: { scopeId: ScopeId.make(org) },          payload: { id: SecretId.make(id), name: "n", value: "v" },        }),      );       const resolvedStatus = yield* asOrg(org, (client) =>        client.secrets.status({          path: { scopeId: ScopeId.make(org), secretId: SecretId.make(id) },        }),      );      expect(resolvedStatus.status).toBe("resolved");       const missingStatus = yield* asOrg(org, (client) =>        client.secrets.status({          path: {            scopeId: ScopeId.make(org),            secretId: SecretId.make(`missing_${crypto.randomUUID().slice(0, 8)}`),          },        }),      );      expect(missingStatus.status).toBe("missing");    }),  );   it.effect("remove deletes the secret; subsequent resolve fails and list drops it", () =>    Effect.gen(function* () {      const org = `org_${crypto.randomUUID()}`;      const id = `sec_${crypto.randomUUID().slice(0, 8)}`;       yield* asOrg(org, (client) =>        Effect.gen(function* () {          yield* client.secrets.set({            path: { scopeId: ScopeId.make(org) },            payload: { id: SecretId.make(id), name: "n", value: "v" },          });          yield* client.secrets.remove({            path: { scopeId: ScopeId.make(org), secretId: SecretId.make(id) },          });        }),      );       const list = yield* asOrg(org, (client) =>        client.secrets.list({ path: { scopeId: ScopeId.make(org) } }),      );      expect(list.map((s) => s.id)).not.toContain(id);       const afterResolve = yield* asOrg(org, (client) =>        client.secrets          .resolve({ path: { scopeId: ScopeId.make(org), secretId: SecretId.make(id) } })          .pipe(Effect.either),      );      expect(afterResolve._tag).toBe("Left");    }),  );   it.effect("resolve on an unknown id fails with a typed error", () =>    Effect.gen(function* () {      const org = `org_${crypto.randomUUID()}`;      const missing = `missing_${crypto.randomUUID().slice(0, 8)}`;       const result = yield* asOrg(org, (client) =>        client.secrets          .resolve({ path: { scopeId: ScopeId.make(org), secretId: SecretId.make(missing) } })          .pipe(Effect.either),      );      expect(result._tag).toBe("Left");      if (result._tag === "Left") {        // The API declares SecretNotFoundError / SecretResolutionError        // as typed errors; either is acceptable for an unknown id.        const err = result.left as { _tag?: string };        expect(          err._tag === "SecretNotFoundError" || err._tag === "SecretResolutionError",        ).toBe(true);      }    }),  );   it.effect("remove on an unknown id is a no-op (idempotent)", () =>    Effect.gen(function* () {      const org = `org_${crypto.randomUUID()}`;      const missing = `missing_${crypto.randomUUID().slice(0, 8)}`;       const result = yield* asOrg(org, (client) =>        client.secrets          .remove({ path: { scopeId: ScopeId.make(org), secretId: SecretId.make(missing) } })          .pipe(Effect.either),      );      expect(result._tag).toBe("Right");    }),  );   it.effect("set with the same id twice updates the value (upsert)", () =>    Effect.gen(function* () {      const org = `org_${crypto.randomUUID()}`;      const id = `sec_${crypto.randomUUID().slice(0, 8)}`;       const first = yield* asOrg(org, (client) =>        Effect.gen(function* () {          yield* client.secrets.set({            path: { scopeId: ScopeId.make(org) },            payload: { id: SecretId.make(id), name: "first", value: "first-value" },          });          return yield* client.secrets.resolve({            path: { scopeId: ScopeId.make(org), secretId: SecretId.make(id) },          });        }),      );      expect(first.value).toBe("first-value");       const second = yield* asOrg(org, (client) =>        Effect.gen(function* () {          yield* client.secrets.set({            path: { scopeId: ScopeId.make(org) },            payload: { id: SecretId.make(id), name: "updated", value: "second-value" },          });          return yield* client.secrets.resolve({            path: { scopeId: ScopeId.make(org), secretId: SecretId.make(id) },          });        }),      );      expect(second.value).toBe("second-value");    }),  );});