@homeflare/alchemy 0.3.2 → 0.4.1

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.
@@ -1,8 +1,8 @@
1
- // src/openbao/auth-role.ts
1
+ // src/openbao/auth-method.ts
2
2
  import { Resource } from "alchemy";
3
3
  import { isResolved } from "alchemy/Diff";
4
4
  import * as Provider from "alchemy/Provider";
5
- import * as Effect2 from "effect/Effect";
5
+ import * as Effect3 from "effect/Effect";
6
6
 
7
7
  // src/openbao/digest.ts
8
8
  var canonical = (text) => text.trimEnd();
@@ -88,16 +88,11 @@ var sameTtl = (want, have) => {
88
88
  var matches = (attributes, props) => attributes.type === props.type && (props.description === undefined || attributes.description === props.description) && sameTtl(props.defaultLeaseTtl, attributes.defaultLeaseTtl) && sameTtl(props.maxLeaseTtl, attributes.maxLeaseTtl);
89
89
  var wantsTune = (props) => props.description !== undefined || props.defaultLeaseTtl !== undefined || props.maxLeaseTtl !== undefined;
90
90
 
91
- // src/openbao/auth-role-form.ts
92
- var policiesOf = (live) => {
93
- const raw = live["token_policies"];
94
- if (!Array.isArray(raw))
95
- return [];
96
- return raw.filter((entry) => typeof entry === "string").slice().sort();
97
- };
98
- var bool = (value, fallback) => typeof value === "boolean" ? value : fallback;
99
- var int = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
100
- var ttlText = (seconds, fallback = "") => {
91
+ // src/openbao/auth-method-form.ts
92
+ var authPath = (path) => mountPath(path);
93
+ var configOf2 = (live) => typeof live["config"] === "object" && live["config"] !== null ? live["config"] : {};
94
+ var text2 = (value) => typeof value === "string" ? value : "";
95
+ var ttlProp2 = (seconds, fallback = "") => {
101
96
  if (seconds === undefined)
102
97
  return fallback;
103
98
  if (seconds % 86400 === 0)
@@ -109,42 +104,46 @@ var ttlText = (seconds, fallback = "") => {
109
104
  return `${String(seconds)}s`;
110
105
  };
111
106
  var attributesOf2 = (props, live) => {
107
+ const config = configOf2(live);
112
108
  const attrs = {
113
- name: props.name,
114
- tokenPolicies: policiesOf(live),
115
- tokenTtl: ttlText(ttlSeconds(live["token_ttl"])),
116
- tokenMaxTtl: ttlText(ttlSeconds(live["token_max_ttl"])),
117
- secretIdTtl: ttlText(ttlSeconds(live["secret_id_ttl"]), "0"),
118
- bindSecretId: bool(live["bind_secret_id"], true),
119
- secretIdNumUses: int(live["secret_id_num_uses"], 0)
109
+ path: authPath(props.path),
110
+ type: text2(live["type"]) || props.type,
111
+ description: text2(live["description"]),
112
+ defaultLeaseTtl: ttlProp2(ttlSeconds(config["default_lease_ttl"])),
113
+ maxLeaseTtl: ttlProp2(ttlSeconds(config["max_lease_ttl"]))
120
114
  };
121
115
  return { ...attrs, digest: sha256(JSON.stringify(attrs)) };
122
116
  };
123
- var readPath2 = (name) => `auth/approle/role/${name}`;
124
- var writeBody = (props) => {
125
- const body = {
126
- token_policies: props.tokenPolicies.join(","),
127
- token_ttl: props.tokenTtl,
128
- token_max_ttl: props.tokenMaxTtl,
129
- secret_id_ttl: props.secretIdTtl
130
- };
131
- if (props.bindSecretId !== undefined)
132
- body["bind_secret_id"] = String(props.bindSecretId);
133
- if (props.secretIdNumUses !== undefined) {
134
- body["secret_id_num_uses"] = String(props.secretIdNumUses);
135
- }
117
+ var readPath2 = (path) => `sys/auth/${authPath(path)}`;
118
+ var tunePath2 = (path) => `${readPath2(path)}/tune`;
119
+ var enableBody2 = (props) => {
120
+ const body = { type: props.type };
121
+ if (props.description !== undefined)
122
+ body["description"] = props.description;
123
+ return body;
124
+ };
125
+ var tuneBody2 = (props) => {
126
+ const body = {};
127
+ if (props.description !== undefined)
128
+ body["description"] = props.description;
129
+ if (props.defaultLeaseTtl !== undefined)
130
+ body["default_lease_ttl"] = props.defaultLeaseTtl;
131
+ if (props.maxLeaseTtl !== undefined)
132
+ body["max_lease_ttl"] = props.maxLeaseTtl;
136
133
  return body;
137
134
  };
138
- var samePolicies = (want, have) => want.length === have.length && want.every((policy, index) => policy === have[index]);
139
135
  var sameTtl2 = (want, have) => {
140
- const wantSeconds = parseDuration(want);
136
+ if (want === undefined)
137
+ return true;
138
+ const wantSeconds = ttlSeconds(want);
141
139
  const haveSeconds = ttlSeconds(have);
142
140
  return wantSeconds !== undefined && wantSeconds === haveSeconds;
143
141
  };
144
- var matches2 = (attributes, props) => {
145
- const wantPolicies = props.tokenPolicies.slice().sort();
146
- return samePolicies(wantPolicies, attributes.tokenPolicies) && sameTtl2(props.tokenTtl, attributes.tokenTtl) && sameTtl2(props.tokenMaxTtl, attributes.tokenMaxTtl) && sameTtl2(props.secretIdTtl, attributes.secretIdTtl) && (props.bindSecretId === undefined || attributes.bindSecretId === props.bindSecretId) && (props.secretIdNumUses === undefined || attributes.secretIdNumUses === props.secretIdNumUses);
147
- };
142
+ var matches2 = (attributes, props) => attributes.type === props.type && (props.description === undefined || attributes.description === props.description) && sameTtl2(props.defaultLeaseTtl, attributes.defaultLeaseTtl) && sameTtl2(props.maxLeaseTtl, attributes.maxLeaseTtl);
143
+ var wantsTune2 = (props) => props.description !== undefined || props.defaultLeaseTtl !== undefined || props.maxLeaseTtl !== undefined;
144
+
145
+ // src/openbao/auth-method-wire.ts
146
+ import * as Effect2 from "effect/Effect";
148
147
 
149
148
  // src/openbao/bao-http.ts
150
149
  import * as Context from "effect/Context";
@@ -199,35 +198,35 @@ class BaoError extends Error {
199
198
  this.name = "BaoError";
200
199
  }
201
200
  }
202
- var objectOf = (text2) => {
201
+ var objectOf = (text3) => {
203
202
  try {
204
- const parsed = JSON.parse(text2);
203
+ const parsed = JSON.parse(text3);
205
204
  return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
206
205
  } catch {
207
206
  return;
208
207
  }
209
208
  };
210
- var errorsOf = (text2) => {
211
- const raw = objectOf(text2)?.["errors"];
209
+ var errorsOf = (text3) => {
210
+ const raw = objectOf(text3)?.["errors"];
212
211
  return Array.isArray(raw) && raw.every((entry) => typeof entry === "string") ? raw : undefined;
213
212
  };
214
- var settle = (intent, method, path, status, text2) => {
213
+ var settle = (intent, method, path, status, text3) => {
215
214
  const fail = (errors) => ({
216
215
  error: new BaoError(status, method, path, errors)
217
216
  });
218
217
  if (status < 200 || status >= 300) {
219
- const errors = errorsOf(text2);
218
+ const errors = errorsOf(text3);
220
219
  if (errors === undefined) {
221
- return fail([`not an OpenBao error body (${String(text2.length)} bytes)`]);
220
+ return fail([`not an OpenBao error body (${String(text3.length)} bytes)`]);
222
221
  }
223
222
  if (status === 404 && intent !== "write")
224
223
  return { body: undefined };
225
224
  return fail(errors);
226
225
  }
227
- if (text2.trim() === "") {
226
+ if (text3.trim() === "") {
228
227
  return intent === "read" ? fail(["a successful read with an empty body"]) : { body: undefined };
229
228
  }
230
- const body = objectOf(text2);
229
+ const body = objectOf(text3);
231
230
  return body === undefined ? fail(["a success body that is not a JSON object"]) : { body };
232
231
  };
233
232
 
@@ -268,10 +267,10 @@ var baoCall = (intent, method, path, body) => Effect.gen(function* () {
268
267
  const address = resolveAddress(env);
269
268
  const client = yield* HttpClient.HttpClient;
270
269
  const request = HttpClientRequest.make(method)(`${address.base}/v1/${path}`).pipe(HttpClientRequest.setHeaders(headersFor(address, env)), body === undefined ? (self) => self : HttpClientRequest.bodyText(JSON.stringify(body), "application/json"));
271
- const exchange = client.execute(request).pipe(Effect.flatMap((response) => Effect.map(response.text, (text3) => ({ status: response.status, text: text3 }))), Effect.timeout(TIMEOUT), Effect.mapError((cause) => new BaoError(0, method, path, [cause.message])));
270
+ const exchange = client.execute(request).pipe(Effect.flatMap((response) => Effect.map(response.text, (text4) => ({ status: response.status, text: text4 }))), Effect.timeout(TIMEOUT), Effect.mapError((cause) => new BaoError(0, method, path, [cause.message])));
272
271
  const gate = yield* BaoGate;
273
- const { status, text: text2 } = yield* retryTransport(exchange.pipe(overSocket(address.socket, method, path), redactingToken, Semaphore.withPermits(gate, 1)));
274
- const outcome = settle(intent, method, path, status, text2);
272
+ const { status, text: text3 } = yield* retryTransport(exchange.pipe(overSocket(address.socket, method, path), redactingToken, Semaphore.withPermits(gate, 1)));
273
+ const outcome = settle(intent, method, path, status, text3);
275
274
  return "error" in outcome ? yield* Effect.fail(outcome.error) : outcome.body;
276
275
  });
277
276
  var baoRead = (path) => Effect.map(baoCall("read", "GET", path), (body) => {
@@ -283,52 +282,176 @@ var baoRead = (path) => Effect.map(baoCall("read", "GET", path), (body) => {
283
282
  var baoWrite = (method, path, body) => Effect.asVoid(baoCall("write", method, path, body));
284
283
  var baoDelete = (path) => Effect.asVoid(baoCall("delete", "DELETE", path));
285
284
 
286
- // src/openbao/auth-role.ts
287
- var BaoAuthRole = Resource("Bao.AuthRole", {
285
+ // src/openbao/auth-method-wire.ts
286
+ var absentFromTable = (path, asked) => baoRead("sys/auth").pipe(Effect2.mapError((listing) => new BaoError(asked.status, asked.method, asked.path, [
287
+ ...asked.errors,
288
+ `sys/auth could not confirm the method is absent: ${listing.message}`
289
+ ])), Effect2.flatMap((table) => table !== undefined && !Object.hasOwn(table, `${authPath(path)}/`) ? Effect2.succeed(undefined) : Effect2.fail(asked)));
290
+ var readAuthMethodData = (path) => baoRead(readPath2(path)).pipe(Effect2.catchIf((error) => error.status === 400, (error) => absentFromTable(path, error)));
291
+ var enableAuthMethod = (props) => baoWrite("POST", readPath2(props.path), enableBody2(props));
292
+ var tuneAuthMethod = (props) => baoWrite("POST", tunePath2(props.path), tuneBody2(props));
293
+ var disableAuthMethod = (path) => baoDelete(readPath2(path));
294
+
295
+ // src/openbao/auth-method.ts
296
+ var BaoAuthMethod = Resource("Bao.AuthMethod", {
288
297
  defaultRemovalPolicy: "retain"
289
298
  });
290
- var readRole = (props) => Effect2.gen(function* () {
291
- const live = yield* baoRead(readPath2(props.name));
299
+ var readMethod = (props) => Effect3.gen(function* () {
300
+ const live = yield* readAuthMethodData(props.path);
292
301
  if (live === undefined)
293
302
  return;
294
303
  return attributesOf2(props, live);
295
304
  });
296
- var BaoAuthRoleProvider = () => Provider.effect(BaoAuthRole, Effect2.succeed(BaoAuthRole.Provider.of({
297
- list: () => Effect2.succeed([]),
298
- read: Effect2.fn(function* ({ olds }) {
299
- return yield* readRole(olds);
305
+ var BaoAuthMethodProvider = () => Provider.effect(BaoAuthMethod, Effect3.succeed(BaoAuthMethod.Provider.of({
306
+ list: () => Effect3.succeed([]),
307
+ read: Effect3.fn(function* ({ olds }) {
308
+ return yield* readMethod(olds);
300
309
  }),
301
- diff: Effect2.fn(function* ({ news, output }) {
310
+ diff: Effect3.fn(function* ({ news, output }) {
302
311
  if (output === undefined || !isResolved(news))
303
312
  return;
304
- const live = yield* readRole(news);
313
+ const live = yield* readMethod(news);
305
314
  if (live === undefined)
306
315
  return { action: "update" };
316
+ if (live.type !== news.type)
317
+ return { action: "replace" };
307
318
  if (matches2(live, news))
308
319
  return { action: "noop" };
309
320
  return { action: "update" };
310
321
  }),
311
- reconcile: Effect2.fn(function* ({ news }) {
322
+ reconcile: Effect3.fn(function* ({ news }) {
323
+ let live = yield* readMethod(news);
324
+ if (live === undefined) {
325
+ yield* enableAuthMethod(news);
326
+ if (wantsTune2(news))
327
+ yield* tuneAuthMethod(news);
328
+ } else if (!matches2(live, news)) {
329
+ if (live.type !== news.type) {
330
+ return yield* Effect3.die(new Error(`Bao.AuthMethod ${authPath(news.path)}: live type ${live.type} != ${news.type}. ` + "Auth method type is immutable — replace manually."));
331
+ }
332
+ yield* tuneAuthMethod(news);
333
+ }
334
+ live = yield* readMethod(news);
335
+ if (live === undefined) {
336
+ return yield* Effect3.die(new Error(`Bao.AuthMethod ${authPath(news.path)}: write returned no error but the method is still absent.`));
337
+ }
338
+ return live;
339
+ }),
340
+ delete: Effect3.fn(function* ({ output }) {
341
+ yield* disableAuthMethod(output.path);
342
+ return;
343
+ })
344
+ })));
345
+ // src/openbao/auth-role.ts
346
+ import { Resource as Resource2 } from "alchemy";
347
+ import { isResolved as isResolved2 } from "alchemy/Diff";
348
+ import * as Provider2 from "alchemy/Provider";
349
+ import * as Effect4 from "effect/Effect";
350
+
351
+ // src/openbao/auth-role-form.ts
352
+ var policiesOf = (live) => {
353
+ const raw = live["token_policies"];
354
+ if (!Array.isArray(raw))
355
+ return [];
356
+ return raw.filter((entry) => typeof entry === "string").slice().sort();
357
+ };
358
+ var bool = (value, fallback) => typeof value === "boolean" ? value : fallback;
359
+ var int = (value, fallback) => typeof value === "number" && Number.isFinite(value) ? value : fallback;
360
+ var ttlText = (seconds, fallback = "") => {
361
+ if (seconds === undefined)
362
+ return fallback;
363
+ if (seconds % 86400 === 0)
364
+ return `${String(seconds / 86400)}d`;
365
+ if (seconds % 3600 === 0)
366
+ return `${String(seconds / 3600)}h`;
367
+ if (seconds % 60 === 0)
368
+ return `${String(seconds / 60)}m`;
369
+ return `${String(seconds)}s`;
370
+ };
371
+ var attributesOf3 = (props, live) => {
372
+ const attrs = {
373
+ name: props.name,
374
+ tokenPolicies: policiesOf(live),
375
+ tokenTtl: ttlText(ttlSeconds(live["token_ttl"])),
376
+ tokenMaxTtl: ttlText(ttlSeconds(live["token_max_ttl"])),
377
+ secretIdTtl: ttlText(ttlSeconds(live["secret_id_ttl"]), "0"),
378
+ bindSecretId: bool(live["bind_secret_id"], true),
379
+ secretIdNumUses: int(live["secret_id_num_uses"], 0)
380
+ };
381
+ return { ...attrs, digest: sha256(JSON.stringify(attrs)) };
382
+ };
383
+ var readPath3 = (name) => `auth/approle/role/${name}`;
384
+ var writeBody = (props) => {
385
+ const body = {
386
+ token_policies: props.tokenPolicies.join(","),
387
+ token_ttl: props.tokenTtl,
388
+ token_max_ttl: props.tokenMaxTtl,
389
+ secret_id_ttl: props.secretIdTtl
390
+ };
391
+ if (props.bindSecretId !== undefined)
392
+ body["bind_secret_id"] = String(props.bindSecretId);
393
+ if (props.secretIdNumUses !== undefined) {
394
+ body["secret_id_num_uses"] = String(props.secretIdNumUses);
395
+ }
396
+ return body;
397
+ };
398
+ var samePolicies = (want, have) => want.length === have.length && want.every((policy, index) => policy === have[index]);
399
+ var sameTtl3 = (want, have) => {
400
+ const wantSeconds = parseDuration(want);
401
+ const haveSeconds = ttlSeconds(have);
402
+ return wantSeconds !== undefined && wantSeconds === haveSeconds;
403
+ };
404
+ var matches3 = (attributes, props) => {
405
+ const wantPolicies = props.tokenPolicies.slice().sort();
406
+ return samePolicies(wantPolicies, attributes.tokenPolicies) && sameTtl3(props.tokenTtl, attributes.tokenTtl) && sameTtl3(props.tokenMaxTtl, attributes.tokenMaxTtl) && sameTtl3(props.secretIdTtl, attributes.secretIdTtl) && (props.bindSecretId === undefined || attributes.bindSecretId === props.bindSecretId) && (props.secretIdNumUses === undefined || attributes.secretIdNumUses === props.secretIdNumUses);
407
+ };
408
+
409
+ // src/openbao/auth-role.ts
410
+ var BaoAuthRole = Resource2("Bao.AuthRole", {
411
+ defaultRemovalPolicy: "retain"
412
+ });
413
+ var readRole = (props) => Effect4.gen(function* () {
414
+ const live = yield* baoRead(readPath3(props.name));
415
+ if (live === undefined)
416
+ return;
417
+ return attributesOf3(props, live);
418
+ });
419
+ var BaoAuthRoleProvider = () => Provider2.effect(BaoAuthRole, Effect4.succeed(BaoAuthRole.Provider.of({
420
+ list: () => Effect4.succeed([]),
421
+ read: Effect4.fn(function* ({ olds }) {
422
+ return yield* readRole(olds);
423
+ }),
424
+ diff: Effect4.fn(function* ({ news, output }) {
425
+ if (output === undefined || !isResolved2(news))
426
+ return;
312
427
  const live = yield* readRole(news);
313
- if (live === undefined || !matches2(live, news)) {
314
- yield* baoWrite("PUT", readPath2(news.name), writeBody(news));
428
+ if (live === undefined)
429
+ return { action: "update" };
430
+ if (matches3(live, news))
431
+ return { action: "noop" };
432
+ return { action: "update" };
433
+ }),
434
+ reconcile: Effect4.fn(function* ({ news }) {
435
+ const live = yield* readRole(news);
436
+ if (live === undefined || !matches3(live, news)) {
437
+ yield* baoWrite("PUT", readPath3(news.name), writeBody(news));
315
438
  }
316
439
  const after = yield* readRole(news);
317
440
  if (after === undefined) {
318
- return yield* Effect2.die(new Error(`Bao.AuthRole ${news.name}: write returned no error but the role is still absent.`));
441
+ return yield* Effect4.die(new Error(`Bao.AuthRole ${news.name}: write returned no error but the role is still absent.`));
319
442
  }
320
443
  return after;
321
444
  }),
322
- delete: Effect2.fn(function* ({ output }) {
323
- yield* baoDelete(readPath2(output.name));
445
+ delete: Effect4.fn(function* ({ output }) {
446
+ yield* baoDelete(readPath3(output.name));
324
447
  return;
325
448
  })
326
449
  })));
327
450
  // src/openbao/cloudflare-role.ts
328
- import { Resource as Resource2 } from "alchemy";
329
- import { isResolved as isResolved2 } from "alchemy/Diff";
330
- import * as Provider2 from "alchemy/Provider";
331
- import * as Effect5 from "effect/Effect";
451
+ import { Resource as Resource3 } from "alchemy";
452
+ import { isResolved as isResolved3 } from "alchemy/Diff";
453
+ import * as Provider3 from "alchemy/Provider";
454
+ import * as Effect7 from "effect/Effect";
332
455
 
333
456
  // src/openbao/cloudflare-group-scope.ts
334
457
  var zoneResource = (zoneId) => `com.cloudflare.api.account.zone.${zoneId}`;
@@ -348,7 +471,7 @@ var groupKey = (name, scope) => `${scope} ${name}`;
348
471
 
349
472
  // src/openbao/cloudflare-permission-groups.ts
350
473
  import * as Context2 from "effect/Context";
351
- import * as Effect4 from "effect/Effect";
474
+ import * as Effect6 from "effect/Effect";
352
475
 
353
476
  // src/openbao/cloudflare-permission-groups-solve.ts
354
477
  var observationsOf = (declared, live) => declared.flatMap((role) => {
@@ -518,7 +641,7 @@ var samePolicies2 = (want, have) => want.length === have.length && want.every((w
518
641
  });
519
642
 
520
643
  // src/openbao/cloudflare-role-wire.ts
521
- import * as Effect3 from "effect/Effect";
644
+ import * as Effect5 from "effect/Effect";
522
645
 
523
646
  // src/openbao/cloudflare-role-form.ts
524
647
  var rolePath = (mount, name) => `${mountPath(mount)}/roles/${name}`;
@@ -531,7 +654,7 @@ var liveRoleOf = (data) => ({
531
654
  policiesText: typeof data["policies"] === "string" ? data["policies"] : "",
532
655
  ttl: seconds(data["ttl"])
533
656
  });
534
- var attributesOf3 = (props, live) => {
657
+ var attributesOf4 = (props, live) => {
535
658
  const attrs = {
536
659
  description: live.description,
537
660
  maxTtl: live.maxTtl ?? 0,
@@ -561,7 +684,7 @@ var writeBody2 = (props, policies) => ({
561
684
  policies: policiesJson(policies),
562
685
  ttl: props.ttl
563
686
  });
564
- var sameTtl3 = (want, have) => {
687
+ var sameTtl4 = (want, have) => {
565
688
  const wantSeconds = parseDuration(want);
566
689
  return wantSeconds !== undefined && wantSeconds === have;
567
690
  };
@@ -570,10 +693,10 @@ var differences = (props, policies, live) => {
570
693
  if (props.description !== live.description) {
571
694
  out.push({ field: "description", have: live.description, want: props.description });
572
695
  }
573
- if (!sameTtl3(props.ttl, live.ttl)) {
696
+ if (!sameTtl4(props.ttl, live.ttl)) {
574
697
  out.push({ field: "ttl", have: String(live.ttl), want: props.ttl });
575
698
  }
576
- if (!sameTtl3(props.maxTtl, live.maxTtl)) {
699
+ if (!sameTtl4(props.maxTtl, live.maxTtl)) {
577
700
  out.push({ field: "max_ttl", have: String(live.maxTtl), want: props.maxTtl });
578
701
  }
579
702
  if (live.policies === undefined || !samePolicies2(policies, live.policies)) {
@@ -583,7 +706,7 @@ var differences = (props, policies, live) => {
583
706
  };
584
707
 
585
708
  // src/openbao/cloudflare-role-wire.ts
586
- var readCloudflareRole = (mount, name) => Effect3.map(baoRead(rolePath(mount, name)), (data) => data === undefined ? undefined : liveRoleOf(data));
709
+ var readCloudflareRole = (mount, name) => Effect5.map(baoRead(rolePath(mount, name)), (data) => data === undefined ? undefined : liveRoleOf(data));
587
710
  var writeCloudflareRole = (mount, name, body) => baoWrite("PUT", rolePath(mount, name), body);
588
711
  var deleteCloudflareRole = (mount, name) => baoDelete(rolePath(mount, name));
589
712
 
@@ -605,9 +728,9 @@ var pick = (mount, groups, refs, hint) => {
605
728
  const unknown = refs.filter((ref) => !groups.has(groupKey(ref.name, ref.scope)));
606
729
  if (unknown.length > 0) {
607
730
  const problems = unknown.map((ref) => `unknown group ${JSON.stringify(ref.name)} at scope ${ref.scope} — ${hint}`);
608
- return Effect4.fail(new CloudflareGroupsError(mount, problems));
731
+ return Effect6.fail(new CloudflareGroupsError(mount, problems));
609
732
  }
610
- return Effect4.succeed(new Map(refs.flatMap((ref) => {
733
+ return Effect6.succeed(new Map(refs.flatMap((ref) => {
611
734
  const key = groupKey(ref.name, ref.scope);
612
735
  const id = groups.get(key);
613
736
  return id === undefined ? [] : [[key, id]];
@@ -615,15 +738,15 @@ var pick = (mount, groups, refs, hint) => {
615
738
  };
616
739
  var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
617
740
  var deniedHint = (mount) => `GET ${mountPath(mount)}/permission-groups answered 403 — this token's policy carries no ` + `\`path "${mountPath(mount)}/permission-groups" { capabilities = ["read"] }\` grant. ` + "It is declared in ../platform/secrets/vault/policies/homeflare-admin/" + "20-cloudflare-permission-groups.hcl and applies with `alchemy deploy` of this stack";
618
- var deniedNamed = (mount, read) => Effect4.catchIf(read, (error) => error.status === 403, () => Effect4.fail(new CloudflareGroupsError(mount, [deniedHint(mount)])));
619
- var engineGroups = (mount) => Effect4.flatMap(deniedNamed(mount, baoRead(`${mountPath(mount)}/permission-groups`)), (data) => {
741
+ var deniedNamed = (mount, read) => Effect6.catchIf(read, (error) => error.status === 403, () => Effect6.fail(new CloudflareGroupsError(mount, [deniedHint(mount)])));
742
+ var engineGroups = (mount) => Effect6.flatMap(deniedNamed(mount, baoRead(`${mountPath(mount)}/permission-groups`)), (data) => {
620
743
  const list = data?.["permission_groups"];
621
744
  if (data === undefined) {
622
745
  const why = "GET <mount>/permission-groups answered 404 — the endpoint is not deployed here";
623
- return Effect4.fail(new CloudflareGroupsError(mount, [why]));
746
+ return Effect6.fail(new CloudflareGroupsError(mount, [why]));
624
747
  }
625
748
  if (!Array.isArray(list)) {
626
- return Effect4.fail(new CloudflareGroupsError(mount, ["no permission_groups array in reply"]));
749
+ return Effect6.fail(new CloudflareGroupsError(mount, ["no permission_groups array in reply"]));
627
750
  }
628
751
  const scoped = new Map;
629
752
  const idsOf = new Map;
@@ -650,24 +773,24 @@ var engineGroups = (mount) => Effect4.flatMap(deniedNamed(mount, baoRead(`${moun
650
773
  const only = [...ids];
651
774
  return ids.size === 1 && only[0] !== undefined ? [[name, only[0]]] : [];
652
775
  }));
653
- return problems.length > 0 ? Effect4.fail(new CloudflareGroupsError(mount, problems)) : Effect4.succeed(new Map([...atEveryScope(sole), ...scoped]));
776
+ return problems.length > 0 ? Effect6.fail(new CloudflareGroupsError(mount, problems)) : Effect6.succeed(new Map([...atEveryScope(sole), ...scoped]));
654
777
  });
655
- var permissionGroupsFromEngine = () => Effect4.sync(() => {
778
+ var permissionGroupsFromEngine = () => Effect6.sync(() => {
656
779
  const cache = new Map;
657
- const cachedFor = (mount) => Effect4.suspend(() => {
780
+ const cachedFor = (mount) => Effect6.suspend(() => {
658
781
  const hit = cache.get(mountPath(mount));
659
782
  if (hit !== undefined)
660
783
  return hit;
661
- return Effect4.flatMap(Effect4.cached(engineGroups(mount)), (lookup) => {
784
+ return Effect6.flatMap(Effect6.cached(engineGroups(mount)), (lookup) => {
662
785
  cache.set(mountPath(mount), lookup);
663
786
  return lookup;
664
787
  });
665
788
  });
666
789
  return CloudflarePermissionGroups.of({
667
- resolve: (mount, refs) => Effect4.flatMap(cachedFor(mount), (groups) => pick(mount, groups, refs, "the engine does not list it for this account at that scope"))
790
+ resolve: (mount, refs) => Effect6.flatMap(cachedFor(mount), (groups) => pick(mount, groups, refs, "the engine does not list it for this account at that scope"))
668
791
  });
669
792
  });
670
- var permissionGroupsFromLiveRoles = (declared) => Effect4.gen(function* () {
793
+ var permissionGroupsFromLiveRoles = (declared) => Effect6.gen(function* () {
671
794
  const accountOf = new Map;
672
795
  const byAccount = new Map;
673
796
  for (const [mount, roles] of declared) {
@@ -678,9 +801,9 @@ var permissionGroupsFromLiveRoles = (declared) => Effect4.gen(function* () {
678
801
  }
679
802
  const solved = new Map;
680
803
  for (const [account, roles] of byAccount) {
681
- const solve = Effect4.gen(function* () {
804
+ const solve = Effect6.gen(function* () {
682
805
  const live = new Map;
683
- yield* Effect4.all(roles.map((role) => Effect4.map(readCloudflareRole(role.mount, role.name), (read) => {
806
+ yield* Effect6.all(roles.map((role) => Effect6.map(readCloudflareRole(role.mount, role.name), (read) => {
684
807
  if (read?.policies !== undefined) {
685
808
  live.set(`${role.mount}/${role.name}`, read.policies);
686
809
  }
@@ -688,11 +811,11 @@ var permissionGroupsFromLiveRoles = (declared) => Effect4.gen(function* () {
688
811
  const result = solveGroups(observationsOf(roles, live));
689
812
  const problems = describeProblems(result);
690
813
  if (problems.length > 0) {
691
- return yield* Effect4.fail(new CloudflareGroupsError(`account ${account}`, problems));
814
+ return yield* Effect6.fail(new CloudflareGroupsError(`account ${account}`, problems));
692
815
  }
693
816
  return atEveryScope(result.groups);
694
817
  });
695
- solved.set(account, yield* Effect4.cached(solve));
818
+ solved.set(account, yield* Effect6.cached(solve));
696
819
  }
697
820
  return CloudflarePermissionGroups.of({
698
821
  resolve: (mount, refs) => {
@@ -700,21 +823,21 @@ var permissionGroupsFromLiveRoles = (declared) => Effect4.gen(function* () {
700
823
  const lookup = account === undefined ? undefined : solved.get(account);
701
824
  if (account === undefined || lookup === undefined) {
702
825
  const why = "no declared role on this mount, so no live role can vouch for its groups";
703
- return Effect4.fail(new CloudflareGroupsError(mount, [why]));
826
+ return Effect6.fail(new CloudflareGroupsError(mount, [why]));
704
827
  }
705
828
  const hint = `no live role on account ${account} carries it; a NEW group needs the engine endpoint`;
706
- return Effect4.flatMap(lookup, (groups) => pick(mount, groups, refs, hint));
829
+ return Effect6.flatMap(lookup, (groups) => pick(mount, groups, refs, hint));
707
830
  }
708
831
  });
709
832
  });
710
833
 
711
834
  // src/openbao/cloudflare-role.ts
712
- var BaoCloudflareRole = Resource2("Bao.CloudflareRole", {
835
+ var BaoCloudflareRole = Resource3("Bao.CloudflareRole", {
713
836
  defaultRemovalPolicy: "retain"
714
837
  });
715
- var BaoCloudflareRoleProvider = () => Provider2.effect(BaoCloudflareRole, Effect5.gen(function* () {
838
+ var BaoCloudflareRoleProvider = () => Provider3.effect(BaoCloudflareRole, Effect7.gen(function* () {
716
839
  const groups = yield* CloudflarePermissionGroups;
717
- const resolved = (props) => Effect5.gen(function* () {
840
+ const resolved = (props) => Effect7.gen(function* () {
718
841
  const refs = new Map;
719
842
  for (const policy of props.policies) {
720
843
  const scope = policy.scope ?? scopeOfResource(policy.resource);
@@ -724,18 +847,18 @@ var BaoCloudflareRoleProvider = () => Provider2.effect(BaoCloudflareRole, Effect
724
847
  const ids = yield* groups.resolve(props.mount, [...refs.values()]);
725
848
  const { missing, policies } = resolvePolicies(props.policies, ids);
726
849
  if (missing.length > 0) {
727
- return yield* Effect5.die(new Error(`Bao.CloudflareRole ${rolePath(props.mount, props.name)}: groups ` + `${missing.join(", ")} came back unresolved from a lookup that reported success.`));
850
+ return yield* Effect7.die(new Error(`Bao.CloudflareRole ${rolePath(props.mount, props.name)}: groups ` + `${missing.join(", ")} came back unresolved from a lookup that reported success.`));
728
851
  }
729
852
  return policies;
730
853
  });
731
854
  return BaoCloudflareRole.Provider.of({
732
- list: () => Effect5.succeed([]),
733
- read: Effect5.fn(function* ({ olds }) {
855
+ list: () => Effect7.succeed([]),
856
+ read: Effect7.fn(function* ({ olds }) {
734
857
  const live = yield* readCloudflareRole(olds.mount, olds.name);
735
- return live === undefined ? undefined : attributesOf3(olds, live);
858
+ return live === undefined ? undefined : attributesOf4(olds, live);
736
859
  }),
737
- diff: Effect5.fn(function* ({ news, output }) {
738
- if (output === undefined || !isResolved2(news))
860
+ diff: Effect7.fn(function* ({ news, output }) {
861
+ if (output === undefined || !isResolved3(news))
739
862
  return;
740
863
  if (refusalOf(news) !== undefined)
741
864
  return { action: "update" };
@@ -745,11 +868,11 @@ var BaoCloudflareRoleProvider = () => Provider2.effect(BaoCloudflareRole, Effect
745
868
  return { action: "update" };
746
869
  return differences(news, policies, live).length === 0 ? { action: "noop" } : { action: "update" };
747
870
  }),
748
- reconcile: Effect5.fn(function* ({ news }) {
871
+ reconcile: Effect7.fn(function* ({ news }) {
749
872
  const path = rolePath(news.mount, news.name);
750
873
  const refusal = refusalOf(news);
751
874
  if (refusal !== undefined) {
752
- return yield* Effect5.die(new Error(`Bao.CloudflareRole ${path}: ${refusal}.`));
875
+ return yield* Effect7.die(new Error(`Bao.CloudflareRole ${path}: ${refusal}.`));
753
876
  }
754
877
  const policies = yield* resolved(news);
755
878
  const live = yield* readCloudflareRole(news.mount, news.name);
@@ -758,15 +881,15 @@ var BaoCloudflareRoleProvider = () => Provider2.effect(BaoCloudflareRole, Effect
758
881
  }
759
882
  const after = yield* readCloudflareRole(news.mount, news.name);
760
883
  if (after === undefined) {
761
- return yield* Effect5.die(new Error(`Bao.CloudflareRole ${path}: the write succeeded but the role is absent.`));
884
+ return yield* Effect7.die(new Error(`Bao.CloudflareRole ${path}: the write succeeded but the role is absent.`));
762
885
  }
763
886
  const left = differences(news, policies, after);
764
887
  if (left.length > 0) {
765
- return yield* Effect5.die(new Error(`Bao.CloudflareRole ${path}: wrote cleanly but reads back different in ` + `${left.map((d) => d.field).join(", ")}. Inspect the role before retrying.`));
888
+ return yield* Effect7.die(new Error(`Bao.CloudflareRole ${path}: wrote cleanly but reads back different in ` + `${left.map((d) => d.field).join(", ")}. Inspect the role before retrying.`));
766
889
  }
767
- return attributesOf3(news, after);
890
+ return attributesOf4(news, after);
768
891
  }),
769
- delete: Effect5.fn(function* ({ output }) {
892
+ delete: Effect7.fn(function* ({ output }) {
770
893
  yield* deleteCloudflareRole(output.mount, output.name);
771
894
  return;
772
895
  })
@@ -873,7 +996,7 @@ var record = (value, where) => {
873
996
  throw new RolesConfigError(where, "expected a mapping");
874
997
  return value;
875
998
  };
876
- var text2 = (raw, key, where) => {
999
+ var text3 = (raw, key, where) => {
877
1000
  const value = raw[key];
878
1001
  if (typeof value === "string")
879
1002
  return value;
@@ -901,24 +1024,24 @@ var template = (value, where) => {
901
1024
  const groups = texts(raw, "groups", where);
902
1025
  if (groups === undefined)
903
1026
  throw new RolesConfigError(`${where}.groups`, "is required");
904
- const bucket = raw["bucket"] === undefined ? undefined : text2(raw, "bucket", where);
1027
+ const bucket = raw["bucket"] === undefined ? undefined : text3(raw, "bucket", where);
905
1028
  if (bucket !== undefined && bucket.length === 0) {
906
1029
  throw new RolesConfigError(`${where}.bucket`, "is empty; omit it to stay account-wide");
907
1030
  }
908
- const groupsScope = raw["groups_scope"] === undefined ? undefined : groupScopeNamed(text2(raw, "groups_scope", where));
1031
+ const groupsScope = raw["groups_scope"] === undefined ? undefined : groupScopeNamed(text3(raw, "groups_scope", where));
909
1032
  if (raw["groups_scope"] !== undefined && groupsScope === undefined) {
910
1033
  throw new RolesConfigError(`${where}.groups_scope`, `expected one of ${Object.keys(GROUP_SCOPES).join(", ")}`);
911
1034
  }
912
1035
  return {
913
1036
  accountGroups: texts(raw, "account_groups", where) ?? [],
914
1037
  bucket,
915
- bucketJurisdiction: raw["bucket_jurisdiction"] === undefined ? "default" : text2(raw, "bucket_jurisdiction", where),
916
- desc: raw["desc"] === undefined ? "" : text2(raw, "desc", where),
1038
+ bucketJurisdiction: raw["bucket_jurisdiction"] === undefined ? "default" : text3(raw, "bucket_jurisdiction", where),
1039
+ desc: raw["desc"] === undefined ? "" : text3(raw, "desc", where),
917
1040
  groups,
918
1041
  groupsScope,
919
- maxTtl: text2(raw, "max_ttl", where),
920
- name: text2(raw, "name", where),
921
- ttl: text2(raw, "ttl", where),
1042
+ maxTtl: text3(raw, "max_ttl", where),
1043
+ name: text3(raw, "name", where),
1044
+ ttl: text3(raw, "ttl", where),
922
1045
  zoneTypes: texts(raw, "zone_types", where) ?? [],
923
1046
  zones: texts(raw, "zones", where)
924
1047
  };
@@ -941,7 +1064,7 @@ var account = (key, value, surfaces) => {
941
1064
  }
942
1065
  }
943
1066
  const zones = raw["zones"] === undefined || raw["zones"] === "all" ? "all" : texts(raw, "zones", where);
944
- return { id: text2(raw, "id", where), key, surfaces: names, zones: zones ?? "all" };
1067
+ return { id: text3(raw, "id", where), key, surfaces: names, zones: zones ?? "all" };
945
1068
  };
946
1069
  var parseRolesConfig = (yaml) => {
947
1070
  const root = record(Bun.YAML.parse(yaml), "(document)");
@@ -952,44 +1075,44 @@ var parseRolesConfig = (yaml) => {
952
1075
  const accounts = Object.entries(record(root["accounts"], "accounts")).map(([key, value]) => account(key, value, surfaces));
953
1076
  return {
954
1077
  accounts,
955
- namespace: text2(record(root["defaults"], "defaults"), "namespace", "defaults"),
1078
+ namespace: text3(record(root["defaults"], "defaults"), "namespace", "defaults"),
956
1079
  surfaces
957
1080
  };
958
1081
  };
959
1082
  // src/openbao/mount.ts
960
- import { Resource as Resource3 } from "alchemy";
961
- import { isResolved as isResolved3 } from "alchemy/Diff";
962
- import * as Provider3 from "alchemy/Provider";
963
- import * as Effect7 from "effect/Effect";
1083
+ import { Resource as Resource4 } from "alchemy";
1084
+ import { isResolved as isResolved4 } from "alchemy/Diff";
1085
+ import * as Provider4 from "alchemy/Provider";
1086
+ import * as Effect9 from "effect/Effect";
964
1087
 
965
1088
  // src/openbao/mount-wire.ts
966
- import * as Effect6 from "effect/Effect";
967
- var absentFromTable = (path, asked) => baoRead("sys/mounts").pipe(Effect6.mapError((listing) => new BaoError(asked.status, asked.method, asked.path, [
1089
+ import * as Effect8 from "effect/Effect";
1090
+ var absentFromTable2 = (path, asked) => baoRead("sys/mounts").pipe(Effect8.mapError((listing) => new BaoError(asked.status, asked.method, asked.path, [
968
1091
  ...asked.errors,
969
1092
  `sys/mounts could not confirm the mount is absent: ${listing.message}`
970
- ])), Effect6.flatMap((table) => table !== undefined && !Object.hasOwn(table, `${mountPath(path)}/`) ? Effect6.succeed(undefined) : Effect6.fail(asked)));
971
- var readMountData = (path) => baoRead(readPath(path)).pipe(Effect6.catchIf((error) => error.status === 400, (error) => absentFromTable(path, error)));
1093
+ ])), Effect8.flatMap((table) => table !== undefined && !Object.hasOwn(table, `${mountPath(path)}/`) ? Effect8.succeed(undefined) : Effect8.fail(asked)));
1094
+ var readMountData = (path) => baoRead(readPath(path)).pipe(Effect8.catchIf((error) => error.status === 400, (error) => absentFromTable2(path, error)));
972
1095
  var enableMount = (props) => baoWrite("POST", readPath(props.path), enableBody(props));
973
1096
  var tuneMount = (props) => baoWrite("POST", tunePath(props.path), tuneBody(props));
974
1097
  var disableMount = (path) => baoDelete(readPath(path));
975
1098
 
976
1099
  // src/openbao/mount.ts
977
- var BaoMount = Resource3("Bao.Mount", {
1100
+ var BaoMount = Resource4("Bao.Mount", {
978
1101
  defaultRemovalPolicy: "retain"
979
1102
  });
980
- var readMount = (props) => Effect7.gen(function* () {
1103
+ var readMount = (props) => Effect9.gen(function* () {
981
1104
  const live = yield* readMountData(props.path);
982
1105
  if (live === undefined)
983
1106
  return;
984
1107
  return attributesOf(props, live);
985
1108
  });
986
- var BaoMountProvider = () => Provider3.effect(BaoMount, Effect7.succeed(BaoMount.Provider.of({
987
- list: () => Effect7.succeed([]),
988
- read: Effect7.fn(function* ({ olds }) {
1109
+ var BaoMountProvider = () => Provider4.effect(BaoMount, Effect9.succeed(BaoMount.Provider.of({
1110
+ list: () => Effect9.succeed([]),
1111
+ read: Effect9.fn(function* ({ olds }) {
989
1112
  return yield* readMount(olds);
990
1113
  }),
991
- diff: Effect7.fn(function* ({ news, output }) {
992
- if (output === undefined || !isResolved3(news))
1114
+ diff: Effect9.fn(function* ({ news, output }) {
1115
+ if (output === undefined || !isResolved4(news))
993
1116
  return;
994
1117
  const live = yield* readMount(news);
995
1118
  if (live === undefined)
@@ -1000,7 +1123,7 @@ var BaoMountProvider = () => Provider3.effect(BaoMount, Effect7.succeed(BaoMount
1000
1123
  return { action: "noop" };
1001
1124
  return { action: "update" };
1002
1125
  }),
1003
- reconcile: Effect7.fn(function* ({ news }) {
1126
+ reconcile: Effect9.fn(function* ({ news }) {
1004
1127
  let live = yield* readMount(news);
1005
1128
  if (live === undefined) {
1006
1129
  yield* enableMount(news);
@@ -1008,26 +1131,26 @@ var BaoMountProvider = () => Provider3.effect(BaoMount, Effect7.succeed(BaoMount
1008
1131
  yield* tuneMount(news);
1009
1132
  } else if (!matches(live, news)) {
1010
1133
  if (live.type !== news.type) {
1011
- return yield* Effect7.die(new Error(`Bao.Mount ${mountPath(news.path)}: live type ${live.type} != ${news.type}. ` + "Secrets engine type is immutable — replace manually."));
1134
+ return yield* Effect9.die(new Error(`Bao.Mount ${mountPath(news.path)}: live type ${live.type} != ${news.type}. ` + "Secrets engine type is immutable — replace manually."));
1012
1135
  }
1013
1136
  yield* tuneMount(news);
1014
1137
  }
1015
1138
  live = yield* readMount(news);
1016
1139
  if (live === undefined) {
1017
- return yield* Effect7.die(new Error(`Bao.Mount ${mountPath(news.path)}: write returned no error but the mount is still absent.`));
1140
+ return yield* Effect9.die(new Error(`Bao.Mount ${mountPath(news.path)}: write returned no error but the mount is still absent.`));
1018
1141
  }
1019
1142
  return live;
1020
1143
  }),
1021
- delete: Effect7.fn(function* ({ output }) {
1144
+ delete: Effect9.fn(function* ({ output }) {
1022
1145
  yield* disableMount(output.path);
1023
1146
  return;
1024
1147
  })
1025
1148
  })));
1026
1149
  // src/openbao/pki-role.ts
1027
- import { Resource as Resource4 } from "alchemy";
1028
- import { isResolved as isResolved4 } from "alchemy/Diff";
1029
- import * as Provider4 from "alchemy/Provider";
1030
- import * as Effect8 from "effect/Effect";
1150
+ import { Resource as Resource5 } from "alchemy";
1151
+ import { isResolved as isResolved5 } from "alchemy/Diff";
1152
+ import * as Provider5 from "alchemy/Provider";
1153
+ import * as Effect10 from "effect/Effect";
1031
1154
 
1032
1155
  // src/openbao/pki-role-form.ts
1033
1156
  var sorted = (values) => [...values].sort();
@@ -1050,7 +1173,7 @@ var canonical2 = (input) => ({
1050
1173
  signatureBits: input.signatureBits,
1051
1174
  ttlSeconds: input.ttlSeconds
1052
1175
  });
1053
- var seconds2 = (text3) => parseDuration(text3) ?? -1;
1176
+ var seconds2 = (text4) => parseDuration(text4) ?? -1;
1054
1177
  var canonicalFromProps = (props) => canonical2({
1055
1178
  allowBareDomains: props.allowBareDomains ?? false,
1056
1179
  allowGlobDomains: props.allowGlobDomains ?? false,
@@ -1104,7 +1227,7 @@ var ttlText2 = (value) => {
1104
1227
  };
1105
1228
  var digestOf = (form) => sha256(JSON.stringify(form));
1106
1229
  var rolePath2 = (props) => `${mountPath(props.mount ?? "pki")}/roles/${props.name}`;
1107
- var attributesOf4 = (props, live) => {
1230
+ var attributesOf5 = (props, live) => {
1108
1231
  const form = canonicalFromLive(live);
1109
1232
  return {
1110
1233
  ...form,
@@ -1139,26 +1262,26 @@ var writeBody3 = (props) => {
1139
1262
  body["ext_key_usage"] = usages.join(",");
1140
1263
  return body;
1141
1264
  };
1142
- var matches3 = (attributes, props) => attributes.digest === digestOf(canonicalFromProps(props));
1265
+ var matches4 = (attributes, props) => attributes.digest === digestOf(canonicalFromProps(props));
1143
1266
 
1144
1267
  // src/openbao/pki-role.ts
1145
- var BaoPkiRole = Resource4("Bao.PkiRole", {
1268
+ var BaoPkiRole = Resource5("Bao.PkiRole", {
1146
1269
  defaultRemovalPolicy: "retain"
1147
1270
  });
1148
- var readRole2 = (props) => Effect8.gen(function* () {
1271
+ var readRole2 = (props) => Effect10.gen(function* () {
1149
1272
  const live = yield* baoRead(rolePath2(props));
1150
1273
  if (live === undefined)
1151
1274
  return;
1152
- return attributesOf4(props, live);
1275
+ return attributesOf5(props, live);
1153
1276
  });
1154
- var badDurations = (props) => [["ttl", props.ttl], ["maxTtl", props.maxTtl]].filter(([, text3]) => parseDuration(text3) === undefined);
1155
- var BaoPkiRoleProvider = () => Provider4.effect(BaoPkiRole, Effect8.succeed(BaoPkiRole.Provider.of({
1156
- list: () => Effect8.succeed([]),
1157
- read: Effect8.fn(function* ({ olds }) {
1277
+ var badDurations = (props) => [["ttl", props.ttl], ["maxTtl", props.maxTtl]].filter(([, text4]) => parseDuration(text4) === undefined);
1278
+ var BaoPkiRoleProvider = () => Provider5.effect(BaoPkiRole, Effect10.succeed(BaoPkiRole.Provider.of({
1279
+ list: () => Effect10.succeed([]),
1280
+ read: Effect10.fn(function* ({ olds }) {
1158
1281
  return yield* readRole2(olds);
1159
1282
  }),
1160
- diff: Effect8.fn(function* ({ news, output }) {
1161
- if (output === undefined || !isResolved4(news))
1283
+ diff: Effect10.fn(function* ({ news, output }) {
1284
+ if (output === undefined || !isResolved5(news))
1162
1285
  return;
1163
1286
  if (mountPath(news.mount ?? "pki") !== output.mount)
1164
1287
  return { action: "replace" };
@@ -1168,40 +1291,40 @@ var BaoPkiRoleProvider = () => Provider4.effect(BaoPkiRole, Effect8.succeed(BaoP
1168
1291
  const live = yield* readRole2(news);
1169
1292
  if (live === undefined)
1170
1293
  return { action: "update" };
1171
- return matches3(live, news) ? { action: "noop" } : { action: "update" };
1294
+ return matches4(live, news) ? { action: "noop" } : { action: "update" };
1172
1295
  }),
1173
- reconcile: Effect8.fn(function* ({ news }) {
1296
+ reconcile: Effect10.fn(function* ({ news }) {
1174
1297
  const path = rolePath2(news);
1175
1298
  if (news.allowedDomains.length === 0) {
1176
- return yield* Effect8.die(new Error(`Bao.PkiRole ${path}: allowedDomains is empty. With allow_any_name false ` + "that role can issue no certificate at all."));
1299
+ return yield* Effect10.die(new Error(`Bao.PkiRole ${path}: allowedDomains is empty. With allow_any_name false ` + "that role can issue no certificate at all."));
1177
1300
  }
1178
1301
  const bad = badDurations(news);
1179
1302
  if (bad.length > 0) {
1180
- return yield* Effect8.die(new Error(`Bao.PkiRole ${path}: ${bad.map(([k, v]) => `${k}=${v}`).join(", ")} ` + "is not a duration OpenBao parses (expect 30m, 720h, 8760h or 0)."));
1303
+ return yield* Effect10.die(new Error(`Bao.PkiRole ${path}: ${bad.map(([k, v]) => `${k}=${v}`).join(", ")} ` + "is not a duration OpenBao parses (expect 30m, 720h, 8760h or 0)."));
1181
1304
  }
1182
1305
  const live = yield* readRole2(news);
1183
- if (live === undefined || !matches3(live, news)) {
1306
+ if (live === undefined || !matches4(live, news)) {
1184
1307
  yield* baoWrite("PUT", path, writeBody3(news));
1185
1308
  }
1186
1309
  const after = yield* readRole2(news);
1187
1310
  if (after === undefined) {
1188
- return yield* Effect8.die(new Error(`Bao.PkiRole ${path}: write reported success but the role is absent.`));
1311
+ return yield* Effect10.die(new Error(`Bao.PkiRole ${path}: write reported success but the role is absent.`));
1189
1312
  }
1190
- if (!matches3(after, news)) {
1191
- return yield* Effect8.die(new Error(`Bao.PkiRole ${path}: wrote cleanly but the role read back different. ` + "OpenBao stored something other than what was declared — inspect with " + `\`bao read ${path}\` before retrying.`));
1313
+ if (!matches4(after, news)) {
1314
+ return yield* Effect10.die(new Error(`Bao.PkiRole ${path}: wrote cleanly but the role read back different. ` + "OpenBao stored something other than what was declared — inspect with " + `\`bao read ${path}\` before retrying.`));
1192
1315
  }
1193
1316
  return after;
1194
1317
  }),
1195
- delete: Effect8.fn(function* ({ output }) {
1318
+ delete: Effect10.fn(function* ({ output }) {
1196
1319
  yield* baoDelete(rolePath2(output));
1197
1320
  return;
1198
1321
  })
1199
1322
  })));
1200
1323
  // src/openbao/policy.ts
1201
- import { Resource as Resource5 } from "alchemy";
1202
- import { isResolved as isResolved5 } from "alchemy/Diff";
1203
- import * as Provider5 from "alchemy/Provider";
1204
- import * as Effect10 from "effect/Effect";
1324
+ import { Resource as Resource6 } from "alchemy";
1325
+ import { isResolved as isResolved6 } from "alchemy/Diff";
1326
+ import * as Provider6 from "alchemy/Provider";
1327
+ import * as Effect12 from "effect/Effect";
1205
1328
  import * as FileSystem from "effect/FileSystem";
1206
1329
  import * as Path from "effect/Path";
1207
1330
 
@@ -1209,32 +1332,32 @@ import * as Path from "effect/Path";
1209
1332
  var isEmptyAssembly = (parts, joined) => parts === 0 || !/^\s*path\s+"/m.test(joined);
1210
1333
 
1211
1334
  // src/openbao/policy-wire.ts
1212
- import * as Effect9 from "effect/Effect";
1335
+ import * as Effect11 from "effect/Effect";
1213
1336
  var policyPath = (name) => `sys/policies/acl/${name}`;
1214
- var readPolicy = (name) => Effect9.flatMap(baoRead(policyPath(name)), (data) => {
1337
+ var readPolicy = (name) => Effect11.flatMap(baoRead(policyPath(name)), (data) => {
1215
1338
  if (data === undefined)
1216
- return Effect9.succeed("");
1217
- const text3 = data["policy"];
1218
- return typeof text3 === "string" ? Effect9.succeed(text3) : Effect9.fail(new BaoError(200, "GET", policyPath(name), ["no data.policy in the response"]));
1339
+ return Effect11.succeed("");
1340
+ const text4 = data["policy"];
1341
+ return typeof text4 === "string" ? Effect11.succeed(text4) : Effect11.fail(new BaoError(200, "GET", policyPath(name), ["no data.policy in the response"]));
1219
1342
  });
1220
1343
  var writePolicy = (name, hcl) => baoWrite("PUT", policyPath(name), { policy: hcl });
1221
1344
  var deletePolicy = (name) => baoDelete(policyPath(name));
1222
1345
 
1223
1346
  // src/openbao/policy.ts
1224
- var BaoPolicy = Resource5("Bao.Policy", {
1347
+ var BaoPolicy = Resource6("Bao.Policy", {
1225
1348
  defaultRemovalPolicy: "retain"
1226
1349
  });
1227
1350
  var grantsOf = (hcl) => (hcl.match(/^path /gm) ?? []).length;
1228
- var attributesOf5 = (name, hcl, parts) => ({
1351
+ var attributesOf6 = (name, hcl, parts) => ({
1229
1352
  name,
1230
1353
  digest: sha256(hcl),
1231
1354
  grants: grantsOf(hcl),
1232
1355
  parts
1233
1356
  });
1234
- var BaoPolicyProvider = () => Provider5.effect(BaoPolicy, Effect10.gen(function* () {
1357
+ var BaoPolicyProvider = () => Provider6.effect(BaoPolicy, Effect12.gen(function* () {
1235
1358
  const fs = yield* FileSystem.FileSystem;
1236
1359
  const path = yield* Path.Path;
1237
- const assemble = (dir) => Effect10.gen(function* () {
1360
+ const assemble = (dir) => Effect12.gen(function* () {
1238
1361
  const entries2 = (yield* fs.readDirectory(dir)).filter((f) => f.endsWith(".hcl")).sort();
1239
1362
  let joined = "";
1240
1363
  for (const f of entries2)
@@ -1243,44 +1366,44 @@ var BaoPolicyProvider = () => Provider5.effect(BaoPolicy, Effect10.gen(function*
1243
1366
  return { joined, parts: entries2.length };
1244
1367
  });
1245
1368
  return BaoPolicy.Provider.of({
1246
- list: () => Effect10.succeed([]),
1247
- read: Effect10.fn(function* ({ olds }) {
1369
+ list: () => Effect12.succeed([]),
1370
+ read: Effect12.fn(function* ({ olds }) {
1248
1371
  const live = yield* readPolicy(olds.name);
1249
- return live.length === 0 ? undefined : attributesOf5(olds.name, live, 0);
1372
+ return live.length === 0 ? undefined : attributesOf6(olds.name, live, 0);
1250
1373
  }),
1251
- diff: Effect10.fn(function* ({ news, output }) {
1252
- if (output === undefined || !isResolved5(news))
1374
+ diff: Effect12.fn(function* ({ news, output }) {
1375
+ if (output === undefined || !isResolved6(news))
1253
1376
  return;
1254
1377
  const { joined } = yield* assemble(news.fragments);
1255
1378
  const live = yield* readPolicy(news.name);
1256
1379
  return live.length > 0 && sha256(live) === sha256(joined) ? { action: "noop" } : { action: "update" };
1257
1380
  }),
1258
- reconcile: Effect10.fn(function* ({ news }) {
1381
+ reconcile: Effect12.fn(function* ({ news }) {
1259
1382
  const name = news.name;
1260
1383
  const { joined, parts } = yield* assemble(news.fragments);
1261
1384
  if (isEmptyAssembly(parts, joined))
1262
- return yield* Effect10.die(new Error(`Bao.Policy ${name}: the fragments under ${news.fragments} carry no path grant ` + `(${String(parts)} file(s)). Writing it would revoke every grant the policy carries.`));
1385
+ return yield* Effect12.die(new Error(`Bao.Policy ${name}: the fragments under ${news.fragments} carry no path grant ` + `(${String(parts)} file(s)). Writing it would revoke every grant the policy carries.`));
1263
1386
  const current = yield* readPolicy(name);
1264
1387
  if (current.length > 0 && sha256(current) === sha256(joined)) {
1265
- return attributesOf5(name, joined, parts);
1388
+ return attributesOf6(name, joined, parts);
1266
1389
  }
1267
1390
  yield* writePolicy(name, joined);
1268
- return attributesOf5(name, joined, parts);
1391
+ return attributesOf6(name, joined, parts);
1269
1392
  }),
1270
- delete: Effect10.fn(function* ({ output }) {
1393
+ delete: Effect12.fn(function* ({ output }) {
1271
1394
  yield* deletePolicy(output.name);
1272
1395
  return;
1273
1396
  })
1274
1397
  });
1275
1398
  }));
1276
1399
  // src/openbao/proxmox-role.ts
1277
- import { Resource as Resource6 } from "alchemy";
1278
- import { isResolved as isResolved6 } from "alchemy/Diff";
1279
- import * as Provider6 from "alchemy/Provider";
1280
- import * as Effect11 from "effect/Effect";
1400
+ import { Resource as Resource7 } from "alchemy";
1401
+ import { isResolved as isResolved7 } from "alchemy/Diff";
1402
+ import * as Provider7 from "alchemy/Provider";
1403
+ import * as Effect13 from "effect/Effect";
1281
1404
 
1282
1405
  // src/openbao/proxmox-role-form.ts
1283
- var text3 = (value) => typeof value === "string" ? value : "";
1406
+ var text4 = (value) => typeof value === "string" ? value : "";
1284
1407
  var ttlText3 = (seconds3, fallback = "0") => {
1285
1408
  if (seconds3 === undefined)
1286
1409
  return fallback;
@@ -1293,11 +1416,11 @@ var ttlText3 = (seconds3, fallback = "0") => {
1293
1416
  return `${String(seconds3)}s`;
1294
1417
  };
1295
1418
  var rolePath3 = (mount, name) => `${mountPath(mount)}/roles/${name}`;
1296
- var attributesOf6 = (props, live) => {
1419
+ var attributesOf7 = (props, live) => {
1297
1420
  const attrs = {
1298
1421
  mount: mountPath(props.mount),
1299
- name: text3(live["name"]) || props.name,
1300
- mintUser: text3(live["mint_user"]),
1422
+ name: text4(live["name"]) || props.name,
1423
+ mintUser: text4(live["mint_user"]),
1301
1424
  ttl: ttlText3(ttlSeconds(live["ttl"])),
1302
1425
  maxTtl: ttlText3(ttlSeconds(live["max_ttl"]))
1303
1426
  };
@@ -1318,74 +1441,74 @@ var writeBody4 = (props) => {
1318
1441
  body: { mint_user: props.mintUser, ttl: String(ttl), max_ttl: String(maxTtl) }
1319
1442
  };
1320
1443
  };
1321
- var sameTtl4 = (want, have) => {
1444
+ var sameTtl5 = (want, have) => {
1322
1445
  const wantSeconds = parseDuration(want);
1323
1446
  const haveSeconds = ttlSeconds(have);
1324
1447
  return wantSeconds !== undefined && wantSeconds === haveSeconds;
1325
1448
  };
1326
- var matches4 = (attributes, props) => attributes.mintUser === props.mintUser && sameTtl4(props.ttl, attributes.ttl) && sameTtl4(props.maxTtl, attributes.maxTtl);
1449
+ var matches5 = (attributes, props) => attributes.mintUser === props.mintUser && sameTtl5(props.ttl, attributes.ttl) && sameTtl5(props.maxTtl, attributes.maxTtl);
1327
1450
 
1328
1451
  // src/openbao/proxmox-role.ts
1329
- var BaoProxmoxRole = Resource6("Bao.ProxmoxRole", {
1452
+ var BaoProxmoxRole = Resource7("Bao.ProxmoxRole", {
1330
1453
  defaultRemovalPolicy: "retain"
1331
1454
  });
1332
- var readRole3 = (props) => Effect11.gen(function* () {
1455
+ var readRole3 = (props) => Effect13.gen(function* () {
1333
1456
  const live = yield* baoRead(rolePath3(props.mount, props.name));
1334
1457
  if (live === undefined)
1335
1458
  return;
1336
- return attributesOf6(props, live);
1459
+ return attributesOf7(props, live);
1337
1460
  });
1338
- var BaoProxmoxRoleProvider = () => Provider6.effect(BaoProxmoxRole, Effect11.succeed(BaoProxmoxRole.Provider.of({
1339
- list: () => Effect11.succeed([]),
1340
- read: Effect11.fn(function* ({ olds }) {
1461
+ var BaoProxmoxRoleProvider = () => Provider7.effect(BaoProxmoxRole, Effect13.succeed(BaoProxmoxRole.Provider.of({
1462
+ list: () => Effect13.succeed([]),
1463
+ read: Effect13.fn(function* ({ olds }) {
1341
1464
  return yield* readRole3(olds);
1342
1465
  }),
1343
- diff: Effect11.fn(function* ({ news, output }) {
1344
- if (output === undefined || !isResolved6(news))
1466
+ diff: Effect13.fn(function* ({ news, output }) {
1467
+ if (output === undefined || !isResolved7(news))
1345
1468
  return;
1346
1469
  const live = yield* readRole3(news);
1347
1470
  if (live === undefined)
1348
1471
  return { action: "update" };
1349
- if (matches4(live, news))
1472
+ if (matches5(live, news))
1350
1473
  return { action: "noop" };
1351
1474
  return { action: "update" };
1352
1475
  }),
1353
- reconcile: Effect11.fn(function* ({ news }) {
1476
+ reconcile: Effect13.fn(function* ({ news }) {
1354
1477
  const live = yield* readRole3(news);
1355
1478
  if (live !== undefined && live.mintUser !== news.mintUser && news.allowMintUserChange !== live.mintUser) {
1356
- return yield* Effect11.die(new Error(`Bao.ProxmoxRole ${rolePath3(news.mount, news.name)}: live mint_user ` + `${live.mintUser} != declared ${news.mintUser}. Every token this role mints ` + "inherits the ACL of that PVE user. To re-scope deliberately, declare " + `allowMintUserChange: '${live.mintUser}'.`));
1479
+ return yield* Effect13.die(new Error(`Bao.ProxmoxRole ${rolePath3(news.mount, news.name)}: live mint_user ` + `${live.mintUser} != declared ${news.mintUser}. Every token this role mints ` + "inherits the ACL of that PVE user. To re-scope deliberately, declare " + `allowMintUserChange: '${live.mintUser}'.`));
1357
1480
  }
1358
- if (live === undefined || !matches4(live, news)) {
1481
+ if (live === undefined || !matches5(live, news)) {
1359
1482
  const write = writeBody4(news);
1360
1483
  if (!write.ok) {
1361
- return yield* Effect11.die(new Error(`Bao.ProxmoxRole ${rolePath3(news.mount, news.name)}: unparseable duration ` + `${write.bad.join(", ")}. Use 30s / 5m / 1h / 1d, or 0.`));
1484
+ return yield* Effect13.die(new Error(`Bao.ProxmoxRole ${rolePath3(news.mount, news.name)}: unparseable duration ` + `${write.bad.join(", ")}. Use 30s / 5m / 1h / 1d, or 0.`));
1362
1485
  }
1363
1486
  yield* baoWrite("PUT", rolePath3(news.mount, news.name), write.body);
1364
1487
  }
1365
1488
  const after = yield* readRole3(news);
1366
1489
  if (after === undefined) {
1367
- return yield* Effect11.die(new Error(`Bao.ProxmoxRole ${rolePath3(news.mount, news.name)}: write returned no error ` + "but the role is still absent."));
1490
+ return yield* Effect13.die(new Error(`Bao.ProxmoxRole ${rolePath3(news.mount, news.name)}: write returned no error ` + "but the role is still absent."));
1368
1491
  }
1369
1492
  return after;
1370
1493
  }),
1371
- delete: Effect11.fn(function* ({ output }) {
1494
+ delete: Effect13.fn(function* ({ output }) {
1372
1495
  yield* baoDelete(rolePath3(output.mount, output.name));
1373
1496
  return;
1374
1497
  })
1375
1498
  })));
1376
1499
  // src/openbao/ssh-role.ts
1377
- import { Resource as Resource7 } from "alchemy";
1378
- import { isResolved as isResolved7 } from "alchemy/Diff";
1379
- import * as Provider7 from "alchemy/Provider";
1380
- import * as Effect12 from "effect/Effect";
1500
+ import { Resource as Resource8 } from "alchemy";
1501
+ import { isResolved as isResolved8 } from "alchemy/Diff";
1502
+ import * as Provider8 from "alchemy/Provider";
1503
+ import * as Effect14 from "effect/Effect";
1381
1504
 
1382
1505
  // src/openbao/ssh-role-form.ts
1383
1506
  var mountOf = (mount) => (mount ?? "ssh").replace(/\/+$/, "");
1384
- var readPath3 = (mount, name) => `${mountOf(mount)}/roles/${name}`;
1385
- var text4 = (value) => typeof value === "string" ? value : "";
1507
+ var readPath4 = (mount, name) => `${mountOf(mount)}/roles/${name}`;
1508
+ var text5 = (value) => typeof value === "string" ? value : "";
1386
1509
  var bool3 = (value, fallback) => typeof value === "boolean" ? value : fallback;
1387
1510
  var csvList = (value) => {
1388
- const parts = Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : text4(value).split(",");
1511
+ const parts = Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : text5(value).split(",");
1389
1512
  return [
1390
1513
  ...new Set(parts.map((entry) => entry.trim()).filter((entry) => entry.length > 0))
1391
1514
  ].sort();
@@ -1396,7 +1519,7 @@ var extMap = (value) => {
1396
1519
  return out;
1397
1520
  const source = value;
1398
1521
  for (const key of Object.keys(source).sort())
1399
- out[key] = text4(source[key]);
1522
+ out[key] = text5(source[key]);
1400
1523
  return out;
1401
1524
  };
1402
1525
  var resolve = (props) => ({
@@ -1417,12 +1540,12 @@ var resolve = (props) => ({
1417
1540
  ttl: props.ttl,
1418
1541
  maxTtl: props.maxTtl
1419
1542
  });
1420
- var attributesOf7 = (form, live) => {
1543
+ var attributesOf8 = (form, live) => {
1421
1544
  const attrs = {
1422
1545
  name: form.name,
1423
1546
  mount: form.mount,
1424
1547
  allowedUsers: csvList(live["allowed_users"]),
1425
- defaultUser: text4(live["default_user"]),
1548
+ defaultUser: text5(live["default_user"]),
1426
1549
  allowUserCertificates: bool3(live["allow_user_certificates"], false),
1427
1550
  allowHostCertificates: bool3(live["allow_host_certificates"], false),
1428
1551
  allowedDomains: csvList(live["allowed_domains"]),
@@ -1433,7 +1556,7 @@ var attributesOf7 = (form, live) => {
1433
1556
  allowedCriticalOptions: csvList(live["allowed_critical_options"]),
1434
1557
  defaultCriticalOptions: extMap(live["default_critical_options"]),
1435
1558
  allowEmptyPrincipals: bool3(live["allow_empty_principals"], false),
1436
- keyType: text4(live["key_type"]) || "ca",
1559
+ keyType: text5(live["key_type"]) || "ca",
1437
1560
  ttlSeconds: ttlSeconds(live["ttl"]) ?? 0,
1438
1561
  maxTtlSeconds: ttlSeconds(live["max_ttl"]) ?? 0
1439
1562
  };
@@ -1462,19 +1585,19 @@ var sameMap = (want, have) => {
1462
1585
  const keys = Object.keys(want);
1463
1586
  return keys.length === Object.keys(have).length && keys.every((key) => have[key] === want[key]);
1464
1587
  };
1465
- var sameTtl5 = (want, have) => parseDuration(want) === have;
1588
+ var sameTtl6 = (want, have) => parseDuration(want) === have;
1466
1589
  var badDurations2 = (form) => ["ttl", "maxTtl"].filter((field) => parseDuration(form[field]) === undefined);
1467
- var matches5 = (attributes, form) => attributes.keyType === "ca" && sameList2(form.allowedUsers, attributes.allowedUsers) && attributes.defaultUser === form.defaultUser && attributes.allowUserCertificates === form.allowUserCertificates && attributes.allowHostCertificates === form.allowHostCertificates && sameList2(form.allowedDomains, attributes.allowedDomains) && attributes.allowSubdomains === form.allowSubdomains && attributes.allowBareDomains === form.allowBareDomains && sameList2(form.allowedExtensions, attributes.allowedExtensions) && sameMap(form.defaultExtensions, attributes.defaultExtensions) && sameList2(form.allowedCriticalOptions, attributes.allowedCriticalOptions) && sameMap(form.defaultCriticalOptions, attributes.defaultCriticalOptions) && attributes.allowEmptyPrincipals === form.allowEmptyPrincipals && sameTtl5(form.ttl, attributes.ttlSeconds) && sameTtl5(form.maxTtl, attributes.maxTtlSeconds);
1590
+ var matches6 = (attributes, form) => attributes.keyType === "ca" && sameList2(form.allowedUsers, attributes.allowedUsers) && attributes.defaultUser === form.defaultUser && attributes.allowUserCertificates === form.allowUserCertificates && attributes.allowHostCertificates === form.allowHostCertificates && sameList2(form.allowedDomains, attributes.allowedDomains) && attributes.allowSubdomains === form.allowSubdomains && attributes.allowBareDomains === form.allowBareDomains && sameList2(form.allowedExtensions, attributes.allowedExtensions) && sameMap(form.defaultExtensions, attributes.defaultExtensions) && sameList2(form.allowedCriticalOptions, attributes.allowedCriticalOptions) && sameMap(form.defaultCriticalOptions, attributes.defaultCriticalOptions) && attributes.allowEmptyPrincipals === form.allowEmptyPrincipals && sameTtl6(form.ttl, attributes.ttlSeconds) && sameTtl6(form.maxTtl, attributes.maxTtlSeconds);
1468
1591
 
1469
1592
  // src/openbao/ssh-role.ts
1470
- var BaoSshRole = Resource7("Bao.SshRole", {
1593
+ var BaoSshRole = Resource8("Bao.SshRole", {
1471
1594
  defaultRemovalPolicy: "retain"
1472
1595
  });
1473
- var readRole4 = (form) => Effect12.gen(function* () {
1474
- const live = yield* baoRead(readPath3(form.mount, form.name));
1596
+ var readRole4 = (form) => Effect14.gen(function* () {
1597
+ const live = yield* baoRead(readPath4(form.mount, form.name));
1475
1598
  if (live === undefined)
1476
1599
  return;
1477
- return { attributes: attributesOf7(form, live), live };
1600
+ return { attributes: attributesOf8(form, live), live };
1478
1601
  });
1479
1602
  var UNMANAGED_DEFAULTS = {
1480
1603
  algorithm_signer: "default",
@@ -1496,15 +1619,15 @@ var wouldErase = (live) => {
1496
1619
  }
1497
1620
  return lost.sort();
1498
1621
  };
1499
- var refuse = (message) => Effect12.die(new Error(message));
1500
- var BaoSshRoleProvider = () => Provider7.effect(BaoSshRole, Effect12.succeed(BaoSshRole.Provider.of({
1501
- list: () => Effect12.succeed([]),
1502
- read: Effect12.fn(function* ({ olds }) {
1622
+ var refuse = (message) => Effect14.die(new Error(message));
1623
+ var BaoSshRoleProvider = () => Provider8.effect(BaoSshRole, Effect14.succeed(BaoSshRole.Provider.of({
1624
+ list: () => Effect14.succeed([]),
1625
+ read: Effect14.fn(function* ({ olds }) {
1503
1626
  const found = yield* readRole4(resolve(olds));
1504
1627
  return found?.attributes;
1505
1628
  }),
1506
- diff: Effect12.fn(function* ({ news, output }) {
1507
- if (output === undefined || !isResolved7(news))
1629
+ diff: Effect14.fn(function* ({ news, output }) {
1630
+ if (output === undefined || !isResolved8(news))
1508
1631
  return;
1509
1632
  const form = resolve(news);
1510
1633
  if (output.mount !== form.mount || output.name !== form.name) {
@@ -1513,11 +1636,11 @@ var BaoSshRoleProvider = () => Provider7.effect(BaoSshRole, Effect12.succeed(Bao
1513
1636
  const found = yield* readRole4(form);
1514
1637
  if (found === undefined)
1515
1638
  return { action: "update" };
1516
- return matches5(found.attributes, form) ? { action: "noop" } : { action: "update" };
1639
+ return matches6(found.attributes, form) ? { action: "noop" } : { action: "update" };
1517
1640
  }),
1518
- reconcile: Effect12.fn(function* ({ news }) {
1641
+ reconcile: Effect14.fn(function* ({ news }) {
1519
1642
  const form = resolve(news);
1520
- const path = readPath3(form.mount, form.name);
1643
+ const path = readPath4(form.mount, form.name);
1521
1644
  const bad = badDurations2(form);
1522
1645
  if (bad.length > 0) {
1523
1646
  return yield* refuse(`Bao.SshRole ${path}: ${bad.join(", ")} is not a duration parseDuration understands ` + "(`0` or `<n>s|m|h|d`). It would write, then report update on every plan forever.");
@@ -1526,7 +1649,7 @@ var BaoSshRoleProvider = () => Provider7.effect(BaoSshRole, Effect12.succeed(Bao
1526
1649
  return yield* refuse(`Bao.SshRole ${path}: allowUserCertificates with an empty allowedUsers and ` + "allowEmptyPrincipals false. Every sign request against it would be rejected.");
1527
1650
  }
1528
1651
  const found = yield* readRole4(form);
1529
- if (found === undefined || !matches5(found.attributes, form)) {
1652
+ if (found === undefined || !matches6(found.attributes, form)) {
1530
1653
  if (found !== undefined) {
1531
1654
  const lost = wouldErase(found.live);
1532
1655
  if (lost.length > 0) {
@@ -1541,12 +1664,14 @@ var BaoSshRoleProvider = () => Provider7.effect(BaoSshRole, Effect12.succeed(Bao
1541
1664
  }
1542
1665
  return after.attributes;
1543
1666
  }),
1544
- delete: Effect12.fn(function* ({ output }) {
1545
- yield* baoDelete(readPath3(output.mount, output.name));
1667
+ delete: Effect14.fn(function* ({ output }) {
1668
+ yield* baoDelete(readPath4(output.mount, output.name));
1546
1669
  return;
1547
1670
  })
1548
1671
  })));
1549
1672
  export {
1673
+ BaoAuthMethod,
1674
+ BaoAuthMethodProvider,
1550
1675
  BaoAuthRole,
1551
1676
  BaoAuthRoleProvider,
1552
1677
  BaoCloudflareRole,
@@ -1570,5 +1695,5 @@ export {
1570
1695
  permissionGroupsFromLiveRoles
1571
1696
  };
1572
1697
 
1573
- //# debugId=63DBD5E0F5E3F35664756E2164756E21
1698
+ //# debugId=8FBBE010DA02328C64756E2164756E21
1574
1699
  //# sourceMappingURL=index.js.map