domainkit 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +26 -26
  2. package/dist/index.d.mts +639 -187
  3. package/dist/index.mjs +301 -300
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/promise.d.mts +464 -0
  6. package/dist/promise.mjs +636 -0
  7. package/dist/promise.mjs.map +1 -0
  8. package/dist/{resolver-CxE-VDw4.mjs → resolver-CvK7JoJM.mjs} +401 -54
  9. package/dist/resolver-CvK7JoJM.mjs.map +1 -0
  10. package/dist/{resolver-Dc0hwV-J.d.mts → resolver-uqe1h5Vz.d.mts} +1513 -25
  11. package/dist/testing.d.mts +4 -5
  12. package/dist/testing.mjs +17 -3
  13. package/dist/testing.mjs.map +1 -1
  14. package/dist/verify-B00c81-n.mjs +2420 -0
  15. package/dist/verify-B00c81-n.mjs.map +1 -0
  16. package/dist/{verify-Dls29YC-.d.mts → verify-CkgVrwyl.d.mts} +318 -21
  17. package/package.json +6 -30
  18. package/dist/auth-BR-19zj-.mjs +0 -738
  19. package/dist/auth-BR-19zj-.mjs.map +0 -1
  20. package/dist/auth-g-waCHcz.mjs +0 -671
  21. package/dist/auth-g-waCHcz.mjs.map +0 -1
  22. package/dist/authorization-OeaSR47S.mjs +0 -284
  23. package/dist/authorization-OeaSR47S.mjs.map +0 -1
  24. package/dist/canonical-json-CpvqGMcr.mjs +0 -57
  25. package/dist/canonical-json-CpvqGMcr.mjs.map +0 -1
  26. package/dist/cloudflare-BrZPU9li.d.mts +0 -32
  27. package/dist/cloudflare-CGmasR8A.mjs +0 -69
  28. package/dist/cloudflare-CGmasR8A.mjs.map +0 -1
  29. package/dist/cloudflare.d.mts +0 -3
  30. package/dist/cloudflare.mjs +0 -2
  31. package/dist/connection-BfkloPZy.d.mts +0 -186
  32. package/dist/connection-BwtOwpH6.mjs +0 -195
  33. package/dist/connection-BwtOwpH6.mjs.map +0 -1
  34. package/dist/connection-CjNQe_E-.mjs +0 -58
  35. package/dist/connection-CjNQe_E-.mjs.map +0 -1
  36. package/dist/connection-api-DNuEZ_jR.d.mts +0 -7
  37. package/dist/dns-record-BLeqo56C.mjs +0 -289
  38. package/dist/dns-record-BLeqo56C.mjs.map +0 -1
  39. package/dist/effect-cloudflare.d.mts +0 -2
  40. package/dist/effect-cloudflare.mjs +0 -2
  41. package/dist/effect-vercel.d.mts +0 -2
  42. package/dist/effect-vercel.mjs +0 -2
  43. package/dist/effect.d.mts +0 -36
  44. package/dist/effect.mjs +0 -51
  45. package/dist/effect.mjs.map +0 -1
  46. package/dist/index-BHWRTThN.d.mts +0 -159
  47. package/dist/index-D3PVknwE.d.mts +0 -145
  48. package/dist/resolver-CxE-VDw4.mjs.map +0 -1
  49. package/dist/vercel-BsNDu4Np.d.mts +0 -31
  50. package/dist/vercel-CfoJaaCu.mjs +0 -60
  51. package/dist/vercel-CfoJaaCu.mjs.map +0 -1
  52. package/dist/vercel.d.mts +0 -3
  53. package/dist/vercel.mjs +0 -2
  54. package/dist/verify-BKbvq7IN.mjs +0 -642
  55. package/dist/verify-BKbvq7IN.mjs.map +0 -1
  56. package/dist/zone-discovery-BPnH3sLU.d.mts +0 -1397
  57. package/dist/zones-DKHTpX9C.mjs +0 -19
  58. package/dist/zones-DKHTpX9C.mjs.map +0 -1
