1import * as AWS from "@/AWS";
2import { Session } from "@/AWS/Macie2/Session.ts";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as macie2 from "@distilled.cloud/aws/macie2";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8import { makeMacie2TestLease } from "./TestLease.ts";
9
10const { test, beforeAll, afterAll } = Test.make({ providers: AWS.providers() });
11const testLease = makeMacie2TestLease();
12
13// Lease acquisition may queue behind the complete lifecycle of every other
14// Macie file. This does not widen any cloud-operation polling budget.
15beforeAll(testLease.acquire, { timeout: 3_600_000 });
16afterAll(testLease.release);
17
18// `getMacieSession` throws `AccessDeniedException` ("Macie is not enabled")
19// when the account has no session.
20const getSession = macie2.getMacieSession({}).pipe(
21 Effect.map((s) => s as macie2.GetMacieSessionResponse | undefined),
22 Effect.catchTag("AccessDeniedException", () => Effect.succeed(undefined)),
23 Effect.catchTag("ResourceNotFoundException", () => Effect.succeed(undefined)),
24);
25
26// The Macie session is an account/region singleton. This test only runs when
27// Macie is not already enabled — it must never disable a session the user
28// already operates (capture-and-restore safety).
29test.provider(
30 "lifecycle: enable Macie, update frequency, disable",
31 (stack) =>
32 Effect.gen(function* () {
33 const preexisting = yield* getSession;
34 if (preexisting) {
35 yield* Effect.logInfo(
36 "Macie already enabled — skipping destructive lifecycle test",
37 );
38 return;
39 }
40
41 yield* stack.destroy();
42
43 // Create — enable Macie with six-hour publishing.
44 const created = yield* stack.deploy(
45 Effect.gen(function* () {
46 return yield* Session("Macie", {
47 status: "ENABLED",
48 findingPublishingFrequency: "SIX_HOURS",
49 });
50 }),
51 );
52 expect(created.status).toBe("ENABLED");
53 expect(created.findingPublishingFrequency).toBe("SIX_HOURS");
54
55 // Out-of-band verification.
56 const live = yield* macie2.getMacieSession({});
57 expect(live.status).toBe("ENABLED");
58 expect(live.findingPublishingFrequency).toBe("SIX_HOURS");
59
60 // Canonical list() coverage.
61 const provider = yield* Provider.findProvider(Session);
62 const all = yield* provider.list();
63 expect(all.some((s) => s.status === "ENABLED")).toBe(true);
64
65 // Update — change frequency + pause in place (no replacement).
66 const updated = yield* stack.deploy(
67 Effect.gen(function* () {
68 return yield* Session("Macie", {
69 status: "PAUSED",
70 findingPublishingFrequency: "FIFTEEN_MINUTES",
71 });
72 }),
73 );
74 expect(updated.accountId).toBe(created.accountId);
75 const afterUpdate = yield* macie2.getMacieSession({});
76 expect(afterUpdate.status).toBe("PAUSED");
77 expect(afterUpdate.findingPublishingFrequency).toBe("FIFTEEN_MINUTES");
78
79 // Destroy — Macie is disabled and the account is unenrolled.
80 yield* stack.destroy();
81 const after = yield* getSession;
82 expect(after).toBeUndefined();
83 }),
84 { tags: ["provider:aws", "provider:aws:macie2", "live"], timeout: 180_000 },
85);