1import * as Cloudflare from "@/Cloudflare";
2import { CloudflareEnvironment } from "@/Cloudflare/CloudflareEnvironment";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as magicTransit from "@distilled.cloud/cloudflare/magic-transit";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8import { MinimumLogLevel } from "effect/References";
9
10const { test } = Test.make({ providers: Cloudflare.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17// Magic WAN sites (and their LANs / ACLs) are entitlement-gated. On the
18// standard testing account every site call fails with the typed
19// `MagicWanUnauthorized` error (Cloudflare code 1025) or `Forbidden` (403)
20// depending on token scope. The deploy path below is gated behind an
21// explicit opt-in env flag for entitled accounts; the read-only `list()`
22// assertion always runs because the provider maps those typed tags to `[]`.
23const entitled = !!process.env.CLOUDFLARE_TEST_MAGIC_WAN;
24
25// `list()` is a parent fan-out: it enumerates every Magic site (account
26// scope) then lists each site's ACLs. On an unentitled account both
27// `listSites` and `listSiteAcls` reject with the typed
28// `MagicWanUnauthorized` / `Forbidden` tags, which the provider swallows to
29// `[]` — so the read-only assertion is safe to run unconditionally. On an
30// entitled account (CLOUDFLARE_TEST_MAGIC_WAN=1) we deploy a site with two
31// LANs and an ACL, then assert the ACL shows up in the result.
32test.provider(
33 "list enumerates the deployed site ACLs",
34 (stack) =>
35 Effect.gen(function* () {
36 const { accountId } = yield* yield* CloudflareEnvironment;
37
38 yield* stack.destroy();
39
40 const provider = yield* Provider.findProvider(
41 Cloudflare.MagicTransit.MagicSiteAcl,
42 );
43
44 if (!entitled) {
45 // Unentitled: list() swallows the typed entitlement tag and yields [].
46 const all = yield* provider.list();
47 expect(Array.isArray(all)).toBe(true);
48 return;
49 }
50
51 const site = yield* stack.deploy(
52 Cloudflare.MagicTransit.MagicSite("ListSite", {
53 name: "alch-acl-list-site",
54 description: "alchemy site acl list test",
55 }),
56 );
57 const lan1 = yield* stack.deploy(
58 Cloudflare.MagicTransit.MagicSiteLan("ListLan1", {
59 siteId: site.siteId,
60 physport: 2,
61 name: "alch-acl-list-lan1",
62 vlanTag: 10,
63 staticAddressing: { address: "192.168.30.1/24" },
64 }),
65 );
66 const lan2 = yield* stack.deploy(
67 Cloudflare.MagicTransit.MagicSiteLan("ListLan2", {
68 siteId: site.siteId,
69 physport: 3,
70 name: "alch-acl-list-lan2",
71 vlanTag: 20,
72 staticAddressing: { address: "192.168.40.1/24" },
73 }),
74 );
75 const acl = yield* stack.deploy(
76 Cloudflare.MagicTransit.MagicSiteAcl("ListAcl", {
77 siteId: site.siteId,
78 name: "alch-acl-list",
79 lan1: { lanId: lan1.lanId, ports: [443] },
80 lan2: { lanId: lan2.lanId },
81 protocols: ["tcp"],
82 }),
83 );
84
85 const all = yield* provider.list();
86 expect(all.some((a) => a.aclId === acl.aclId)).toBe(true);
87 expect(
88 all.some((a) => a.name === "alch-acl-list" && a.siteId === site.siteId),
89 ).toBe(true);
90 // Every hydrated row carries the ambient account scope.
91 expect(all.every((a) => a.accountId === accountId)).toBe(true);
92
93 yield* stack.destroy();
94 }).pipe(logLevel),
95 {
96 tags: ["provider:cloudflare", "provider:cloudflare:magictransit", "live"],
97 timeout: 180_000,
98 },
99);
100
101test.provider(
102 "unentitled accounts surface the typed Magic WAN error for ACL listing",
103 (stack) =>
104 Effect.gen(function* () {
105 const { accountId } = yield* yield* CloudflareEnvironment;
106
107 yield* stack.destroy();
108
109 const canList = yield* magicTransit.listSites({ accountId }).pipe(
110 Effect.as(true),
111 Effect.catchTag(["MagicWanUnauthorized", "Forbidden"], () =>
112 Effect.succeed(false),
113 ),
114 );
115 if (canList) {
116 // Entitled account — the list test above covers real behavior.
117 yield* Effect.logInfo(
118 "account is Magic WAN-entitled; probe test is a no-op",
119 );
120 return;
121 }
122
123 // The typed tag — not UnknownCloudflareError, not a status check.
124 const error = yield* magicTransit
125 .listSites({ accountId })
126 .pipe(Effect.flip);
127 expect(["MagicWanUnauthorized", "Forbidden"]).toContain(error._tag);
128
129 // Despite the gating, list() degrades to an empty array.
130 const provider = yield* Provider.findProvider(
131 Cloudflare.MagicTransit.MagicSiteAcl,
132 );
133 expect(yield* provider.list()).toEqual([]);
134
135 yield* stack.destroy();
136 }).pipe(logLevel),
137 {
138 tags: ["provider:cloudflare", "provider:cloudflare:magictransit", "live"],
139 timeout: 120_000,
140 },
141);