@@ -0,0 +1,2420 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
+ import { I as Error$3, L as Service$3, Y as Opaque, gt as decode$8, ht as Schema$4, i as toAsync$3, it as equals, n as Service$2, nt as decode$9, pt as Service$1, t as Error$4, tt as data, ut as candidates, vt as parse$1, x as authorize$1, yt as Error$2 } from "./resolver-CvK7JoJM.mjs";
3
+ import { Clock, Context, Crypto, Data, Effect, Layer, Option, Schema, SchemaIssue, SchemaTransformation } from "effect";
4
+ import * as oauth from "oauth4webapi";
5
+ import * as DnsPacket from "@leichtgewicht/dns-packet";
6
+ //#region package.json
7
+ var version = "0.3.0";
8
+ //#endregion
9
+ //#region src/auth/provider-context.ts
10
+ var provider_context_exports = /* @__PURE__ */ __exportAll({
11
+ Envelope: () => Envelope,
12
+ codec: () => codec,
13
+ decode: () => decode$7,
14
+ encode: () => encode$4
15
+ });
16
+ /** A provider-owned, versioned, non-secret context value persisted by the host. */
17
+ const Envelope = Schema.Struct({
18
+ value: Schema.Json,
19
+ version: Schema.String
20
+ });
21
+ /** Build an adapter-owned context codec from a schema and stable version identifier. */
22
+ function codec(version, schema) {
23
+ return {
24
+ decode: Effect.fn("ProviderContext.decode")((envelope) => envelope.version !== version ? Effect.fail(new Error$2({ message: `Unsupported provider context version: ${envelope.version}` })) : Schema.decodeUnknownEffect(schema)(envelope.value).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message })))),
25
+ encode: Effect.fn("ProviderContext.encode")((value) => Schema.encodeEffect(schema)(value).pipe(Effect.flatMap((encoded) => Schema.decodeUnknownEffect(Schema.Json)(encoded)), Effect.map((encoded) => ({
26
+ value: encoded,
27
+ version
28
+ })), Effect.mapError((cause) => new Error$2({ message: cause.message })))),
29
+ version
30
+ };
31
+ }
32
+ const decode$7 = Effect.fn("ProviderContext.Envelope.decode")((input) => Schema.decodeUnknownEffect(Envelope)(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
33
+ const encode$4 = Schema.encodeSync(Envelope);
34
+ //#endregion
35
+ //#region src/auth/authorization.ts
36
+ var authorization_exports = /* @__PURE__ */ __exportAll({
37
+ Capability: () => Capability,
38
+ CapabilityEvidence: () => CapabilityEvidence,
39
+ Evidence: () => Evidence$1,
40
+ EvidenceSchema: () => EvidenceSchema,
41
+ Revocation: () => Revocation,
42
+ Schema: () => Schema$3,
43
+ decode: () => decode$6,
44
+ encode: () => encode$3,
45
+ evidenceFor: () => evidenceFor$1,
46
+ validate: () => validate$1
47
+ });
48
+ const Capability = Schema.Literals(["dns:read", "dns:write"]);
49
+ const Evidence$1 = Data.taggedEnum();
50
+ const EvidenceSchema = Schema.TaggedUnion({
51
+ Declared: {},
52
+ Exercised: { observedAt: Schema.DateFromString },
53
+ Introspected: { observedAt: Schema.DateFromString }
54
+ });
55
+ const CapabilityEvidence = Schema.Struct({
56
+ capability: Capability,
57
+ evidence: EvidenceSchema
58
+ });
59
+ const Revocation = Schema.TaggedUnion({
60
+ Active: {},
61
+ Pending: { requestedAt: Schema.DateFromString }
62
+ });
63
+ /** A provider credential authorization shared by one or more owner connections. */
64
+ const Schema$3 = Schema.Struct({
65
+ authorizedById: Schema.String,
66
+ capabilityEvidence: Schema.Array(CapabilityEvidence),
67
+ createdAt: Schema.DateFromString,
68
+ expiresAt: Schema.NullOr(Schema.DateFromString),
69
+ id: Schema.String,
70
+ method: Schema.Literals([
71
+ "integration",
72
+ "oauth2",
73
+ "token"
74
+ ]),
75
+ providerAccountId: Schema.String,
76
+ providerContext: Envelope,
77
+ providerId: Schema.String,
78
+ requiredCapabilities: Schema.Array(Capability),
79
+ revocation: Revocation,
80
+ scopes: Schema.Array(Schema.String)
81
+ });
82
+ const decode$6 = Effect.fn("ProviderAuthorization.decode")((input) => Schema.decodeUnknownEffect(Schema$3)(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
83
+ const validate$1 = Effect.fn("ProviderAuthorization.validate")((input) => Schema.decodeUnknownEffect(Schema.toType(Schema$3))(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
84
+ const encode$3 = Schema.encodeSync(Schema$3);
85
+ function evidenceFor$1(authorization, capability) {
86
+ return authorization.capabilityEvidence.find((item) => item.capability === capability)?.evidence;
87
+ }
88
+ //#endregion
89
+ //#region src/auth/connection.ts
90
+ const Grant = Schema.TaggedUnion({
91
+ account: { excludedDomains: Schema.Array(Schema$4) },
92
+ domains: { domains: Schema.Array(Schema$4) }
93
+ });
94
+ /** Returns whether a grant includes one parsed domain. */
95
+ const coversDomain = (grant, domain) => grant._tag === "account" ? !grant.excludedDomains.includes(domain) : grant.domains.includes(domain);
96
+ /** Expands a grant to include the requested domains. */
97
+ const includeDomains = (current, requested) => {
98
+ if (current === void 0) return requested;
99
+ if (current._tag === "account" && requested._tag === "account") return {
100
+ _tag: "account",
101
+ excludedDomains: current.excludedDomains.filter((domain) => requested.excludedDomains.includes(domain))
102
+ };
103
+ if (current._tag === "account" && requested._tag === "domains") return {
104
+ _tag: "account",
105
+ excludedDomains: current.excludedDomains.filter((domain) => !requested.domains.includes(domain))
106
+ };
107
+ if (requested._tag === "account") {
108
+ const includedDomains = current._tag === "domains" ? current.domains : [];
109
+ return {
110
+ _tag: "account",
111
+ excludedDomains: requested.excludedDomains.filter((domain) => !includedDomains.includes(domain))
112
+ };
113
+ }
114
+ if (current._tag === "account") return current;
115
+ return {
116
+ _tag: "domains",
117
+ domains: [.../* @__PURE__ */ new Set([...current.domains, ...requested.domains])]
118
+ };
119
+ };
120
+ /** Contracts a grant so it no longer includes one parsed domain. */
121
+ const removeDomain$1 = (grant, domain) => grant._tag === "account" ? {
122
+ _tag: "account",
123
+ excludedDomains: [.../* @__PURE__ */ new Set([...grant.excludedDomains, domain])]
124
+ } : {
125
+ _tag: "domains",
126
+ domains: grant.domains.filter((candidate) => candidate !== domain)
127
+ };
128
+ /** An owner-scoped grant bound to one provider authorization. */
129
+ const Schema$2 = Schema.Struct({
130
+ authorizationId: Schema.String,
131
+ createdAt: Schema.DateFromString,
132
+ grant: Grant,
133
+ id: Schema.String,
134
+ ownerId: Schema.String
135
+ });
136
+ const decode$5 = Effect.fn("Connection.decode")((input) => Schema.decodeUnknownEffect(Schema$2)(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
137
+ const validate = Effect.fn("Connection.validate")((input) => Schema.decodeUnknownEffect(Schema.toType(Schema$2))(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
138
+ const encode$2 = Schema.encodeSync(Schema$2);
139
+ var AuthorizationError = class extends Schema.TaggedError()("AuthorizationError", {
140
+ category: Schema.Literal("authorization"),
141
+ message: Schema.String,
142
+ operation: Schema.String,
143
+ retry: Schema.Literals([
144
+ "never",
145
+ "after-user-action",
146
+ "safe",
147
+ "unknown"
148
+ ])
149
+ }) {};
150
+ const authorizationError = (message, operation) => new AuthorizationError({
151
+ category: "authorization",
152
+ message,
153
+ operation,
154
+ retry: "after-user-action"
155
+ });
156
+ function assertGrant(connection, authorization, request) {
157
+ if (connection.authorizationId !== authorization.id || authorization.providerId !== request.providerId || authorization.revocation._tag !== "Active") throw authorizationError("Connection does not grant this provider account", "Connection.assertGrant");
158
+ if (authorization.expiresAt !== null) {
159
+ if (Number.isNaN(authorization.expiresAt.getTime())) throw authorizationError("Connection expiration is invalid", "Connection.assertGrant");
160
+ if (authorization.expiresAt <= (request.now ?? /* @__PURE__ */ new Date())) throw authorizationError("Connection has expired", "Connection.assertGrant");
161
+ }
162
+ if (!authorization.requiredCapabilities.includes(request.capability)) throw authorizationError(`Connection lacks the ${request.capability} capability`, "Connection.assertGrant");
163
+ if (evidenceFor$1(authorization, request.capability) === void 0) throw authorizationError(`Connection has no evidence for the ${request.capability} capability`, "Connection.assertGrant");
164
+ let domain;
165
+ try {
166
+ domain = parse$1(request.domain);
167
+ } catch (cause) {
168
+ if (cause instanceof Error$2) throw cause;
169
+ throw new Error$2({ message: cause instanceof Error ? cause.message : String(cause) });
170
+ }
171
+ if (!coversDomain(connection.grant, domain)) throw authorizationError("Connection does not grant this domain", "Connection.assertGrant");
172
+ return domain;
173
+ }
174
+ //#endregion
175
+ //#region src/auth/connect.ts
176
+ const Method$1 = Data.taggedEnum();
177
+ const StartResult = Data.taggedEnum();
178
+ var Error$1 = class extends Schema.TaggedError()("ConnectionError", {
179
+ category: Schema.Literals([
180
+ "authorization",
181
+ "provider",
182
+ "validation"
183
+ ]),
184
+ message: Schema.String,
185
+ operation: Schema.String,
186
+ retry: Schema.Literals([
187
+ "never",
188
+ "after-user-action",
189
+ "safe",
190
+ "unknown"
191
+ ])
192
+ }) {};
193
+ const RemoveDomainResult = Data.taggedEnum();
194
+ const persist = Effect.fn("Connection.persist")(function* (input) {
195
+ const repository = yield* Service$1;
196
+ const crypto = yield* Crypto.Crypto;
197
+ const now = new Date(yield* Clock.currentTimeMillis);
198
+ const missingCapability = input.requiredCapabilities.find((capability) => !input.authentication.capabilityEvidence.some((item) => item.capability === capability));
199
+ if (missingCapability !== void 0) return yield* new Error$1({
200
+ category: "authorization",
201
+ message: `Provider authorization lacks evidence for ${missingCapability}`,
202
+ operation: "Connection.persist",
203
+ retry: "after-user-action"
204
+ });
205
+ const existing = yield* repository.findByProviderAccount(input.providerId, input.authentication.providerAccountId);
206
+ const authorizationId = existing?.authorization.id ?? (yield* crypto.randomUUIDv4.pipe(Effect.mapError((cause) => new Error$1({
207
+ category: "validation",
208
+ message: cause.message,
209
+ operation: "Connection.persist",
210
+ retry: "safe"
211
+ }))));
212
+ const existingBinding = existing?.bindings.find((binding) => binding.ownerId === input.ownerId);
213
+ const binding = {
214
+ authorizationId,
215
+ createdAt: existingBinding?.createdAt ?? now,
216
+ grant: includeDomains(existingBinding?.grant, input.grant),
217
+ id: existingBinding?.id ?? (yield* crypto.randomUUIDv4.pipe(Effect.mapError((cause) => new Error$1({
218
+ category: "validation",
219
+ message: cause.message,
220
+ operation: "Connection.persist",
221
+ retry: "safe"
222
+ })))),
223
+ ownerId: input.ownerId
224
+ };
225
+ const aggregate = {
226
+ authorization: {
227
+ authorizedById: input.authorizedById,
228
+ capabilityEvidence: [...input.authentication.capabilityEvidence],
229
+ createdAt: existing?.authorization.createdAt ?? now,
230
+ expiresAt: input.authentication.expiresAt,
231
+ id: authorizationId,
232
+ method: input.method,
233
+ providerAccountId: input.authentication.providerAccountId,
234
+ providerContext: input.authentication.providerContext,
235
+ providerId: input.providerId,
236
+ requiredCapabilities: [...input.requiredCapabilities],
237
+ revocation: { _tag: "Active" },
238
+ scopes: [...input.authentication.scopes]
239
+ },
240
+ bindings: [...existing?.bindings.filter((candidate) => candidate.id !== binding.id) ?? [], binding],
241
+ credential: input.authentication.credential
242
+ };
243
+ return yield* repository.connect(aggregate);
244
+ });
245
+ const start$1 = Effect.fn("Connection.start")(function* (input) {
246
+ if (input.method._tag === "Interactive") {
247
+ const crypto = yield* Crypto.Crypto;
248
+ const now = yield* Clock.currentTimeMillis;
249
+ const continuationId = yield* crypto.randomUUIDv4.pipe(Effect.mapError((cause) => new Error$1({
250
+ category: "validation",
251
+ message: cause.message,
252
+ operation: "Connection.start",
253
+ retry: "safe"
254
+ })));
255
+ const started = yield* input.method.flow.start(continuationId);
256
+ yield* input.method.continuations.put({
257
+ authorizedById: input.authorizedById,
258
+ expiresAt: new Date(now + (input.method.ttlMs ?? 6e5)),
259
+ grant: input.grant,
260
+ id: continuationId,
261
+ method: input.method.flow.method,
262
+ ownerId: input.ownerId,
263
+ payload: started.payload,
264
+ providerId: input.method.flow.providerId,
265
+ requiredCapabilities: [...input.method.flow.requiredCapabilities]
266
+ });
267
+ return StartResult.Redirect({
268
+ authorizationUrl: started.authorizationUrl,
269
+ continuationId
270
+ });
271
+ }
272
+ const authentication = yield* input.method.authenticate(input.method.token);
273
+ const aggregate = yield* persist({
274
+ authentication,
275
+ authorizedById: input.authorizedById,
276
+ grant: input.grant,
277
+ method: "token",
278
+ ownerId: input.ownerId,
279
+ providerId: input.method.providerId,
280
+ requiredCapabilities: input.method.requiredCapabilities
281
+ });
282
+ return StartResult.Connected({ aggregate });
283
+ });
284
+ const complete$1 = Effect.fn("Connection.complete")(function* (input) {
285
+ const continuation = yield* input.continuations.consume(input.continuationId, new Date(yield* Clock.currentTimeMillis));
286
+ if (continuation === null) return yield* new Error$1({
287
+ category: "authorization",
288
+ message: "Connection continuation is expired, unknown, or already consumed",
289
+ operation: "Connection.complete",
290
+ retry: "after-user-action"
291
+ });
292
+ if (continuation.providerId !== input.flow.providerId || continuation.method !== input.flow.method) return yield* new Error$1({
293
+ category: "authorization",
294
+ message: "Connection continuation does not match the provider flow",
295
+ operation: "Connection.complete",
296
+ retry: "never"
297
+ });
298
+ const authentication = yield* input.flow.complete(continuation.payload, input.callbackUrl);
299
+ return yield* persist({
300
+ authentication,
301
+ authorizedById: continuation.authorizedById,
302
+ grant: continuation.grant,
303
+ method: continuation.method,
304
+ ownerId: continuation.ownerId,
305
+ providerId: continuation.providerId,
306
+ requiredCapabilities: continuation.requiredCapabilities
307
+ });
308
+ });
309
+ /** Extends one owner binding without repeating provider authentication. */
310
+ const extend = Effect.fn("Connection.extend")(function* (input) {
311
+ const repository = yield* Service$1;
312
+ const aggregate = yield* repository.getByConnectionId(input.connectionId);
313
+ const binding = aggregate?.bindings.find(({ id }) => id === input.connectionId);
314
+ if (aggregate === null || binding === void 0 || binding.ownerId !== input.ownerId) return yield* new Error$1({
315
+ category: "authorization",
316
+ message: "Connection does not belong to this owner",
317
+ operation: "Connection.extend",
318
+ retry: "never"
319
+ });
320
+ if (aggregate.authorization.revocation._tag !== "Active") return yield* new Error$1({
321
+ category: "authorization",
322
+ message: "Provider authorization is awaiting revocation",
323
+ operation: "Connection.extend",
324
+ retry: "after-user-action"
325
+ });
326
+ const now = new Date(yield* Clock.currentTimeMillis);
327
+ if (aggregate.authorization.expiresAt !== null && (Number.isNaN(aggregate.authorization.expiresAt.getTime()) || aggregate.authorization.expiresAt <= now)) return yield* new Error$1({
328
+ category: "authorization",
329
+ message: "Provider authorization has expired",
330
+ operation: "Connection.extend",
331
+ retry: "after-user-action"
332
+ });
333
+ return yield* repository.bind(aggregate.authorization.id, {
334
+ ...binding,
335
+ grant: includeDomains(binding.grant, input.grant)
336
+ });
337
+ });
338
+ /** Removes one domain from an owner binding without revoking provider authorization. */
339
+ const removeDomain = Effect.fn("Connection.removeDomain")(function* (input) {
340
+ const repository = yield* Service$1;
341
+ const aggregate = yield* repository.getByConnectionId(input.connectionId);
342
+ const binding = aggregate?.bindings.find(({ id }) => id === input.connectionId);
343
+ if (aggregate === null || binding === void 0 || binding.ownerId !== input.ownerId) return yield* new Error$1({
344
+ category: "authorization",
345
+ message: "Connection does not belong to this owner",
346
+ operation: "Connection.removeDomain",
347
+ retry: "never"
348
+ });
349
+ const domain = yield* decode$8(input.domain).pipe(Effect.mapError((cause) => new Error$1({
350
+ category: "validation",
351
+ message: cause.message,
352
+ operation: "Connection.removeDomain",
353
+ retry: "never"
354
+ })));
355
+ const updated = yield* repository.modifyBinding(input.connectionId, (current) => {
356
+ if (!coversDomain(current.grant, domain)) return {
357
+ binding: current,
358
+ value: false
359
+ };
360
+ return {
361
+ binding: {
362
+ ...current,
363
+ grant: removeDomain$1(current.grant, domain)
364
+ },
365
+ value: true
366
+ };
367
+ });
368
+ return updated.value ? RemoveDomainResult.Removed({ aggregate: updated.aggregate }) : RemoveDomainResult.AlreadyRemoved({ aggregate: updated.aggregate });
369
+ });
370
+ //#endregion
371
+ //#region src/auth/diagnostic.ts
372
+ var diagnostic_exports = /* @__PURE__ */ __exportAll({
373
+ Category: () => Category,
374
+ Fields: () => Fields,
375
+ RetryAdvice: () => RetryAdvice,
376
+ from: () => from
377
+ });
378
+ const Category = Schema.Literals([
379
+ "authorization",
380
+ "configuration",
381
+ "provider",
382
+ "storage",
383
+ "validation"
384
+ ]);
385
+ const RetryAdvice = Schema.Literals([
386
+ "never",
387
+ "after-user-action",
388
+ "safe",
389
+ "unknown"
390
+ ]);
391
+ const Fields = {
392
+ category: Category,
393
+ message: Schema.String,
394
+ operation: Schema.String,
395
+ retry: RetryAdvice
396
+ };
397
+ function from(error) {
398
+ return {
399
+ category: error.category,
400
+ message: error.message,
401
+ operation: error.operation,
402
+ retry: error.retry,
403
+ tag: error._tag
404
+ };
405
+ }
406
+ //#endregion
407
+ //#region src/auth/manifest.ts
408
+ var manifest_exports = /* @__PURE__ */ __exportAll({
409
+ Method: () => Method,
410
+ Schema: () => Schema$1,
411
+ decode: () => decode$4
412
+ });
413
+ const Method = Schema.TaggedUnion({
414
+ integration: {
415
+ capabilities: Schema.Array(Schema.Literals(["dns:read", "dns:write"])),
416
+ installUrl: Schema.String,
417
+ tokenEndpoint: Schema.String
418
+ },
419
+ oauth2: {
420
+ authorizationServer: Schema.Struct({
421
+ authorization_endpoint: Schema.String,
422
+ issuer: Schema.String,
423
+ revocation_endpoint: Schema.optionalKey(Schema.String),
424
+ token_endpoint: Schema.String
425
+ }),
426
+ capabilities: Schema.Array(Schema.Literals(["dns:read", "dns:write"])),
427
+ clientAuth: Schema.Literals([
428
+ "none",
429
+ "client_secret_basic",
430
+ "client_secret_post"
431
+ ]),
432
+ scopes: Schema.Array(Schema.String)
433
+ },
434
+ token: {
435
+ capabilities: Schema.Array(Schema.Literals(["dns:read", "dns:write"])),
436
+ instructionsUrl: Schema.String
437
+ }
438
+ });
439
+ const Schema$1 = Schema.Struct({
440
+ methods: Schema.Array(Method),
441
+ providerId: Schema.String
442
+ });
443
+ const decode$4 = Effect.fn("ProviderAuth.decode")((input) => Schema.decodeUnknownEffect(Schema$1)(input).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message }))));
444
+ //#endregion
445
+ //#region src/auth/secret.ts
446
+ var secret_exports = /* @__PURE__ */ __exportAll({
447
+ Value: () => Value,
448
+ make: () => make$6
449
+ });
450
+ /** A deliberately non-serializable credential value. */
451
+ var Value = class Value {
452
+ #value;
453
+ constructor(value) {
454
+ this.#value = value;
455
+ }
456
+ static from(value) {
457
+ if (value.length === 0) throw new Error("Secret values cannot be empty");
458
+ return new Value(value);
459
+ }
460
+ expose() {
461
+ return this.#value;
462
+ }
463
+ toJSON() {
464
+ return "[REDACTED]";
465
+ }
466
+ toString() {
467
+ return "[REDACTED]";
468
+ }
469
+ };
470
+ const make$6 = Value.from;
471
+ //#endregion
472
+ //#region src/discovery/selection.ts
473
+ var selection_exports = /* @__PURE__ */ __exportAll({
474
+ Evidence: () => Evidence,
475
+ Selection: () => Selection,
476
+ select: () => select
477
+ });
478
+ const Evidence = Schema.Struct({
479
+ accountId: Schema.String,
480
+ connectionId: Schema.String,
481
+ decisiveNameserverMatch: Schema.Boolean,
482
+ matchedNameservers: Schema.Array(Schema$4),
483
+ providerId: Schema.String,
484
+ zone: Schema$4
485
+ });
486
+ const Selection = Schema.TaggedUnion({
487
+ selected: {
488
+ candidate: Evidence,
489
+ evidence: Schema.Array(Evidence),
490
+ reason: Schema.Literals(["explicit", "unique-nameserver-match"])
491
+ },
492
+ manual: {
493
+ evidence: Schema.Array(Evidence),
494
+ reason: Schema.Literals(["ambiguous", "unsupported"])
495
+ }
496
+ });
497
+ function select(input) {
498
+ const domain = parse$1(input.domain);
499
+ const zoneCandidates = new Set(candidates(domain));
500
+ const authoritative = nameserverSet(input.authoritativeNameservers);
501
+ const eligible = input.connectedZones.filter((connected) => {
502
+ if (!zoneCandidates.has(parse$1(connected.zone))) return false;
503
+ try {
504
+ assertGrant(connected.connection, connected.authorization, {
505
+ capability: "dns:read",
506
+ domain,
507
+ ...input.now === void 0 ? {} : { now: input.now },
508
+ providerId: connected.providerId
509
+ });
510
+ return true;
511
+ } catch {
512
+ return false;
513
+ }
514
+ });
515
+ const evidence = eligible.map((connected) => evidenceFor(connected, authoritative));
516
+ if (input.explicit !== void 0) {
517
+ const explicitZone = parse$1(input.explicit.zone);
518
+ const index = eligible.findIndex((connected) => connected.providerId === input.explicit?.providerId && connected.authorization.providerAccountId === input.explicit.accountId && parse$1(connected.zone) === explicitZone);
519
+ if (index < 0) throw authorizationError("Explicit provider zone is not connected or granted", "ProviderDiscovery.select");
520
+ const candidate = evidence[index];
521
+ if (candidate === void 0) throw new Error("Eligible provider evidence is missing");
522
+ return {
523
+ _tag: "selected",
524
+ candidate,
525
+ evidence,
526
+ reason: "explicit"
527
+ };
528
+ }
529
+ const decisive = evidence.filter(({ decisiveNameserverMatch }) => decisiveNameserverMatch);
530
+ const candidate = decisive[0];
531
+ return decisive.length === 1 && candidate !== void 0 ? {
532
+ _tag: "selected",
533
+ candidate,
534
+ evidence,
535
+ reason: "unique-nameserver-match"
536
+ } : {
537
+ _tag: "manual",
538
+ evidence,
539
+ reason: decisive.length > 1 ? "ambiguous" : "unsupported"
540
+ };
541
+ }
542
+ function evidenceFor(connected, authoritative) {
543
+ const configured = new Set(nameserverSet(connected.nameservers));
544
+ const matchedNameservers = authoritative.filter((nameserver) => configured.has(nameserver));
545
+ return {
546
+ accountId: connected.authorization.providerAccountId,
547
+ connectionId: connected.connection.id,
548
+ decisiveNameserverMatch: authoritative.length > 0 && matchedNameservers.length === authoritative.length,
549
+ matchedNameservers,
550
+ providerId: connected.providerId,
551
+ zone: parse$1(connected.zone)
552
+ };
553
+ }
554
+ function nameserverSet(nameservers) {
555
+ return [...new Set(nameservers.map(parse$1))].sort();
556
+ }
557
+ //#endregion
558
+ //#region src/plan/connection-authorization.ts
559
+ var connection_authorization_exports = /* @__PURE__ */ __exportAll({ authorize: () => authorize });
560
+ const authorize = Effect.fn("ConnectionAuthorization.authorize")(function* (input) {
561
+ const domain = yield* Effect.try({
562
+ try: () => assertGrant(input.connection, input.authorization, {
563
+ capability: "dns:write",
564
+ domain: input.domain,
565
+ providerId: input.plan.providerId
566
+ }),
567
+ catch: (cause) => cause instanceof AuthorizationError || cause instanceof Error$2 ? cause : authorizationError("Connection grant is invalid", "ConnectionAuthorization.authorize")
568
+ });
569
+ const authorization = yield* authorize$1(input.plan, input.operationIds, input.allowPartial === void 0 ? {} : { allowPartial: input.allowPartial });
570
+ const selected = new Set(authorization.operationIds);
571
+ if (input.plan.operations.filter((operation) => operation._tag === "create" && selected.has(operation.id) && operation.requirement.name !== domain && !operation.requirement.name.endsWith(`.${domain}`)).length > 0) return yield* authorizationError(`Plan operations are outside the granted domain ${domain}`, "ConnectionAuthorization.authorize");
572
+ return authorization;
573
+ });
574
+ //#endregion
575
+ //#region src/auth/authorization-code.ts
576
+ const start = Effect.fn("AuthorizationCode.start")(function* (input) {
577
+ const crypto = yield* Crypto.Crypto;
578
+ const codeVerifier = base64Url(yield* randomBytes(crypto, 32));
579
+ const challenge = base64Url(yield* digest(crypto, codeVerifier));
580
+ const authorizationUrl = new URL(input.method.authorizationServer.authorization_endpoint);
581
+ authorizationUrl.search = new URLSearchParams({
582
+ client_id: input.client.clientId,
583
+ code_challenge: challenge,
584
+ code_challenge_method: "S256",
585
+ redirect_uri: input.redirectUri,
586
+ response_type: "code",
587
+ scope: input.method.scopes.join(" "),
588
+ state: input.state
589
+ }).toString();
590
+ return {
591
+ authorizationUrl,
592
+ payload: make$6(JSON.stringify({
593
+ codeVerifier,
594
+ redirectUri: input.redirectUri,
595
+ state: input.state
596
+ }))
597
+ };
598
+ });
599
+ const complete = Effect.fn("AuthorizationCode.complete")(function* (input) {
600
+ const payload = yield* decodePayload(input.payload);
601
+ if (input.callbackUrl.searchParams.get("state") !== payload.state) return yield* failure$5("Authorization callback state does not match its continuation");
602
+ const server = input.method.authorizationServer;
603
+ const client = { client_id: input.client.clientId };
604
+ const authentication = yield* clientAuthentication(input.method, input.client);
605
+ return yield* Effect.tryPromise({
606
+ try: async (signal) => {
607
+ const callback = oauth.validateAuthResponse(server, client, input.callbackUrl, payload.state);
608
+ const response = await oauth.authorizationCodeGrantRequest(server, client, authentication, callback, payload.redirectUri, payload.codeVerifier, requestOptions(input.fetch, signal));
609
+ return oauth.processAuthorizationCodeResponse(server, client, response);
610
+ },
611
+ catch: (cause) => new Error$1({
612
+ category: "provider",
613
+ message: cause instanceof globalThis.Error ? cause.name : "OAuth provider request failed",
614
+ operation: "AuthorizationCode.complete",
615
+ retry: "unknown"
616
+ })
617
+ });
618
+ });
619
+ const PayloadSchema = Schema.Struct({
620
+ codeVerifier: Schema.String,
621
+ redirectUri: Schema.String,
622
+ state: Schema.String
623
+ });
624
+ function decodePayload(payload) {
625
+ return Schema.decodeUnknownEffect(Schema.fromJsonString(PayloadSchema))(payload.expose()).pipe(Effect.mapError(() => new Error$1({
626
+ category: "authorization",
627
+ message: "OAuth continuation payload is invalid",
628
+ operation: "AuthorizationCode",
629
+ retry: "after-user-action"
630
+ })));
631
+ }
632
+ function clientAuthentication(method, client) {
633
+ switch (method.clientAuth) {
634
+ case "none": return Effect.succeed(oauth.None());
635
+ case "client_secret_basic": return client.clientSecret === void 0 ? failure$5("OAuth client secret is required") : Effect.succeed(oauth.ClientSecretBasic(client.clientSecret.expose()));
636
+ case "client_secret_post": return client.clientSecret === void 0 ? failure$5("OAuth client secret is required") : Effect.succeed(oauth.ClientSecretPost(client.clientSecret.expose()));
637
+ }
638
+ }
639
+ function requestOptions(fetchImplementation, signal) {
640
+ return fetchImplementation === void 0 ? { signal } : {
641
+ signal,
642
+ [oauth.customFetch]: (url, options) => fetchImplementation(url, {
643
+ ...options,
644
+ body: options.body
645
+ })
646
+ };
647
+ }
648
+ const failure$5 = (message) => Effect.fail(new Error$1({
649
+ category: "authorization",
650
+ message,
651
+ operation: "AuthorizationCode",
652
+ retry: "after-user-action"
653
+ }));
654
+ function randomBytes(crypto, size) {
655
+ return crypto.randomBytes(size).pipe(Effect.mapError((cause) => new Error$1({
656
+ category: "validation",
657
+ message: cause.message,
658
+ operation: "AuthorizationCode.start",
659
+ retry: "safe"
660
+ })));
661
+ }
662
+ function digest(crypto, value) {
663
+ return crypto.digest("SHA-256", new TextEncoder().encode(value)).pipe(Effect.mapError((cause) => new Error$1({
664
+ category: "validation",
665
+ message: cause.message,
666
+ operation: "AuthorizationCode.start",
667
+ retry: "safe"
668
+ })));
669
+ }
670
+ function base64Url(bytes) {
671
+ let binary = "";
672
+ for (const byte of bytes) binary += String.fromCharCode(byte);
673
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
674
+ }
675
+ //#endregion
676
+ //#region src/providers/cloudflare/protocol.ts
677
+ const ErrorDetail$1 = Schema.Struct({
678
+ code: Schema.Number,
679
+ message: Schema.String
680
+ });
681
+ const ResultInfo = Schema.Struct({
682
+ count: Schema.optionalKey(Schema.Number),
683
+ page: Schema.optionalKey(Schema.Number),
684
+ per_page: Schema.optionalKey(Schema.Number),
685
+ total_count: Schema.optionalKey(Schema.Number),
686
+ total_pages: Schema.optionalKey(Schema.Number)
687
+ });
688
+ const Message = Schema.Struct({
689
+ code: Schema.optionalKey(Schema.Number),
690
+ message: Schema.String
691
+ });
692
+ const BaseEnvelope = Schema.Struct({
693
+ errors: Schema.Array(ErrorDetail$1),
694
+ messages: Schema.Array(Message),
695
+ success: Schema.Boolean
696
+ });
697
+ const Account = Schema.Struct({
698
+ id: Schema.String,
699
+ name: Schema.String
700
+ });
701
+ const Zone = Schema.Struct({
702
+ account: Account,
703
+ id: Schema.String,
704
+ name: Schema.String,
705
+ name_servers: Schema.Array(Schema.String),
706
+ status: Schema.optionalKey(Schema.String)
707
+ });
708
+ const Record$1 = Schema.Struct({
709
+ content: Schema.optionalKey(Schema.String),
710
+ data: Schema.optionalKey(Schema.Unknown),
711
+ id: Schema.String,
712
+ name: Schema.String,
713
+ priority: Schema.optionalKey(Schema.Number),
714
+ proxied: Schema.optionalKey(Schema.Boolean),
715
+ ttl: Schema.Number,
716
+ type: Schema.String
717
+ });
718
+ const Token = Schema.Struct({
719
+ expires_on: Schema.optionalKey(Schema.String),
720
+ id: Schema.String,
721
+ not_before: Schema.optionalKey(Schema.String),
722
+ status: Schema.Literals([
723
+ "active",
724
+ "disabled",
725
+ "expired"
726
+ ])
727
+ });
728
+ const ZoneListEnvelope = Schema.Struct({
729
+ errors: Schema.Array(ErrorDetail$1),
730
+ messages: Schema.Array(Message),
731
+ result: Schema.Array(Zone),
732
+ result_info: Schema.optionalKey(ResultInfo),
733
+ success: Schema.Boolean
734
+ });
735
+ const RecordListEnvelope$1 = Schema.Struct({
736
+ errors: Schema.Array(ErrorDetail$1),
737
+ messages: Schema.Array(Message),
738
+ result: Schema.Array(Record$1),
739
+ result_info: Schema.optionalKey(ResultInfo),
740
+ success: Schema.Boolean
741
+ });
742
+ const RecordEnvelope = Schema.Struct({
743
+ errors: Schema.Array(ErrorDetail$1),
744
+ messages: Schema.Array(Message),
745
+ result: Record$1,
746
+ success: Schema.Boolean
747
+ });
748
+ const TokenEnvelope = Schema.Struct({
749
+ errors: Schema.Array(ErrorDetail$1),
750
+ messages: Schema.Array(Message),
751
+ result: Token,
752
+ success: Schema.Boolean
753
+ });
754
+ //#endregion
755
+ //#region src/providers/cloudflare/records.ts
756
+ const Data$1 = Schema.Struct({
757
+ flags: Schema.optionalKey(Schema.Number),
758
+ port: Schema.optionalKey(Schema.Number),
759
+ priority: Schema.optionalKey(Schema.Number),
760
+ tag: Schema.optionalKey(Schema.String),
761
+ target: Schema.optionalKey(Schema.String),
762
+ value: Schema.optionalKey(Schema.String),
763
+ weight: Schema.optionalKey(Schema.Number)
764
+ });
765
+ const decode$3 = Effect.fn("CloudflareRecords.decode")((record) => Effect.gen(function* () {
766
+ const name = yield* decode$8(record.name).pipe(Effect.match({
767
+ onFailure: () => null,
768
+ onSuccess: (value) => value
769
+ }));
770
+ if (name === null) return yield* decodeOpaque$1(record);
771
+ const common = {
772
+ metadata: {
773
+ ownership: "provider",
774
+ provenance: record.proxied === true ? "cloudflare:proxied" : "cloudflare",
775
+ purpose: "existing DNS record"
776
+ },
777
+ name,
778
+ policy: record.type === "CNAME" ? "exclusive" : "append",
779
+ ttl: record.ttl === 1 ? null : record.ttl
780
+ };
781
+ const content = () => record.content === void 0 ? Effect.fail(failure$4("decodeRecord", `Cloudflare ${record.type} record has no content`)) : Effect.succeed(record.content);
782
+ switch (record.type) {
783
+ case "A":
784
+ case "AAAA": return yield* decode$9({
785
+ ...common,
786
+ _tag: record.type,
787
+ address: yield* content()
788
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message)));
789
+ case "CNAME":
790
+ case "NS": return yield* decode$9({
791
+ ...common,
792
+ _tag: record.type,
793
+ target: yield* content()
794
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message)));
795
+ case "TXT": return yield* decode$9({
796
+ ...common,
797
+ _tag: "TXT",
798
+ value: yield* content()
799
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message)));
800
+ case "MX": return yield* decode$9({
801
+ ...common,
802
+ _tag: "MX",
803
+ exchange: yield* content(),
804
+ priority: record.priority
805
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message)));
806
+ case "CAA": {
807
+ const data = yield* decodeData(record);
808
+ return yield* decode$9({
809
+ ...common,
810
+ _tag: "CAA",
811
+ ...data
812
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message)));
813
+ }
814
+ case "SRV": {
815
+ const data = yield* decodeData(record);
816
+ return yield* decode$9({
817
+ ...common,
818
+ _tag: "SRV",
819
+ ...data
820
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message)));
821
+ }
822
+ default: return yield* decodeOpaque$1(record);
823
+ }
824
+ }));
825
+ const decodeOpaque$1 = Effect.fn("CloudflareRecords.decodeOpaque")((record) => Schema.decodeUnknownEffect(Opaque)({
826
+ _tag: "Opaque",
827
+ name: record.name,
828
+ providerRecordId: record.id,
829
+ providerType: record.type
830
+ }).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message))));
831
+ function encode$1(record) {
832
+ const common = {
833
+ name: record.name,
834
+ proxied: false,
835
+ ttl: record.ttl ?? 1,
836
+ type: record._tag
837
+ };
838
+ switch (record._tag) {
839
+ case "A":
840
+ case "AAAA": return {
841
+ ...common,
842
+ content: record.address
843
+ };
844
+ case "CNAME":
845
+ case "NS": return {
846
+ ...common,
847
+ content: record.target
848
+ };
849
+ case "TXT": return {
850
+ ...common,
851
+ content: record.value
852
+ };
853
+ case "MX": return {
854
+ ...common,
855
+ content: record.exchange,
856
+ priority: record.priority
857
+ };
858
+ case "CAA": return {
859
+ ...common,
860
+ data: {
861
+ flags: record.flags,
862
+ tag: record.tag,
863
+ value: record.value
864
+ }
865
+ };
866
+ case "SRV": return {
867
+ ...common,
868
+ data: {
869
+ port: record.port,
870
+ priority: record.priority,
871
+ target: record.target,
872
+ weight: record.weight
873
+ }
874
+ };
875
+ }
876
+ }
877
+ const decodeData = Effect.fn("CloudflareRecords.decodeData")((record) => Schema.decodeUnknownEffect(Data$1)(record.data).pipe(Effect.mapError((cause) => failure$4("decodeRecord", cause.message))));
878
+ function failure$4(operation, message, fields = {}) {
879
+ return new Error$3({
880
+ message,
881
+ operation,
882
+ providerId: "cloudflare",
883
+ reason: fields.reason ?? "response"
884
+ });
885
+ }
886
+ //#endregion
887
+ //#region src/providers/cloudflare/client.ts
888
+ var client_exports$1 = /* @__PURE__ */ __exportAll({
889
+ discoverAuthorizationAccount: () => discoverAuthorizationAccount,
890
+ discovery: () => discovery$1,
891
+ make: () => make$5,
892
+ validateDomainToken: () => validateDomainToken
893
+ });
894
+ /** Exposes Cloudflare zone lookup as the optional provider discovery capability. */
895
+ function discovery$1(client) {
896
+ return {
897
+ listZones: (name) => client.listZones({ name }).pipe(Effect.map((zones) => zones.map((zone) => ({
898
+ ...zone,
899
+ status: zone.status === "active" || zone.status === "pending" ? zone.status : "unknown"
900
+ })))),
901
+ provider: client
902
+ };
903
+ }
904
+ const makeTransport = (options) => {
905
+ const fetch = options.fetch ?? globalThis.fetch;
906
+ const baseUrl = (options.baseUrl ?? "https://api.cloudflare.com/client/v4").replace(/\/$/, "");
907
+ const request = Effect.fn("CloudflareClient.request")((path, operation, init) => Effect.gen(function* () {
908
+ const response = yield* Effect.tryPromise({
909
+ try: () => fetch(`${baseUrl}${path}`, {
910
+ ...init,
911
+ headers: {
912
+ Accept: "application/json",
913
+ Authorization: `Bearer ${options.token.expose()}`,
914
+ ...init?.body === void 0 ? {} : { "Content-Type": "application/json" },
915
+ ...init?.headers
916
+ }
917
+ }),
918
+ catch: () => failure$3(operation, "Cloudflare request failed", { reason: "transport" })
919
+ });
920
+ return {
921
+ body: yield* Effect.tryPromise({
922
+ try: () => response.json(),
923
+ catch: () => {
924
+ const retryAfterMs = retryAfter(response.headers.get("retry-after"));
925
+ return failure$3(operation, response.ok ? "Cloudflare returned a non-JSON response" : `Cloudflare request failed with HTTP ${response.status}`, {
926
+ reason: response.ok ? "response" : reason$1(response.status),
927
+ ...retryAfterMs === void 0 ? {} : { retryAfterMs },
928
+ status: response.status
929
+ });
930
+ }
931
+ }),
932
+ response
933
+ };
934
+ }));
935
+ const listZonesPage = Effect.fn("CloudflareClient.listZonesPage")((accountId, name, page) => Effect.gen(function* () {
936
+ const query = new URLSearchParams({
937
+ page: String(page),
938
+ per_page: "50"
939
+ });
940
+ query.set("type", "full,partial,secondary,internal");
941
+ if (accountId !== void 0) query.set("account.id", accountId);
942
+ if (name !== void 0) query.set("name", name);
943
+ const { body, response } = yield* request(`/zones?${query}`, "listZones");
944
+ yield* ensureSuccess(body, "listZones", response);
945
+ return yield* decode$2(ZoneListEnvelope, body, "listZones", response);
946
+ }));
947
+ return {
948
+ allZones: Effect.fn("CloudflareClient.allZones")((accountId, name) => Effect.gen(function* () {
949
+ const zones = [];
950
+ let page = 1;
951
+ while (true) {
952
+ const envelope = yield* listZonesPage(accountId, name, page);
953
+ zones.push(...envelope.result);
954
+ const totalPages = envelope.result_info?.total_pages;
955
+ if (totalPages !== void 0 && page >= totalPages || totalPages === void 0 && envelope.result.length < 50) return zones;
956
+ page += 1;
957
+ }
958
+ })),
959
+ inspectToken: Effect.fn("CloudflareClient.inspectToken")((path) => Effect.gen(function* () {
960
+ const { body, response } = yield* request(path, "validateToken");
961
+ yield* ensureSuccess(body, "validateToken", response);
962
+ const envelope = yield* decode$2(TokenEnvelope, body, "validateToken", response);
963
+ if (envelope.result.status !== "active") return yield* Effect.fail(failure$3("validateToken", `Cloudflare token is ${envelope.result.status}`, {
964
+ reason: "authentication",
965
+ status: response.status
966
+ }));
967
+ const expiresAt = envelope.result.expires_on === void 0 ? null : new Date(envelope.result.expires_on);
968
+ if (expiresAt !== null && Number.isNaN(expiresAt.valueOf())) return yield* Effect.fail(failure$3("validateToken", "Cloudflare token expiry is not a valid timestamp", {
969
+ reason: "response",
970
+ status: response.status
971
+ }));
972
+ return expiresAt;
973
+ })),
974
+ request
975
+ };
976
+ };
977
+ const discoverAccount = Effect.fn("CloudflareClient.discoverAccount")((options) => Effect.gen(function* () {
978
+ const { allZones } = makeTransport(options);
979
+ for (const candidate of candidates(options.domain)) {
980
+ const matches = yield* allZones(void 0, candidate);
981
+ const match = matches[0];
982
+ if (matches.length === 0) continue;
983
+ if (matches.length === 1 && match !== void 0) return match.account;
984
+ return yield* Effect.fail(failure$3("discoverAccount", `Cloudflare returned multiple accessible zones named ${candidate}`, { reason: "conflict" }));
985
+ }
986
+ return yield* Effect.fail(failure$3("discoverAccount", `Cloudflare did not expose an accessible zone for ${options.domain}`, { reason: "not_found" }));
987
+ }));
988
+ const discoverAuthorizationAccount = discoverAccount;
989
+ const validateDomainToken = Effect.fn("CloudflareClient.validateDomainToken")((options) => Effect.gen(function* () {
990
+ const transport = makeTransport(options);
991
+ const account = options.tokenKind === "account" ? yield* discoverAccount(options) : void 0;
992
+ const expiresAt = yield* transport.inspectToken(account === void 0 ? "/user/tokens/verify" : `/accounts/${encodeURIComponent(account.id)}/tokens/verify`);
993
+ return {
994
+ accountId: (account ?? (yield* discoverAccount(options))).id,
995
+ capabilities: options.capabilities,
996
+ expiresAt,
997
+ scopes: []
998
+ };
999
+ }));
1000
+ /** Creates an Effect-native Cloudflare client without owning the credential lifecycle. */
1001
+ function make$5(options) {
1002
+ const { allZones, inspectToken, request } = makeTransport(options);
1003
+ const resolveZone = Effect.fn("CloudflareClient.resolveZone")((name) => Effect.gen(function* () {
1004
+ const matches = yield* allZones(options.accountId, name);
1005
+ const match = matches[0];
1006
+ if (matches.length === 1 && match !== void 0) return match;
1007
+ return yield* Effect.fail(failure$3("resolveZone", matches.length === 0 ? `Cloudflare zone ${name} was not found in account ${options.accountId}` : `Cloudflare returned multiple zones named ${name} in account ${options.accountId}`, { reason: matches.length === 0 ? "not_found" : "response" }));
1008
+ }));
1009
+ const listRecords = Effect.fn("CloudflareClient.listRecords")((zoneName) => Effect.gen(function* () {
1010
+ const zone = yield* resolveZone(zoneName);
1011
+ const records = [];
1012
+ let page = 1;
1013
+ while (true) {
1014
+ const query = new URLSearchParams({
1015
+ page: String(page),
1016
+ per_page: "100"
1017
+ });
1018
+ const { body, response } = yield* request(`/zones/${encodeURIComponent(zone.id)}/dns_records?${query}`, "listRecords");
1019
+ yield* ensureSuccess(body, "listRecords", response);
1020
+ const envelope = yield* decode$2(RecordListEnvelope$1, body, "listRecords", response);
1021
+ records.push(...yield* Effect.forEach(envelope.result, decode$3));
1022
+ const totalPages = envelope.result_info?.total_pages;
1023
+ if (totalPages !== void 0 && page >= totalPages || totalPages === void 0 && envelope.result.length < 100) return records;
1024
+ page += 1;
1025
+ }
1026
+ }));
1027
+ const createRecord = Effect.fn("CloudflareClient.createRecord")((zoneName, record) => Effect.gen(function* () {
1028
+ const zone = yield* resolveZone(zoneName);
1029
+ const { body, response } = yield* request(`/zones/${encodeURIComponent(zone.id)}/dns_records`, "createRecord", {
1030
+ body: JSON.stringify(encode$1(record)),
1031
+ method: "POST"
1032
+ });
1033
+ yield* ensureSuccess(body, "createRecord", response);
1034
+ return { providerRecordId: (yield* decode$2(RecordEnvelope, body, "createRecord", response)).result.id };
1035
+ }));
1036
+ const getRecord = Effect.fn("CloudflareClient.getRecord")((zoneName, providerRecordId) => Effect.gen(function* () {
1037
+ const zone = yield* resolveZone(zoneName);
1038
+ const { body, response } = yield* request(`/zones/${encodeURIComponent(zone.id)}/dns_records/${encodeURIComponent(providerRecordId)}`, "getRecord");
1039
+ if (response.status === 404) return null;
1040
+ yield* ensureSuccess(body, "getRecord", response);
1041
+ const envelope = yield* decode$2(RecordEnvelope, body, "getRecord", response);
1042
+ return yield* decode$3(envelope.result);
1043
+ }));
1044
+ return {
1045
+ id: "cloudflare",
1046
+ createRecord,
1047
+ deleteRecord: Effect.fn("CloudflareClient.deleteRecord")((zoneName, providerRecordId) => Effect.gen(function* () {
1048
+ const zone = yield* resolveZone(zoneName);
1049
+ const { body, response } = yield* request(`/zones/${encodeURIComponent(zone.id)}/dns_records/${encodeURIComponent(providerRecordId)}`, "deleteRecord", { method: "DELETE" });
1050
+ yield* ensureSuccess(body, "deleteRecord", response);
1051
+ })),
1052
+ getRecord,
1053
+ listAccounts: Effect.fn("CloudflareClient.listAccounts")(() => allZones().pipe(Effect.map((zones) => {
1054
+ const accounts = /* @__PURE__ */ new Map();
1055
+ for (const zone of zones) accounts.set(zone.account.id, zone.account);
1056
+ return [...accounts.values()].sort((left, right) => left.name.localeCompare(right.name));
1057
+ }))),
1058
+ listRecords,
1059
+ listZones: Effect.fn("CloudflareClient.listZones")((input = {}) => allZones(input.accountId ?? options.accountId, input.name).pipe(Effect.flatMap((zones) => Effect.forEach(zones, projectZone$1)))),
1060
+ validateToken: Effect.fn("CloudflareClient.validateToken")(() => Effect.gen(function* () {
1061
+ const path = options.tokenKind === "account" ? `/accounts/${encodeURIComponent(options.accountId)}/tokens/verify` : "/user/tokens/verify";
1062
+ const expiresAt = yield* inspectToken(path);
1063
+ yield* allZones(options.accountId);
1064
+ return {
1065
+ accountId: options.accountId,
1066
+ capabilities: options.capabilities,
1067
+ expiresAt,
1068
+ scopes: []
1069
+ };
1070
+ }))
1071
+ };
1072
+ }
1073
+ const projectZone$1 = Effect.fn("CloudflareClient.projectZone")((zone) => Effect.gen(function* () {
1074
+ const name = yield* decode$8(zone.name).pipe(Effect.mapError((cause) => failure$3("listZones", cause.message, { reason: "response" })));
1075
+ const nameservers = yield* Effect.forEach(zone.name_servers, (nameserver) => decode$8(nameserver).pipe(Effect.mapError((cause) => failure$3("listZones", cause.message, { reason: "response" }))));
1076
+ return {
1077
+ accountId: zone.account.id,
1078
+ id: zone.id,
1079
+ name,
1080
+ nameservers,
1081
+ status: zone.status ?? null
1082
+ };
1083
+ }));
1084
+ function decode$2(schema, input, operation, response) {
1085
+ return Schema.decodeUnknownEffect(schema)(input).pipe(Effect.mapError((cause) => failure$3(operation, `Cloudflare response did not match its API contract: ${cause.message}`, {
1086
+ reason: "response",
1087
+ status: response.status
1088
+ })));
1089
+ }
1090
+ function ensureSuccess(input, operation, response) {
1091
+ return Schema.decodeUnknownEffect(BaseEnvelope)(input).pipe(Effect.mapError(() => failure$3(operation, "Cloudflare response did not contain a valid API envelope", {
1092
+ reason: "response",
1093
+ status: response.status
1094
+ })), Effect.flatMap((envelope) => {
1095
+ if (response.ok && envelope.success) return Effect.void;
1096
+ const detail = envelope.errors[0];
1097
+ const retryAfterMs = retryAfter(response.headers.get("retry-after"));
1098
+ return Effect.fail(failure$3(operation, detail?.message ?? `Cloudflare request failed with HTTP ${response.status}`, {
1099
+ ...detail === void 0 ? {} : { code: detail.code },
1100
+ reason: reason$1(response.status, detail?.code),
1101
+ ...retryAfterMs === void 0 ? {} : { retryAfterMs },
1102
+ status: response.status
1103
+ }));
1104
+ }));
1105
+ }
1106
+ function reason$1(status, code) {
1107
+ if (status === 401) return "authentication";
1108
+ if (status === 403) return "authorization";
1109
+ if (status === 404) return "not_found";
1110
+ if (status === 409 || code === 81056 || code === 81057 || code === 81058) return "conflict";
1111
+ if (status === 429) return "rate_limit";
1112
+ if (status >= 500) return "response";
1113
+ return "request";
1114
+ }
1115
+ function retryAfter(value) {
1116
+ if (value === null) return void 0;
1117
+ const seconds = Number(value);
1118
+ if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
1119
+ const date = Date.parse(value);
1120
+ return Number.isNaN(date) ? void 0 : Math.max(0, date - Date.now());
1121
+ }
1122
+ function failure$3(operation, message, fields = {}) {
1123
+ return new Error$3({
1124
+ ...fields,
1125
+ message,
1126
+ operation,
1127
+ providerId: "cloudflare"
1128
+ });
1129
+ }
1130
+ //#endregion
1131
+ //#region src/providers/cloudflare/auth.ts
1132
+ var auth_exports$1 = /* @__PURE__ */ __exportAll({
1133
+ contextCodec: () => contextCodec$1,
1134
+ manifest: () => manifest$1,
1135
+ oauthAuthentication: () => oauthAuthentication,
1136
+ oauthFlow: () => oauthFlow,
1137
+ oauthMethod: () => oauthMethod,
1138
+ subjectResolver: () => subjectResolver,
1139
+ tokenConnectionMethod: () => tokenConnectionMethod$1,
1140
+ tokenMethod: () => tokenMethod$1,
1141
+ tokenValidator: () => tokenValidator
1142
+ });
1143
+ const authorizationServer = {
1144
+ authorization_endpoint: "https://dash.cloudflare.com/oauth2/auth",
1145
+ issuer: "https://dash.cloudflare.com",
1146
+ revocation_endpoint: "https://dash.cloudflare.com/oauth2/revoke",
1147
+ token_endpoint: "https://dash.cloudflare.com/oauth2/token"
1148
+ };
1149
+ const contextCodec$1 = codec("cloudflare.v1", Schema.Struct({ tokenKind: Schema.Literals(["account", "user"]) }));
1150
+ /** Describes Cloudflare's caller-created API-token authorization method. */
1151
+ function tokenMethod$1(capabilities) {
1152
+ return {
1153
+ _tag: "token",
1154
+ capabilities: [...capabilities],
1155
+ instructionsUrl: "https://developers.cloudflare.com/fundamentals/api/get-started/create-token/"
1156
+ };
1157
+ }
1158
+ /** Describes a registered Cloudflare OAuth client and its assigned scope IDs. */
1159
+ function oauthMethod(options) {
1160
+ return {
1161
+ _tag: "oauth2",
1162
+ authorizationServer,
1163
+ capabilities: [...options.capabilities],
1164
+ clientAuth: options.clientAuth,
1165
+ scopes: [...options.scopes]
1166
+ };
1167
+ }
1168
+ /** Creates the Cloudflare token and OAuth authorization manifest. */
1169
+ function manifest$1(options) {
1170
+ return {
1171
+ methods: [tokenMethod$1(options.capabilities), oauthMethod(options)],
1172
+ providerId: "cloudflare"
1173
+ };
1174
+ }
1175
+ /** Resolves the Cloudflare account selected by a completed OAuth grant. */
1176
+ function subjectResolver(options) {
1177
+ return (tokens, accessToken) => Effect.gen(function* () {
1178
+ const accountId = options.accountId ?? (yield* discoverAuthorizationAccount({
1179
+ ...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
1180
+ domain: options.domain,
1181
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1182
+ token: accessToken
1183
+ }).pipe(Effect.map((account) => account.id)));
1184
+ if (options.accountId !== void 0) yield* make$5({
1185
+ accountId: options.accountId,
1186
+ ...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
1187
+ capabilities: options.capabilities,
1188
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1189
+ token: accessToken,
1190
+ tokenKind: "user"
1191
+ }).listZones();
1192
+ const now = yield* Clock.currentTimeMillis;
1193
+ return {
1194
+ accountId,
1195
+ expiresAt: typeof tokens.expires_in === "number" ? new Date(now + tokens.expires_in * 1e3) : null
1196
+ };
1197
+ });
1198
+ }
1199
+ /** Creates a host callback that validates a Cloudflare API token. */
1200
+ function tokenValidator(options) {
1201
+ return (token) => options.accountId === void 0 ? validateDomainToken({
1202
+ ...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
1203
+ capabilities: options.capabilities,
1204
+ domain: options.domain,
1205
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1206
+ token,
1207
+ ...options.tokenKind === void 0 ? {} : { tokenKind: options.tokenKind }
1208
+ }) : make$5({
1209
+ accountId: options.accountId,
1210
+ ...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
1211
+ capabilities: options.capabilities,
1212
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1213
+ token,
1214
+ ...options.tokenKind === void 0 ? {} : { tokenKind: options.tokenKind }
1215
+ }).validateToken();
1216
+ }
1217
+ /** Creates a provider-independent token connection method backed by Cloudflare validation. */
1218
+ function tokenConnectionMethod$1(options) {
1219
+ const requiredCapabilities = [...options.capabilities];
1220
+ return Method$1.Token({
1221
+ authenticate: Effect.fn("CloudflareAuth.authenticateToken")(function* (token) {
1222
+ const validated = yield* tokenValidator(options)(token);
1223
+ const observedAt = new Date(yield* Clock.currentTimeMillis);
1224
+ return {
1225
+ capabilityEvidence: validated.capabilities.map((capability) => ({
1226
+ capability,
1227
+ evidence: Evidence$1.Introspected({ observedAt })
1228
+ })),
1229
+ credential: {
1230
+ accessToken: token,
1231
+ refreshToken: null,
1232
+ tokenType: "bearer"
1233
+ },
1234
+ expiresAt: validated.expiresAt,
1235
+ providerAccountId: validated.accountId,
1236
+ providerContext: yield* contextCodec$1.encode({ tokenKind: options.tokenKind ?? "user" }),
1237
+ scopes: [...validated.scopes]
1238
+ };
1239
+ }),
1240
+ providerId: "cloudflare",
1241
+ requiredCapabilities,
1242
+ token: options.token
1243
+ });
1244
+ }
1245
+ /** Converts a completed Cloudflare OAuth grant into the canonical connection authentication. */
1246
+ const oauthAuthentication = Effect.fn("CloudflareAuth.oauthAuthentication")(function* (options) {
1247
+ const resolved = yield* subjectResolver(options)(options.tokens, options.accessToken);
1248
+ const observedAt = new Date(yield* Clock.currentTimeMillis);
1249
+ return {
1250
+ capabilityEvidence: options.capabilities.map((capability) => ({
1251
+ capability,
1252
+ evidence: Evidence$1.Introspected({ observedAt })
1253
+ })),
1254
+ credential: {
1255
+ accessToken: options.accessToken,
1256
+ refreshToken: options.tokens.refresh_token === void 0 ? null : Value.from(options.tokens.refresh_token),
1257
+ tokenType: options.tokens.token_type
1258
+ },
1259
+ expiresAt: resolved.expiresAt,
1260
+ providerAccountId: resolved.accountId,
1261
+ providerContext: yield* contextCodec$1.encode({ tokenKind: "user" }),
1262
+ scopes: (options.tokens.scope ?? "").split(" ").filter(Boolean)
1263
+ };
1264
+ });
1265
+ /** Creates Cloudflare's OAuth implementation of the common interactive connection capability. */
1266
+ function oauthFlow(options) {
1267
+ const method = oauthMethod({
1268
+ capabilities: options.capabilities,
1269
+ clientAuth: options.clientAuth,
1270
+ scopes: options.scopes
1271
+ });
1272
+ return {
1273
+ complete: Effect.fn("CloudflareAuth.oauthFlow.complete")(function* (payload, callbackUrl) {
1274
+ const tokens = yield* complete({
1275
+ callbackUrl,
1276
+ client: options.client,
1277
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1278
+ method,
1279
+ payload,
1280
+ providerId: "cloudflare"
1281
+ });
1282
+ return yield* oauthAuthentication({
1283
+ ...options.accountId === void 0 ? { domain: options.domain } : { accountId: options.accountId },
1284
+ ...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
1285
+ capabilities: options.capabilities,
1286
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1287
+ accessToken: make$6(tokens.access_token),
1288
+ tokens
1289
+ });
1290
+ }),
1291
+ method: "oauth2",
1292
+ providerId: "cloudflare",
1293
+ requiredCapabilities: [...options.capabilities],
1294
+ start: (continuationId) => start({
1295
+ client: options.client,
1296
+ method,
1297
+ redirectUri: options.redirectUri,
1298
+ state: continuationId
1299
+ })
1300
+ };
1301
+ }
1302
+ //#endregion
1303
+ //#region src/providers/vercel/protocol.ts
1304
+ const Pagination = Schema.Struct({
1305
+ count: Schema.Number,
1306
+ next: Schema.NullOr(Schema.Number),
1307
+ prev: Schema.NullOr(Schema.Number)
1308
+ });
1309
+ const ErrorDetail = Schema.Struct({
1310
+ code: Schema.String,
1311
+ message: Schema.String,
1312
+ limit: Schema.optionalKey(Schema.Struct({
1313
+ remaining: Schema.Number,
1314
+ reset: Schema.optionalKey(Schema.Number),
1315
+ resetMs: Schema.optionalKey(Schema.Number),
1316
+ total: Schema.Number
1317
+ }))
1318
+ });
1319
+ const ErrorEnvelope = Schema.Struct({ error: ErrorDetail });
1320
+ const User = Schema.Struct({
1321
+ id: Schema.String,
1322
+ name: Schema.NullOr(Schema.String),
1323
+ username: Schema.String
1324
+ });
1325
+ const UserEnvelope = Schema.Struct({ user: User });
1326
+ const Team = Schema.Struct({
1327
+ id: Schema.String,
1328
+ name: Schema.NullOr(Schema.String),
1329
+ slug: Schema.String
1330
+ });
1331
+ const TeamListEnvelope = Schema.Struct({
1332
+ pagination: Pagination,
1333
+ teams: Schema.Array(Team)
1334
+ });
1335
+ const Domain = Schema.Struct({
1336
+ id: Schema.String,
1337
+ intendedNameservers: Schema.Array(Schema.String),
1338
+ name: Schema.String,
1339
+ nameservers: Schema.Array(Schema.String),
1340
+ serviceType: Schema.Literals([
1341
+ "zeit.world",
1342
+ "external",
1343
+ "na"
1344
+ ]),
1345
+ teamId: Schema.NullOr(Schema.String),
1346
+ userId: Schema.String,
1347
+ verified: Schema.Boolean,
1348
+ zone: Schema.optionalKey(Schema.Boolean)
1349
+ });
1350
+ const DomainConfig = Schema.Struct({
1351
+ misconfigured: Schema.Boolean,
1352
+ serviceType: Schema.Literals([
1353
+ "zeit.world",
1354
+ "external",
1355
+ "na"
1356
+ ])
1357
+ });
1358
+ const DomainEnvelope = Schema.Struct({ domain: Domain });
1359
+ const DomainListEnvelope = Schema.Struct({
1360
+ domains: Schema.Array(Domain),
1361
+ pagination: Pagination
1362
+ });
1363
+ const Record = Schema.Struct({
1364
+ id: Schema.String,
1365
+ mxPriority: Schema.optionalKey(Schema.Number),
1366
+ name: Schema.String,
1367
+ priority: Schema.optionalKey(Schema.Number),
1368
+ ttl: Schema.optionalKey(Schema.Number),
1369
+ type: Schema.String,
1370
+ value: Schema.String
1371
+ });
1372
+ const RecordListEnvelope = Schema.Struct({
1373
+ pagination: Schema.optionalKey(Pagination),
1374
+ records: Schema.Array(Record)
1375
+ });
1376
+ const CreateRecordEnvelope = Schema.Struct({
1377
+ uid: Schema.String,
1378
+ updated: Schema.optionalKey(Schema.Number)
1379
+ });
1380
+ const IntegrationToken = Schema.Struct({
1381
+ access_token: Schema.String,
1382
+ installation_id: Schema.optionalKey(Schema.String),
1383
+ team_id: Schema.NullOr(Schema.String),
1384
+ token_type: Schema.optionalKey(Schema.String),
1385
+ user_id: Schema.String
1386
+ });
1387
+ //#endregion
1388
+ //#region src/providers/vercel/records.ts
1389
+ const decode$1 = Effect.fn("VercelRecords.decode")((zone, record) => Effect.gen(function* () {
1390
+ const absolute = absoluteNameCandidate(zone, record.name);
1391
+ const name = yield* decode$8(absolute).pipe(Effect.match({
1392
+ onFailure: () => null,
1393
+ onSuccess: (value) => value
1394
+ }));
1395
+ if (name === null) return yield* decodeOpaque(record, absolute);
1396
+ const common = {
1397
+ metadata: {
1398
+ ownership: "provider",
1399
+ provenance: "vercel",
1400
+ purpose: "existing DNS record"
1401
+ },
1402
+ name,
1403
+ policy: record.type === "CNAME" ? "exclusive" : "append",
1404
+ ttl: record.ttl ?? 60
1405
+ };
1406
+ const fromRecord = (input) => decode$9(input).pipe(Effect.mapError((cause) => failure$2("decodeRecord", cause.message)));
1407
+ switch (record.type) {
1408
+ case "A":
1409
+ case "AAAA": return yield* fromRecord({
1410
+ ...common,
1411
+ _tag: record.type,
1412
+ address: record.value
1413
+ });
1414
+ case "CNAME":
1415
+ case "NS": return yield* fromRecord({
1416
+ ...common,
1417
+ _tag: record.type,
1418
+ target: record.value
1419
+ });
1420
+ case "TXT": return yield* fromRecord({
1421
+ ...common,
1422
+ _tag: "TXT",
1423
+ value: record.value
1424
+ });
1425
+ case "MX": return yield* fromRecord({
1426
+ ...common,
1427
+ _tag: "MX",
1428
+ exchange: record.value,
1429
+ priority: record.mxPriority ?? record.priority
1430
+ });
1431
+ case "CAA": {
1432
+ const match = record.value.match(/^(\d{1,3})\s+(issue|issuewild|iodef)\s+(?:"((?:\\.|[^"])*)"|(\S.*))$/);
1433
+ if (match === null) return yield* Effect.fail(failure$2("decodeRecord", "Vercel CAA record has an invalid value"));
1434
+ return yield* fromRecord({
1435
+ ...common,
1436
+ _tag: "CAA",
1437
+ flags: Number(match[1]),
1438
+ tag: match[2],
1439
+ value: unescapeQuoted(match[3] ?? match[4] ?? "")
1440
+ });
1441
+ }
1442
+ case "SRV": {
1443
+ const parts = record.value.trim().split(/\s+/);
1444
+ const [priority, weight, port, target] = parts.length === 4 ? parts : [
1445
+ String(record.priority ?? ""),
1446
+ parts[0],
1447
+ parts[1],
1448
+ parts[2]
1449
+ ];
1450
+ return yield* fromRecord({
1451
+ ...common,
1452
+ _tag: "SRV",
1453
+ port: Number(port),
1454
+ priority: Number(priority),
1455
+ target,
1456
+ weight: Number(weight)
1457
+ });
1458
+ }
1459
+ default: return yield* decodeOpaque(record, name);
1460
+ }
1461
+ }));
1462
+ const decodeOpaque = Effect.fn("VercelRecords.decodeOpaque")((record, name) => Schema.decodeUnknownEffect(Opaque)({
1463
+ _tag: "Opaque",
1464
+ name,
1465
+ providerRecordId: record.id,
1466
+ providerType: record.type
1467
+ }).pipe(Effect.mapError((cause) => failure$2("decodeRecord", cause.message))));
1468
+ function encode(zone, record) {
1469
+ const common = {
1470
+ name: relativeName(zone, record.name),
1471
+ ...record.ttl === null ? {} : { ttl: record.ttl },
1472
+ type: record._tag
1473
+ };
1474
+ switch (record._tag) {
1475
+ case "A":
1476
+ case "AAAA": return {
1477
+ ...common,
1478
+ value: record.address
1479
+ };
1480
+ case "CNAME":
1481
+ case "NS": return {
1482
+ ...common,
1483
+ value: record.target
1484
+ };
1485
+ case "TXT": return {
1486
+ ...common,
1487
+ value: record.value
1488
+ };
1489
+ case "MX": return {
1490
+ ...common,
1491
+ mxPriority: record.priority,
1492
+ value: record.exchange
1493
+ };
1494
+ case "CAA": return {
1495
+ ...common,
1496
+ value: `${record.flags} ${record.tag} "${escapeQuoted(record.value)}"`
1497
+ };
1498
+ case "SRV": return {
1499
+ ...common,
1500
+ srv: {
1501
+ port: record.port,
1502
+ priority: record.priority,
1503
+ target: record.target,
1504
+ weight: record.weight
1505
+ }
1506
+ };
1507
+ }
1508
+ }
1509
+ function absoluteNameCandidate(zone, name) {
1510
+ return name === "" || name === "@" ? zone : name === zone || name.endsWith(`.${zone}`) ? name : `${name}.${zone}`;
1511
+ }
1512
+ function relativeName(zone, name) {
1513
+ if (name === zone) return "";
1514
+ const suffix = `.${zone}`;
1515
+ if (!name.endsWith(suffix)) throw failure$2("encodeRecord", `DNS record ${name} is outside Vercel zone ${zone}`, { reason: "request" });
1516
+ return name.slice(0, -suffix.length);
1517
+ }
1518
+ function escapeQuoted(value) {
1519
+ return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
1520
+ }
1521
+ function unescapeQuoted(value) {
1522
+ return value.replace(/\\([\\"])/g, "$1");
1523
+ }
1524
+ function failure$2(operation, message, fields = {}) {
1525
+ return new Error$3({
1526
+ message,
1527
+ operation,
1528
+ providerId: "vercel",
1529
+ reason: fields.reason ?? "response"
1530
+ });
1531
+ }
1532
+ //#endregion
1533
+ //#region src/providers/vercel/client.ts
1534
+ var client_exports = /* @__PURE__ */ __exportAll({
1535
+ discovery: () => discovery,
1536
+ make: () => make$4
1537
+ });
1538
+ /** Exposes Vercel zone lookup as the optional provider discovery capability. */
1539
+ function discovery(client) {
1540
+ return {
1541
+ listZones: (name) => client.listZones({ name }),
1542
+ provider: client
1543
+ };
1544
+ }
1545
+ /** Creates an Effect-native Vercel client without owning the credential lifecycle. */
1546
+ function make$4(options) {
1547
+ const fetch = options.fetch ?? globalThis.fetch;
1548
+ const baseUrl = (options.baseUrl ?? "https://api.vercel.com").replace(/\/$/, "");
1549
+ const withContext = (path, values = {}) => {
1550
+ const url = new URL(`${baseUrl}${path}`);
1551
+ for (const [key, value] of Object.entries(values)) url.searchParams.set(key, value);
1552
+ if (options.context._tag === "team") url.searchParams.set("teamId", options.context.teamId);
1553
+ return url;
1554
+ };
1555
+ const request = Effect.fn("VercelClient.request")((url, operation, init) => Effect.gen(function* () {
1556
+ const response = yield* Effect.tryPromise({
1557
+ try: () => fetch(url, {
1558
+ ...init,
1559
+ headers: {
1560
+ Accept: "application/json",
1561
+ Authorization: `Bearer ${options.token.expose()}`,
1562
+ ...init?.body === void 0 ? {} : { "Content-Type": "application/json" },
1563
+ ...init?.headers
1564
+ }
1565
+ }),
1566
+ catch: () => failure$1(operation, "Vercel request failed", { reason: "transport" })
1567
+ });
1568
+ const body = yield* Effect.tryPromise({
1569
+ try: () => response.json(),
1570
+ catch: () => failure$1(operation, response.ok ? "Vercel returned a non-JSON response" : `Vercel request failed with HTTP ${response.status}`, {
1571
+ reason: response.ok ? "response" : reason(response.status),
1572
+ ...rateLimit(response),
1573
+ status: response.status
1574
+ })
1575
+ });
1576
+ if (!response.ok) return yield* Effect.fail(apiFailure(body, operation, response));
1577
+ return {
1578
+ body,
1579
+ response
1580
+ };
1581
+ }));
1582
+ const allTeams = Effect.fn("VercelClient.allTeams")(() => Effect.gen(function* () {
1583
+ const teams = [];
1584
+ let until = null;
1585
+ while (true) {
1586
+ const url = new URL(`${baseUrl}/v2/teams`);
1587
+ url.searchParams.set("limit", "100");
1588
+ if (until !== null) url.searchParams.set("until", String(until));
1589
+ const { body, response } = yield* request(url, "listAccounts");
1590
+ const envelope = yield* decode(TeamListEnvelope, body, "listAccounts", response);
1591
+ teams.push(...envelope.teams);
1592
+ if (envelope.pagination.next === null) return teams;
1593
+ until = envelope.pagination.next;
1594
+ }
1595
+ }));
1596
+ const allDomains = Effect.fn("VercelClient.allDomains")(() => Effect.gen(function* () {
1597
+ const domains = [];
1598
+ let until = null;
1599
+ while (true) {
1600
+ const values = { limit: "100" };
1601
+ if (until !== null) values.until = String(until);
1602
+ const { body, response } = yield* request(withContext("/v5/domains", values), "listZones");
1603
+ const envelope = yield* decode(DomainListEnvelope, body, "listZones", response);
1604
+ domains.push(...envelope.domains);
1605
+ if (envelope.pagination.next === null) return domains;
1606
+ until = envelope.pagination.next;
1607
+ }
1608
+ }));
1609
+ const discoverZone = Effect.fn("VercelClient.discoverZone")((name) => Effect.gen(function* () {
1610
+ const configResult = yield* request(withContext(`/v6/domains/${encodeURIComponent(name)}/config`), "resolveZone");
1611
+ const config = yield* decode(DomainConfig, configResult.body, "resolveZone", configResult.response);
1612
+ const domainResult = yield* request(withContext(`/v5/domains/${encodeURIComponent(name)}`), "resolveZone");
1613
+ const envelope = yield* decode(DomainEnvelope, domainResult.body, "resolveZone", domainResult.response);
1614
+ if (!hasDnsStorage(envelope.domain, config.serviceType)) return null;
1615
+ return envelope.domain;
1616
+ }).pipe(Effect.catchTag("ProviderError", (cause) => cause.reason === "not_found" ? Effect.succeed(null) : Effect.fail(cause))));
1617
+ const resolveZone = Effect.fn("VercelClient.resolveZone")((name) => Effect.gen(function* () {
1618
+ const domain = yield* discoverZone(name);
1619
+ if (domain === null) return yield* Effect.fail(failure$1("resolveZone", `Vercel zone ${name} is not configured for authoritative DNS in the selected account`, { reason: "not_found" }));
1620
+ return yield* decode$8(domain.name).pipe(Effect.mapError((cause) => failure$1("resolveZone", `Vercel returned an invalid storage zone: ${cause.message}`)));
1621
+ }));
1622
+ const listRecords = Effect.fn("VercelClient.listRecords")((zoneName) => Effect.gen(function* () {
1623
+ const storageZone = yield* resolveZone(zoneName);
1624
+ const records = [];
1625
+ let until = null;
1626
+ while (true) {
1627
+ const values = { limit: "100" };
1628
+ if (until !== null) values.until = String(until);
1629
+ const { body, response } = yield* request(withContext(`/v5/domains/${encodeURIComponent(storageZone)}/records`, values), "listRecords");
1630
+ const envelope = yield* decode(RecordListEnvelope, body, "listRecords", response);
1631
+ records.push(...yield* Effect.forEach(envelope.records, (record) => decode$1(storageZone, record)));
1632
+ const next = envelope.pagination?.next ?? null;
1633
+ if (next === null) return records.filter((record) => record.name === zoneName || record.name.endsWith(`.${zoneName}`));
1634
+ until = next;
1635
+ }
1636
+ }));
1637
+ const createRecord = Effect.fn("VercelClient.createRecord")((zoneName, record) => Effect.gen(function* () {
1638
+ const storageZone = yield* resolveZone(zoneName);
1639
+ const body = yield* Effect.try({
1640
+ try: () => encode(storageZone, record),
1641
+ catch: (cause) => cause instanceof Error$3 ? cause : failure$1("createRecord", "Vercel record could not be encoded", { reason: "request" })
1642
+ });
1643
+ const result = yield* request(withContext(`/v2/domains/${encodeURIComponent(storageZone)}/records`), "createRecord", {
1644
+ body: JSON.stringify(body),
1645
+ method: "POST"
1646
+ });
1647
+ return { providerRecordId: (yield* decode(CreateRecordEnvelope, result.body, "createRecord", result.response)).uid };
1648
+ }));
1649
+ const getRecord = Effect.fn("VercelClient.getRecord")((zoneName, providerRecordId) => Effect.gen(function* () {
1650
+ const storageZone = yield* resolveZone(zoneName);
1651
+ let until = null;
1652
+ while (true) {
1653
+ const values = { limit: "100" };
1654
+ if (until !== null) values.until = String(until);
1655
+ const { body, response } = yield* request(withContext(`/v5/domains/${encodeURIComponent(storageZone)}/records`, values), "getRecord");
1656
+ const envelope = yield* decode(RecordListEnvelope, body, "getRecord", response);
1657
+ const record = envelope.records.find(({ id }) => id === providerRecordId);
1658
+ if (record !== void 0) return yield* decode$1(storageZone, record);
1659
+ const next = envelope.pagination?.next ?? null;
1660
+ if (next === null) return null;
1661
+ until = next;
1662
+ }
1663
+ }));
1664
+ return {
1665
+ id: "vercel",
1666
+ createRecord,
1667
+ deleteRecord: Effect.fn("VercelClient.deleteRecord")((zoneName, providerRecordId) => Effect.gen(function* () {
1668
+ const storageZone = yield* resolveZone(zoneName);
1669
+ yield* request(withContext(`/v2/domains/${encodeURIComponent(storageZone)}/records/${encodeURIComponent(providerRecordId)}`), "deleteRecord", { method: "DELETE" });
1670
+ })),
1671
+ getRecord,
1672
+ listAccounts: Effect.fn("VercelClient.listAccounts")(() => Effect.gen(function* () {
1673
+ const userResult = yield* request(new URL(`${baseUrl}/v2/user`), "listAccounts");
1674
+ const { user } = yield* decode(UserEnvelope, userResult.body, "listAccounts", userResult.response);
1675
+ const teams = yield* allTeams();
1676
+ return [{
1677
+ id: user.id,
1678
+ name: user.name ?? user.username,
1679
+ type: "personal"
1680
+ }, ...teams.map((team) => ({
1681
+ id: team.id,
1682
+ name: team.name ?? team.slug,
1683
+ type: "team"
1684
+ }))];
1685
+ })),
1686
+ listRecords,
1687
+ listZones: Effect.fn("VercelClient.listZones")((input = {}) => Effect.gen(function* () {
1688
+ const domains = (yield* allDomains()).filter((domain) => hasDnsStorage(domain) && (input.name === void 0 || domain.name === input.name));
1689
+ if (domains.length > 0 || input.name === void 0) return yield* Effect.forEach(domains, projectZone);
1690
+ const discovered = yield* discoverZone(input.name);
1691
+ return discovered === null ? [] : [yield* projectZone(discovered)];
1692
+ })),
1693
+ validateToken: Effect.fn("VercelClient.validateToken")(() => Effect.gen(function* () {
1694
+ let accountId;
1695
+ if (options.context._tag === "team") {
1696
+ yield* allDomains();
1697
+ accountId = options.context.teamId;
1698
+ } else {
1699
+ const result = yield* request(new URL(`${baseUrl}/v2/user`), "validateToken");
1700
+ const { user } = yield* decode(UserEnvelope, result.body, "validateToken", result.response);
1701
+ accountId = user.id;
1702
+ }
1703
+ return {
1704
+ accountId,
1705
+ capabilities: options.capabilities,
1706
+ expiresAt: null,
1707
+ scopes: []
1708
+ };
1709
+ }))
1710
+ };
1711
+ }
1712
+ function hasDnsStorage(domain, configuredServiceType = domain.serviceType) {
1713
+ return configuredServiceType === "zeit.world" || domain.zone === true || domain.intendedNameservers.length > 0;
1714
+ }
1715
+ const projectZone = Effect.fn("VercelClient.projectZone")((domain) => Effect.gen(function* () {
1716
+ const name = yield* decode$8(domain.name).pipe(Effect.mapError((cause) => failure$1("listZones", cause.message, { reason: "response" })));
1717
+ const nameservers = yield* Effect.forEach(domain.intendedNameservers, (nameserver) => decode$8(nameserver).pipe(Effect.mapError((cause) => failure$1("listZones", cause.message, { reason: "response" }))));
1718
+ return {
1719
+ accountId: domain.teamId ?? domain.userId,
1720
+ id: domain.id,
1721
+ name,
1722
+ nameservers,
1723
+ status: domain.verified ? "active" : "pending"
1724
+ };
1725
+ }));
1726
+ function decode(schema, input, operation, response) {
1727
+ return Schema.decodeUnknownEffect(schema)(input).pipe(Effect.mapError((cause) => failure$1(operation, `Vercel response did not match its API contract: ${cause.message}`, {
1728
+ reason: "response",
1729
+ status: response.status
1730
+ })));
1731
+ }
1732
+ function apiFailure(input, operation, response) {
1733
+ const detail = Schema.decodeUnknownOption(ErrorEnvelope)(input);
1734
+ return failure$1(operation, detail._tag === "Some" ? detail.value.error.message : `Vercel request failed with HTTP ${response.status}`, {
1735
+ ...detail._tag === "Some" ? { code: detail.value.error.code } : {},
1736
+ reason: reason(response.status, detail._tag === "Some" ? detail.value.error.code : void 0),
1737
+ ...rateLimit(response, detail._tag === "Some" ? detail.value.error : void 0),
1738
+ status: response.status
1739
+ });
1740
+ }
1741
+ function reason(status, code) {
1742
+ if (status === 401 || code === "invalid_token") return "authentication";
1743
+ if (status === 403) return "authorization";
1744
+ if (status === 404 || code === "not_found") return "not_found";
1745
+ if (status === 409 || code === "conflict") return "conflict";
1746
+ if (status === 429 || code === "rate_limited") return "rate_limit";
1747
+ if (status >= 500) return "response";
1748
+ return "request";
1749
+ }
1750
+ function rateLimit(response, detail) {
1751
+ const resetMs = detail?.limit?.resetMs;
1752
+ const header = response.headers.get("x-ratelimit-reset");
1753
+ const reset = resetMs ?? (header === null ? void 0 : Number(header) * 1e3);
1754
+ return reset === void 0 || !Number.isFinite(reset) ? {} : { retryAfterMs: Math.max(0, reset - Date.now()) };
1755
+ }
1756
+ function failure$1(operation, message, fields = {}) {
1757
+ return new Error$3({
1758
+ ...fields,
1759
+ message,
1760
+ operation,
1761
+ providerId: "vercel"
1762
+ });
1763
+ }
1764
+ //#endregion
1765
+ //#region src/providers/vercel/auth.ts
1766
+ var auth_exports = /* @__PURE__ */ __exportAll({
1767
+ contextCodec: () => contextCodec,
1768
+ exchangeCode: () => exchangeCode,
1769
+ integrationAuthentication: () => integrationAuthentication,
1770
+ integrationFlow: () => integrationFlow,
1771
+ integrationMethod: () => integrationMethod,
1772
+ manifest: () => manifest,
1773
+ tokenConnectionMethod: () => tokenConnectionMethod,
1774
+ tokenMethod: () => tokenMethod
1775
+ });
1776
+ const contextCodec = codec("vercel.v1", Schema.TaggedUnion({
1777
+ personal: { installationId: Schema.NullOr(Schema.String) },
1778
+ team: {
1779
+ installationId: Schema.NullOr(Schema.String),
1780
+ teamId: Schema.String
1781
+ }
1782
+ }));
1783
+ /** Describes Vercel's caller-created personal access-token method. */
1784
+ function tokenMethod(capabilities) {
1785
+ return {
1786
+ _tag: "token",
1787
+ capabilities: [...capabilities],
1788
+ instructionsUrl: "https://vercel.com/account/settings/tokens"
1789
+ };
1790
+ }
1791
+ /** Describes Vercel's provider-specific integration installation flow. */
1792
+ function integrationMethod(options) {
1793
+ return {
1794
+ _tag: "integration",
1795
+ capabilities: [...options.capabilities],
1796
+ installUrl: `https://vercel.com/integrations/${encodeURIComponent(options.slug)}/new`,
1797
+ tokenEndpoint: "https://api.vercel.com/oauth/access_token"
1798
+ };
1799
+ }
1800
+ /** Creates the Vercel token and integration authorization manifest. */
1801
+ function manifest(options) {
1802
+ return {
1803
+ methods: [tokenMethod(options.capabilities), integrationMethod(options)],
1804
+ providerId: "vercel"
1805
+ };
1806
+ }
1807
+ /** Exchanges Vercel's one-time integration code and preserves its account context. */
1808
+ const exchangeCode = Effect.fn("VercelAuth.exchangeCode")((options) => Effect.gen(function* () {
1809
+ const fetch = options.fetch ?? globalThis.fetch;
1810
+ const baseUrl = (options.baseUrl ?? "https://api.vercel.com").replace(/\/$/, "");
1811
+ const body = new URLSearchParams({
1812
+ client_id: options.clientId,
1813
+ client_secret: options.clientSecret.expose(),
1814
+ code: options.code.expose(),
1815
+ redirect_uri: options.redirectUri
1816
+ });
1817
+ const response = yield* Effect.tryPromise({
1818
+ try: () => fetch(`${baseUrl}/oauth/access_token`, {
1819
+ body,
1820
+ headers: {
1821
+ Accept: "application/json",
1822
+ "Content-Type": "application/x-www-form-urlencoded"
1823
+ },
1824
+ method: "POST"
1825
+ }),
1826
+ catch: () => failure("exchangeCode", "Vercel token exchange failed", "transport")
1827
+ });
1828
+ const input = yield* Effect.tryPromise({
1829
+ try: () => response.json(),
1830
+ catch: () => failure("exchangeCode", response.ok ? "Vercel returned a non-JSON token response" : `Vercel token exchange failed with HTTP ${response.status}`, response.ok ? "response" : response.status === 401 ? "authentication" : "request", response.status)
1831
+ });
1832
+ if (!response.ok) {
1833
+ const detail = Schema.decodeUnknownOption(ErrorEnvelope)(input);
1834
+ return yield* Effect.fail(failure("exchangeCode", detail._tag === "Some" ? detail.value.error.message : `Vercel token exchange failed with HTTP ${response.status}`, response.status === 401 ? "authentication" : "request", response.status, detail._tag === "Some" ? detail.value.error.code : void 0));
1835
+ }
1836
+ const token = yield* Schema.decodeUnknownEffect(IntegrationToken)(input).pipe(Effect.mapError((cause) => failure("exchangeCode", `Vercel token response did not match its API contract: ${cause.message}`, "response", response.status)));
1837
+ return {
1838
+ accessToken: make$6(token.access_token),
1839
+ context: token.team_id === null ? { _tag: "personal" } : {
1840
+ _tag: "team",
1841
+ teamId: token.team_id
1842
+ },
1843
+ installationId: token.installation_id ?? null,
1844
+ userId: token.user_id
1845
+ };
1846
+ }));
1847
+ /** Creates a provider-independent token connection method backed by Vercel validation. */
1848
+ function tokenConnectionMethod(options) {
1849
+ const requiredCapabilities = [...options.capabilities];
1850
+ return Method$1.Token({
1851
+ authenticate: Effect.fn("VercelAuth.authenticateToken")(function* (token) {
1852
+ const validated = yield* make$4({
1853
+ ...options,
1854
+ token
1855
+ }).validateToken();
1856
+ const observedAt = new Date(yield* Clock.currentTimeMillis);
1857
+ return {
1858
+ capabilityEvidence: validated.capabilities.map((capability) => ({
1859
+ capability,
1860
+ evidence: Evidence$1.Introspected({ observedAt })
1861
+ })),
1862
+ credential: {
1863
+ accessToken: token,
1864
+ refreshToken: null,
1865
+ tokenType: "bearer"
1866
+ },
1867
+ expiresAt: validated.expiresAt,
1868
+ providerAccountId: validated.accountId,
1869
+ providerContext: yield* contextCodec.encode(options.context._tag === "team" ? {
1870
+ _tag: "team",
1871
+ installationId: null,
1872
+ teamId: options.context.teamId
1873
+ } : {
1874
+ _tag: "personal",
1875
+ installationId: null
1876
+ }),
1877
+ scopes: [...validated.scopes]
1878
+ };
1879
+ }),
1880
+ providerId: "vercel",
1881
+ requiredCapabilities,
1882
+ token: options.token
1883
+ });
1884
+ }
1885
+ /** Converts a completed Vercel Integration exchange into canonical connection authentication. */
1886
+ const integrationAuthentication = Effect.fn("VercelAuth.integrationAuthentication")(function* (options) {
1887
+ const exchanged = yield* exchangeCode(options);
1888
+ const observedAt = new Date(yield* Clock.currentTimeMillis);
1889
+ return {
1890
+ capabilityEvidence: options.capabilities.map((capability) => ({
1891
+ capability,
1892
+ evidence: Evidence$1.Introspected({ observedAt })
1893
+ })),
1894
+ credential: {
1895
+ accessToken: exchanged.accessToken,
1896
+ refreshToken: null,
1897
+ tokenType: "bearer"
1898
+ },
1899
+ expiresAt: null,
1900
+ providerAccountId: exchanged.context._tag === "team" ? exchanged.context.teamId : exchanged.userId,
1901
+ providerContext: yield* contextCodec.encode(exchanged.context._tag === "team" ? {
1902
+ _tag: "team",
1903
+ installationId: exchanged.installationId,
1904
+ teamId: exchanged.context.teamId
1905
+ } : {
1906
+ _tag: "personal",
1907
+ installationId: exchanged.installationId
1908
+ }),
1909
+ scopes: []
1910
+ };
1911
+ });
1912
+ /** Creates Vercel Integration's implementation of the common interactive connection capability. */
1913
+ function integrationFlow(options) {
1914
+ const method = integrationMethod(options);
1915
+ const Payload = Schema.fromJsonString(Schema.Struct({ state: Schema.String }));
1916
+ return {
1917
+ complete: Effect.fn("VercelAuth.integrationFlow.complete")(function* (payload, callbackUrl) {
1918
+ const continuation = yield* Schema.decodeUnknownEffect(Payload)(payload.expose()).pipe(Effect.mapError(() => new Error$1({
1919
+ category: "authorization",
1920
+ message: "Vercel Integration continuation payload is invalid",
1921
+ operation: "VercelAuth.integrationFlow.complete",
1922
+ retry: "after-user-action"
1923
+ })));
1924
+ const code = callbackUrl.searchParams.get("code");
1925
+ if (callbackUrl.searchParams.get("state") !== continuation.state || code === null) return yield* new Error$1({
1926
+ category: "authorization",
1927
+ message: "Vercel Integration callback does not match its continuation",
1928
+ operation: "VercelAuth.integrationFlow.complete",
1929
+ retry: "after-user-action"
1930
+ });
1931
+ return yield* integrationAuthentication({
1932
+ ...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
1933
+ capabilities: options.capabilities,
1934
+ clientId: options.clientId,
1935
+ clientSecret: options.clientSecret,
1936
+ code: make$6(code),
1937
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch },
1938
+ redirectUri: options.redirectUri
1939
+ });
1940
+ }),
1941
+ method: "integration",
1942
+ providerId: "vercel",
1943
+ requiredCapabilities: [...options.capabilities],
1944
+ start: (continuationId) => {
1945
+ const authorizationUrl = new URL(method.installUrl);
1946
+ authorizationUrl.searchParams.set("source", "external");
1947
+ authorizationUrl.searchParams.set("state", continuationId);
1948
+ return Effect.succeed({
1949
+ authorizationUrl,
1950
+ payload: make$6(JSON.stringify({ state: continuationId }))
1951
+ });
1952
+ }
1953
+ };
1954
+ }
1955
+ function failure(operation, message, reason, status, code) {
1956
+ return new Error$3({
1957
+ ...code === void 0 ? {} : { code },
1958
+ message,
1959
+ operation,
1960
+ providerId: "vercel",
1961
+ reason,
1962
+ ...status === void 0 ? {} : { status }
1963
+ });
1964
+ }
1965
+ //#endregion
1966
+ //#region src/verification/dns-data.ts
1967
+ var dns_data_exports = /* @__PURE__ */ __exportAll({ parse: () => parse });
1968
+ const CanonicalAddress = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
1969
+ decode: (value) => value.trim().toLowerCase(),
1970
+ encode: (value) => value
1971
+ })));
1972
+ const CanonicalDomain = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transformOrFail({
1973
+ decode: (value, options) => Effect.try({
1974
+ try: () => parse$1(value).toString(),
1975
+ catch: (cause) => new SchemaIssue.InvalidValue({ message: cause instanceof Error ? cause.message : String(cause) }, value, options)
1976
+ }),
1977
+ encode: (value) => Effect.succeed(value)
1978
+ })));
1979
+ const CanonicalMx = tokenizedDomain(2, 1);
1980
+ const CanonicalSrv = tokenizedDomain(4, 3);
1981
+ const CanonicalTxt = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
1982
+ decode: (value) => {
1983
+ const trimmed = value.trim();
1984
+ const chunks = [...trimmed.matchAll(/"((?:\\.|[^"])*)"/g)];
1985
+ return chunks.length === 0 ? trimmed : chunks.map((match) => (match[1] ?? "").replace(/\\"/g, "\"").replace(/\\\\/g, "\\")).join("");
1986
+ },
1987
+ encode: (value) => value
1988
+ })));
1989
+ const CanonicalCaa = Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transform({
1990
+ decode: (value) => value.trim().replace(/\s+"([\s\S]*)"$/, " $1"),
1991
+ encode: (value) => value
1992
+ })));
1993
+ function parse(type, input) {
1994
+ const schema = (() => {
1995
+ switch (type) {
1996
+ case "A":
1997
+ case "AAAA": return CanonicalAddress;
1998
+ case "CNAME":
1999
+ case "NS": return CanonicalDomain;
2000
+ case "MX": return CanonicalMx;
2001
+ case "SRV": return CanonicalSrv;
2002
+ case "TXT": return CanonicalTxt;
2003
+ case "CAA": return CanonicalCaa;
2004
+ }
2005
+ })();
2006
+ try {
2007
+ return Schema.decodeUnknownSync(schema)(input);
2008
+ } catch (cause) {
2009
+ throw new Error$2({ message: cause instanceof Error ? cause.message : String(cause) });
2010
+ }
2011
+ }
2012
+ function tokenizedDomain(length, domainIndex) {
2013
+ return Schema.String.pipe(Schema.decodeTo(Schema.String, SchemaTransformation.transformOrFail({
2014
+ decode: (value, options) => Effect.try({
2015
+ try: () => {
2016
+ const parts = value.trim().split(/\s+/);
2017
+ if (parts.length !== length) throw new Error("DNS record data has an invalid field count");
2018
+ const domain = parts[domainIndex];
2019
+ if (domain === void 0) throw new Error("DNS record target is missing");
2020
+ parts[domainIndex] = parse$1(domain);
2021
+ return parts.join(" ");
2022
+ },
2023
+ catch: (cause) => new SchemaIssue.InvalidValue({ message: cause instanceof Error ? cause.message : String(cause) }, value, options)
2024
+ }),
2025
+ encode: (value) => Effect.succeed(value)
2026
+ })));
2027
+ }
2028
+ //#endregion
2029
+ //#region src/verification/doh.ts
2030
+ var doh_exports = /* @__PURE__ */ __exportAll({
2031
+ layer: () => layer$2,
2032
+ make: () => make$3,
2033
+ toAsync: () => toAsync$2
2034
+ });
2035
+ function make$3(options) {
2036
+ const fetch = options.fetch ?? globalThis.fetch;
2037
+ const timeoutMs = options.timeoutMs ?? 5e3;
2038
+ return { resolve: Effect.fn("DnsOverHttps.resolve")((query) => Effect.tryPromise({
2039
+ try: (effectSignal) => request({
2040
+ effectSignal,
2041
+ fetch,
2042
+ query,
2043
+ timeoutMs,
2044
+ endpoint: options.endpoint
2045
+ }),
2046
+ catch: (cause) => cause instanceof Error$4 ? cause : new Error$4({
2047
+ cause,
2048
+ message: cause instanceof Error ? cause.message : "DNS resolution failed",
2049
+ reason: "transport"
2050
+ })
2051
+ }).pipe(Effect.flatMap((message) => decodeResolution(query, message)))) };
2052
+ }
2053
+ const layer$2 = (options) => Layer.succeed(Service$2, make$3(options));
2054
+ const toAsync$2 = (options) => toAsync$3(make$3(options));
2055
+ function decodeResolution(query, message) {
2056
+ return Effect.try({
2057
+ try: () => DnsPacket.decode(message),
2058
+ catch: (cause) => new Error$4({
2059
+ cause,
2060
+ message: "DoH returned an invalid DNS message",
2061
+ reason: "response"
2062
+ })
2063
+ }).pipe(Effect.flatMap((packet) => validatePacket(query, packet)), Effect.flatMap(decodePacket));
2064
+ }
2065
+ function decodePacket(packet) {
2066
+ if (packet.rcode === "NXDOMAIN") return Effect.succeed({ _tag: "nodata" });
2067
+ if (packet.rcode !== "NOERROR") return Effect.fail(new Error$4({
2068
+ message: `DNS resolver returned ${packet.rcode ?? "an unknown response code"}`,
2069
+ reason: "response"
2070
+ }));
2071
+ if (packet.answers === void 0 || packet.answers.length === 0) return Effect.succeed({ _tag: "nodata" });
2072
+ return Effect.forEach(packet.answers, decodeAnswer, { concurrency: "unbounded" }).pipe(Effect.map((answers) => {
2073
+ const supportedAnswers = answers.filter((answer) => answer !== null);
2074
+ return supportedAnswers.length === 0 ? { _tag: "nodata" } : {
2075
+ _tag: "answer",
2076
+ answers: supportedAnswers
2077
+ };
2078
+ }));
2079
+ }
2080
+ function validatePacket(query, packet) {
2081
+ return Effect.try({
2082
+ try: () => {
2083
+ if (packet.type !== "response") throw new Error("DoH returned a DNS query");
2084
+ if (packet.id !== 0) throw new Error("DoH response used an unexpected message ID");
2085
+ if (packet.flag_tc) throw new Error("DoH returned a truncated DNS response");
2086
+ const questions = packet.questions ?? [];
2087
+ if (questions.length !== 1) throw new Error("DoH returned an unexpected question count");
2088
+ const question = questions[0];
2089
+ if (question === void 0) throw new Error("DoH response omitted the DNS question");
2090
+ if (question.class !== "IN" || question.type !== query.type || parse$1(question.name) !== query.name) throw new Error("DoH response did not match the DNS question");
2091
+ return packet;
2092
+ },
2093
+ catch: (cause) => new Error$4({
2094
+ cause,
2095
+ message: cause instanceof Error ? cause.message : "DoH returned an invalid DNS response",
2096
+ reason: "response"
2097
+ })
2098
+ });
2099
+ }
2100
+ function decodeAnswer(answer) {
2101
+ return Effect.gen(function* () {
2102
+ if (answer.class !== "IN") return null;
2103
+ const decoded = yield* Effect.try({
2104
+ try: () => answerData(answer),
2105
+ catch: (cause) => new Error$4({
2106
+ cause,
2107
+ message: "DoH returned invalid DNS record data",
2108
+ reason: "response"
2109
+ })
2110
+ });
2111
+ if (decoded === void 0) return null;
2112
+ const name = yield* decode$8(answer.name);
2113
+ const data = yield* Effect.try({
2114
+ try: () => parse(decoded.type, decoded.data),
2115
+ catch: (cause) => new Error$4({
2116
+ cause,
2117
+ message: "DoH returned invalid DNS record data",
2118
+ reason: "response"
2119
+ })
2120
+ });
2121
+ if (answer.ttl === void 0) return yield* new Error$4({
2122
+ message: "DoH response omitted the DNS record TTL",
2123
+ reason: "response"
2124
+ });
2125
+ return {
2126
+ data,
2127
+ name,
2128
+ ttl: answer.ttl,
2129
+ type: decoded.type
2130
+ };
2131
+ }).pipe(Effect.mapError((cause) => cause instanceof Error$4 ? cause : new Error$4({
2132
+ cause,
2133
+ message: cause.message,
2134
+ reason: "response"
2135
+ })));
2136
+ }
2137
+ function answerData(answer) {
2138
+ switch (answer.type) {
2139
+ case "A":
2140
+ case "AAAA":
2141
+ case "CNAME":
2142
+ case "NS": return {
2143
+ data: answer.data,
2144
+ type: answer.type
2145
+ };
2146
+ case "CAA": return {
2147
+ data: `${answer.data.flags ?? 0} ${answer.data.tag} ${answer.data.value}`,
2148
+ type: answer.type
2149
+ };
2150
+ case "MX": return {
2151
+ data: `${requiredNumber(answer.data.preference, "MX preference")} ${answer.data.exchange}`,
2152
+ type: answer.type
2153
+ };
2154
+ case "SRV": return {
2155
+ data: [
2156
+ requiredNumber(answer.data.priority, "SRV priority"),
2157
+ requiredNumber(answer.data.weight, "SRV weight"),
2158
+ requiredNumber(answer.data.port, "SRV port"),
2159
+ answer.data.target
2160
+ ].join(" "),
2161
+ type: answer.type
2162
+ };
2163
+ case "TXT": return {
2164
+ data: decodeTxt(answer.data),
2165
+ type: answer.type
2166
+ };
2167
+ default: return;
2168
+ }
2169
+ }
2170
+ function decodeTxt(data) {
2171
+ const encoded = (Array.isArray(data) ? data : [data]).map((chunk) => typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
2172
+ const length = encoded.reduce((total, chunk) => total + chunk.length, 0);
2173
+ const joined = new Uint8Array(length);
2174
+ let offset = 0;
2175
+ for (const chunk of encoded) {
2176
+ joined.set(chunk, offset);
2177
+ offset += chunk.length;
2178
+ }
2179
+ return new TextDecoder("utf-8", { fatal: true }).decode(joined);
2180
+ }
2181
+ function requiredNumber(value, field) {
2182
+ if (value === void 0) throw new Error(`DoH response omitted ${field}`);
2183
+ return value;
2184
+ }
2185
+ async function request(input) {
2186
+ const controller = new AbortController();
2187
+ let timedOut = false;
2188
+ const abortFromEffect = () => controller.abort(input.effectSignal.reason);
2189
+ const abortFromHost = () => controller.abort(input.query.signal?.reason);
2190
+ input.effectSignal.addEventListener("abort", abortFromEffect, { once: true });
2191
+ input.query.signal?.addEventListener("abort", abortFromHost, { once: true });
2192
+ const timer = setTimeout(() => {
2193
+ timedOut = true;
2194
+ controller.abort(/* @__PURE__ */ new Error("DNS resolution timed out"));
2195
+ }, input.timeoutMs);
2196
+ try {
2197
+ const query = Uint8Array.from(DnsPacket.encode({
2198
+ flags: DnsPacket.RECURSION_DESIRED,
2199
+ id: 0,
2200
+ questions: [{
2201
+ name: input.query.name,
2202
+ type: input.query.type
2203
+ }],
2204
+ type: "query"
2205
+ }));
2206
+ const response = await input.fetch(new URL(input.endpoint), {
2207
+ body: query,
2208
+ headers: {
2209
+ accept: "application/dns-message",
2210
+ "content-type": "application/dns-message"
2211
+ },
2212
+ method: "POST",
2213
+ signal: controller.signal
2214
+ });
2215
+ if (!response.ok) throw new Error$4({
2216
+ message: `DoH returned HTTP ${response.status}`,
2217
+ reason: "transport"
2218
+ });
2219
+ const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
2220
+ if (contentType !== "application/dns-message") throw new Error$4({
2221
+ message: `DoH returned unsupported content type ${contentType ?? "<missing>"}`,
2222
+ reason: "response"
2223
+ });
2224
+ return new Uint8Array(await response.arrayBuffer());
2225
+ } catch (cause) {
2226
+ if (timedOut) throw new Error$4({
2227
+ message: "DNS query timed out",
2228
+ reason: "timeout"
2229
+ });
2230
+ throw cause;
2231
+ } finally {
2232
+ clearTimeout(timer);
2233
+ input.effectSignal.removeEventListener("abort", abortFromEffect);
2234
+ input.query.signal?.removeEventListener("abort", abortFromHost);
2235
+ }
2236
+ }
2237
+ //#endregion
2238
+ //#region src/verification/cloudflare-doh.ts
2239
+ var cloudflare_doh_exports = /* @__PURE__ */ __exportAll({
2240
+ layer: () => layer$1,
2241
+ make: () => make$2,
2242
+ toAsync: () => toAsync$1
2243
+ });
2244
+ const endpoint$1 = "https://cloudflare-dns.com/dns-query";
2245
+ function make$2(options = {}) {
2246
+ return make$3({
2247
+ ...options,
2248
+ endpoint: options.endpoint ?? endpoint$1
2249
+ });
2250
+ }
2251
+ const layer$1 = (options = {}) => Layer.succeed(Service$2, make$2(options));
2252
+ const toAsync$1 = (options = {}) => toAsync$3(make$2(options));
2253
+ //#endregion
2254
+ //#region src/verification/google-doh.ts
2255
+ var google_doh_exports = /* @__PURE__ */ __exportAll({
2256
+ layer: () => layer,
2257
+ make: () => make$1,
2258
+ toAsync: () => toAsync
2259
+ });
2260
+ const endpoint = "https://dns.google/dns-query";
2261
+ function make$1(options = {}) {
2262
+ return make$3({
2263
+ ...options,
2264
+ endpoint: options.endpoint ?? endpoint
2265
+ });
2266
+ }
2267
+ const layer = (options = {}) => Layer.succeed(Service$2, make$1(options));
2268
+ const toAsync = (options = {}) => toAsync$3(make$1(options));
2269
+ //#endregion
2270
+ //#region src/verification/resolver-pool.ts
2271
+ var resolver_pool_exports = /* @__PURE__ */ __exportAll({
2272
+ Observation: () => Observation,
2273
+ Policy: () => Policy,
2274
+ Service: () => Service,
2275
+ defaultLayer: () => defaultLayer,
2276
+ defaultMake: () => defaultMake,
2277
+ make: () => make
2278
+ });
2279
+ const Observation = Data.taggedEnum();
2280
+ const PolicyVariants = Data.taggedEnum();
2281
+ const QuorumMinimum = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
2282
+ const PolicySchema = Schema.TaggedUnion({
2283
+ AllMatch: {},
2284
+ AnyMatch: {},
2285
+ Quorum: { minimum: QuorumMinimum }
2286
+ });
2287
+ const Policy = {
2288
+ AllMatch: PolicyVariants.AllMatch,
2289
+ AnyMatch: PolicyVariants.AnyMatch,
2290
+ Quorum: ({ minimum }) => PolicyVariants.Quorum({ minimum: Schema.decodeUnknownSync(QuorumMinimum)(minimum) }),
2291
+ Schema: PolicySchema
2292
+ };
2293
+ var Service = class extends Context.Service()("@domainkit/DnsResolverPool") {};
2294
+ function make(entries) {
2295
+ return Service.of({ observe: Effect.fn("DnsResolverPool.observe")((query) => Effect.forEach(entries, (entry) => observe$1(entry, query), { concurrency: "unbounded" })) });
2296
+ }
2297
+ /** Cloudflare and Google RFC wire-format DoH resolvers. */
2298
+ function defaultMake(options = {}) {
2299
+ const timeoutMs = options.timeoutMs ?? 5e3;
2300
+ return make([{
2301
+ id: "cloudflare",
2302
+ resolver: make$2(options),
2303
+ timeoutMs
2304
+ }, {
2305
+ id: "google",
2306
+ resolver: make$1(options),
2307
+ timeoutMs
2308
+ }]);
2309
+ }
2310
+ const defaultLayer = (options = {}) => Layer.succeed(Service, defaultMake(options));
2311
+ function observe$1(entry, query) {
2312
+ const timeoutMs = entry.timeoutMs ?? 5e3;
2313
+ return entry.resolver.resolve(query).pipe(Effect.timeout(timeoutMs), Effect.match({
2314
+ onFailure: (failure) => {
2315
+ if (failure._tag === "TimeoutError" || failure._tag === "ResolverError" && failure.reason === "timeout") return Observation.TimedOut({
2316
+ resolverId: entry.id,
2317
+ timeoutMs
2318
+ });
2319
+ return Observation.Failed({
2320
+ message: failure.message,
2321
+ reason: failure.reason === "response" ? "response" : "transport",
2322
+ resolverId: entry.id
2323
+ });
2324
+ },
2325
+ onSuccess: (resolution) => resolution._tag === "nodata" ? Observation.NoData({ resolverId: entry.id }) : Observation.Answer({
2326
+ answers: resolution.answers,
2327
+ resolverId: entry.id
2328
+ })
2329
+ }));
2330
+ }
2331
+ //#endregion
2332
+ //#region src/verification/verify.ts
2333
+ var verify_exports = /* @__PURE__ */ __exportAll({
2334
+ Provider: () => Provider,
2335
+ ProviderObservation: () => ProviderObservation,
2336
+ PublicDns: () => PublicDns,
2337
+ PublicDnsObservation: () => PublicDnsObservation,
2338
+ Result: () => Result,
2339
+ observe: () => observe
2340
+ });
2341
+ const PublicDns = Data.taggedEnum();
2342
+ const Provider = Data.taggedEnum();
2343
+ const ProviderObservation = Data.taggedEnum();
2344
+ const PublicDnsObservation = Data.taggedEnum();
2345
+ const Result = Data.taggedEnum();
2346
+ function observe(input) {
2347
+ return observeEffect(input);
2348
+ }
2349
+ const observeEffect = Effect.fn("Verification.observe")(function* (input) {
2350
+ const publicDns = input.publicDns ?? PublicDns.Enabled({});
2351
+ const provider = input.provider ?? Provider.Disabled();
2352
+ const publicEffect = publicDns._tag === "Disabled" ? Effect.succeed(null) : observePublicDns(input.record, publicDns.policy ?? Policy.AnyMatch());
2353
+ const providerEffect = provider._tag === "Disabled" ? Effect.succeed(null) : Effect.flatMap(Service$3, (service) => observeProvider(service, provider.zone, input.record).pipe(Effect.catch((failure) => Effect.succeed(ProviderObservation.Unavailable({ message: failure.message })))));
2354
+ const [providerObservation, publicDnsObservation] = yield* Effect.all([providerEffect, publicEffect], { concurrency: "unbounded" });
2355
+ return aggregate({
2356
+ provider: providerObservation,
2357
+ publicDns: publicDnsObservation
2358
+ });
2359
+ });
2360
+ function observeProvider(provider, zone, requirement) {
2361
+ return provider.listRecords(zone).pipe(Effect.map((records) => {
2362
+ if (records.some((existing) => existing._tag !== "Opaque" && equals(existing, requirement))) return ProviderObservation.Matched();
2363
+ const sameSet = records.filter((existing) => existing._tag !== "Opaque" && existing.name === requirement.name && existing._tag === requirement._tag);
2364
+ return sameSet.length === 0 ? ProviderObservation.Pending() : ProviderObservation.Mismatch({ records: sameSet });
2365
+ }));
2366
+ }
2367
+ function observePublicDns(requirement, policy) {
2368
+ return Effect.gen(function* () {
2369
+ const validatedPolicy = yield* Schema.decodeUnknownEffect(Policy.Schema)(policy).pipe(Effect.mapError((cause) => new Error$2({ message: cause.message })));
2370
+ const configuredPool = yield* Effect.serviceOption(Service);
2371
+ const evidence = yield* Option.getOrElse(configuredPool, () => defaultMake()).observe({
2372
+ name: requirement.name,
2373
+ type: requirement._tag
2374
+ });
2375
+ if (validatedPolicy._tag === "Quorum" && validatedPolicy.minimum > evidence.length) return yield* new Error$2({ message: `Quorum minimum ${validatedPolicy.minimum} exceeds the ${evidence.length} configured resolvers` });
2376
+ return evaluatePublicDns(requirement, validatedPolicy, evidence);
2377
+ });
2378
+ }
2379
+ function evaluatePublicDns(requirement, policy, evidence) {
2380
+ const matchedResolverIds = evidence.flatMap((observation) => observation._tag === "Answer" && answersMatch(requirement, observation.answers) ? [observation.resolverId] : []);
2381
+ const required = policy._tag === "AnyMatch" ? 1 : policy._tag === "AllMatch" ? evidence.length : policy.minimum;
2382
+ if (required > 0 && matchedResolverIds.length >= required) return PublicDnsObservation.Verified({
2383
+ evidence,
2384
+ matchedResolverIds
2385
+ });
2386
+ const unavailable = evidence.filter((observation) => observation._tag === "TimedOut" || observation._tag === "Failed").length;
2387
+ if (unavailable > 0 && matchedResolverIds.length + unavailable >= required) return PublicDnsObservation.Unavailable({ evidence });
2388
+ if (evidence.some((observation) => observation._tag === "Answer" && !answersMatch(requirement, observation.answers))) return PublicDnsObservation.Mismatch({ evidence });
2389
+ if (evidence.some((observation) => observation._tag === "NoData")) return PublicDnsObservation.Pending({ evidence });
2390
+ return PublicDnsObservation.Unavailable({ evidence });
2391
+ }
2392
+ function answersMatch(requirement, answers) {
2393
+ const expected = parse(requirement._tag, recordValue(requirement));
2394
+ return answers.some((answer) => answer.name === requirement.name && answer.type === requirement._tag && parse(requirement._tag, answer.data) === expected);
2395
+ }
2396
+ function aggregate(evidence) {
2397
+ const requested = [evidence.provider, evidence.publicDns].filter((observation) => observation !== null);
2398
+ if (requested.length === 0) return Result.NotObserved(evidence);
2399
+ if (requested.every((observation) => observation._tag === "Matched" || observation._tag === "Verified")) return Result.Verified(evidence);
2400
+ if (requested.some((observation) => observation._tag === "Unavailable")) return Result.Unavailable(evidence);
2401
+ if (requested.some((observation) => observation._tag === "Mismatch")) return Result.Mismatch(evidence);
2402
+ return Result.Pending(evidence);
2403
+ }
2404
+ function recordValue(requirement) {
2405
+ const data$1 = data(requirement);
2406
+ switch (requirement._tag) {
2407
+ case "A":
2408
+ case "AAAA": return String(data$1.address);
2409
+ case "CNAME":
2410
+ case "NS": return String(data$1.target);
2411
+ case "TXT": return String(data$1.value);
2412
+ case "MX": return `${data$1.priority} ${data$1.exchange}`;
2413
+ case "CAA": return `${data$1.flags} ${data$1.tag} ${data$1.value}`;
2414
+ case "SRV": return `${data$1.priority} ${data$1.weight} ${data$1.port} ${data$1.target}`;
2415
+ }
2416
+ }
2417
+ //#endregion
2418
+ export { RemoveDomainResult as $, make$4 as A, discovery$1 as B, integrationFlow as C, encode$3 as Ct, tokenMethod as D, tokenConnectionMethod as E, subjectResolver as F, secret_exports as G, authorize as H, tokenConnectionMethod$1 as I, decode$4 as J, Method as K, tokenMethod$1 as L, manifest$1 as M, oauthFlow as N, client_exports as O, oauthMethod as P, Method$1 as Q, tokenValidator as R, exchangeCode as S, decode$6 as St, manifest as T, version as Tt, connection_authorization_exports as U, make$5 as V, selection_exports as W, diagnostic_exports as X, manifest_exports as Y, Error$1 as Z, toAsync$1 as _, CapabilityEvidence as _t, Result as a, AuthorizationError as at, dns_data_exports as b, Schema$3 as bt, Observation as c, assertGrant as ct, defaultMake as d, decode$5 as dt, StartResult as et, make as f, encode$2 as ft, cloudflare_doh_exports as g, Capability as gt, toAsync as h, validate as ht, PublicDnsObservation as i, start$1 as it, auth_exports$1 as j, discovery as k, Policy as l, authorizationError as lt, google_doh_exports as m, removeDomain$1 as mt, ProviderObservation as n, extend as nt, observe as o, Grant as ot, resolver_pool_exports as p, includeDomains as pt, Schema$1 as q, PublicDns as r, removeDomain as rt, verify_exports as s, Schema$2 as st, Provider as t, complete$1 as tt, Service as u, coversDomain as ut, doh_exports as v, Evidence$1 as vt, integrationMethod as w, provider_context_exports as wt, auth_exports as x, authorization_exports as xt, toAsync$2 as y, EvidenceSchema as yt, client_exports$1 as z };
2419
+
2420
+ //# sourceMappingURL=verify-B00c81-n.mjs.map