@homeflare/alchemy 0.28.0 → 0.29.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.
Files changed (221) hide show
  1. package/README.md +2 -0
  2. package/dist/caddy/admin-address.d.ts +27 -0
  3. package/dist/caddy/admin-address.d.ts.map +1 -0
  4. package/dist/caddy/admin-calls.d.ts +25 -28
  5. package/dist/caddy/admin-calls.d.ts.map +1 -1
  6. package/dist/caddy/admin.d.ts +28 -38
  7. package/dist/caddy/admin.d.ts.map +1 -1
  8. package/dist/caddy/caddy-http-client.d.ts +25 -0
  9. package/dist/caddy/caddy-http-client.d.ts.map +1 -0
  10. package/dist/caddy/config-errors.d.ts +24 -0
  11. package/dist/caddy/config-errors.d.ts.map +1 -0
  12. package/dist/caddy/config-lifecycle.d.ts +20 -49
  13. package/dist/caddy/config-lifecycle.d.ts.map +1 -1
  14. package/dist/caddy/config-reconcile.d.ts +45 -0
  15. package/dist/caddy/config-reconcile.d.ts.map +1 -0
  16. package/dist/caddy/config.d.ts +4 -3
  17. package/dist/caddy/config.d.ts.map +1 -1
  18. package/dist/caddy/fake-caddy.d.ts +10 -2
  19. package/dist/caddy/fake-caddy.d.ts.map +1 -1
  20. package/dist/caddy/index.d.ts +3 -3
  21. package/dist/caddy/index.d.ts.map +1 -1
  22. package/dist/caddy/index.js +487 -444
  23. package/dist/caddy/index.js.map +16 -12
  24. package/dist/caddy/local-admin.d.ts +20 -34
  25. package/dist/caddy/local-admin.d.ts.map +1 -1
  26. package/dist/caddy/providers.d.ts +19 -3
  27. package/dist/caddy/providers.d.ts.map +1 -1
  28. package/dist/cloudflare/mesh-node-token.d.ts +1 -1
  29. package/dist/cloudflare/mesh-node-token.d.ts.map +1 -1
  30. package/dist/forgejo/branch-protection.d.ts +4 -4
  31. package/dist/forgejo/org-actions-secrets.d.ts +4 -4
  32. package/dist/forgejo/org-label.d.ts +4 -4
  33. package/dist/forgejo/org-team.d.ts +4 -4
  34. package/dist/forgejo/repo-webhook.d.ts +4 -4
  35. package/dist/forgejo/repository.d.ts +4 -4
  36. package/dist/forgejo/team-member.d.ts +4 -4
  37. package/dist/github/declare-repo-baseline.d.ts +1 -1
  38. package/dist/github/declare-repo-baseline.d.ts.map +1 -1
  39. package/dist/github/index.d.ts +8 -4
  40. package/dist/github/index.d.ts.map +1 -1
  41. package/dist/github/index.js +83 -24
  42. package/dist/github/index.js.map +14 -12
  43. package/dist/github/repo-apply-order-fake-providers.d.ts +48 -0
  44. package/dist/github/repo-apply-order-fake-providers.d.ts.map +1 -0
  45. package/dist/github/repo-apply-order-fake-stack.d.ts +13 -0
  46. package/dist/github/repo-apply-order-fake-stack.d.ts.map +1 -0
  47. package/dist/github/repo-auto-merge-gate.d.ts +54 -0
  48. package/dist/github/repo-auto-merge-gate.d.ts.map +1 -0
  49. package/dist/github/repo-baseline-data.d.ts +10 -1
  50. package/dist/github/repo-baseline-data.d.ts.map +1 -1
  51. package/dist/github/repo-policy.d.ts +1 -1
  52. package/dist/github/repo-policy.d.ts.map +1 -1
  53. package/dist/github/repository-ruleset-errors.d.ts +3 -2
  54. package/dist/github/repository-ruleset-errors.d.ts.map +1 -1
  55. package/dist/github/repository-ruleset-form.d.ts.map +1 -1
  56. package/dist/github/repository-ruleset-guards.d.ts +3 -2
  57. package/dist/github/repository-ruleset-guards.d.ts.map +1 -1
  58. package/dist/github/repository-ruleset-octokit.d.ts +49 -0
  59. package/dist/github/repository-ruleset-octokit.d.ts.map +1 -1
  60. package/dist/github/repository-ruleset-probe.d.ts +2 -1
  61. package/dist/github/repository-ruleset-probe.d.ts.map +1 -1
  62. package/dist/github/repository-ruleset-props.d.ts +7 -4
  63. package/dist/github/repository-ruleset-props.d.ts.map +1 -1
  64. package/dist/github/repository-ruleset-providers.d.ts +42 -0
  65. package/dist/github/repository-ruleset-providers.d.ts.map +1 -0
  66. package/dist/github/repository-ruleset.d.ts +26 -4
  67. package/dist/github/repository-ruleset.d.ts.map +1 -1
  68. package/dist/litellm/fake-litellm.d.ts +27 -16
  69. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  70. package/dist/litellm/fake-stack.d.ts +9 -4
  71. package/dist/litellm/fake-stack.d.ts.map +1 -1
  72. package/dist/litellm/index.d.ts +7 -5
  73. package/dist/litellm/index.d.ts.map +1 -1
  74. package/dist/litellm/index.js +53 -123
  75. package/dist/litellm/index.js.map +8 -8
  76. package/dist/litellm/operations.d.ts +60 -0
  77. package/dist/litellm/operations.d.ts.map +1 -0
  78. package/dist/litellm/pass-through-endpoint.d.ts +10 -28
  79. package/dist/litellm/pass-through-endpoint.d.ts.map +1 -1
  80. package/dist/litellm/pass-through-errors.d.ts +37 -0
  81. package/dist/litellm/pass-through-errors.d.ts.map +1 -0
  82. package/dist/litellm/pass-through-form.d.ts +11 -4
  83. package/dist/litellm/pass-through-form.d.ts.map +1 -1
  84. package/dist/litellm/providers.d.ts +7 -5
  85. package/dist/litellm/providers.d.ts.map +1 -1
  86. package/dist/netbox/prefix.d.ts +4 -4
  87. package/dist/paperless/custom-field.d.ts +21 -21
  88. package/dist/paperless/custom-field.d.ts.map +1 -1
  89. package/dist/paperless/document-type.d.ts +34 -4
  90. package/dist/paperless/document-type.d.ts.map +1 -1
  91. package/dist/paperless/fake-paperless.d.ts +36 -19
  92. package/dist/paperless/fake-paperless.d.ts.map +1 -1
  93. package/dist/paperless/index.d.ts +7 -2
  94. package/dist/paperless/index.d.ts.map +1 -1
  95. package/dist/paperless/index.js +164 -228
  96. package/dist/paperless/index.js.map +10 -13
  97. package/dist/paperless/matching-locate.d.ts +42 -20
  98. package/dist/paperless/matching-locate.d.ts.map +1 -1
  99. package/dist/paperless/matching-types.d.ts +47 -18
  100. package/dist/paperless/matching-types.d.ts.map +1 -1
  101. package/dist/paperless/matching.d.ts +30 -27
  102. package/dist/paperless/matching.d.ts.map +1 -1
  103. package/dist/paperless/providers.d.ts +13 -7
  104. package/dist/paperless/providers.d.ts.map +1 -1
  105. package/dist/paperless/storage-path.d.ts +34 -4
  106. package/dist/paperless/storage-path.d.ts.map +1 -1
  107. package/dist/paperless/tag.d.ts +43 -8
  108. package/dist/paperless/tag.d.ts.map +1 -1
  109. package/dist/proxmox/acl.d.ts +30 -23
  110. package/dist/proxmox/acl.d.ts.map +1 -1
  111. package/dist/proxmox/distilled-pve.d.ts +89 -0
  112. package/dist/proxmox/distilled-pve.d.ts.map +1 -0
  113. package/dist/proxmox/index.js +663 -609
  114. package/dist/proxmox/index.js.map +12 -11
  115. package/dist/proxmox/members.d.ts +29 -10
  116. package/dist/proxmox/members.d.ts.map +1 -1
  117. package/docs/caddy-admin.md +1 -1
  118. package/docs/caddy.md +3 -2
  119. package/docs/credentials.md +16 -0
  120. package/docs/litellm.md +21 -13
  121. package/docs/paperless.md +12 -0
  122. package/docs/peers.md +5 -0
  123. package/docs/repo-policy.md +16 -1
  124. package/docs/repository-ruleset.md +53 -13
  125. package/docs/upstream-conformance.md +126 -10
  126. package/package.json +5 -2
  127. package/src/caddy/admin-address.ts +71 -0
  128. package/src/caddy/admin-calls.ts +48 -100
  129. package/src/caddy/admin.ts +37 -41
  130. package/src/caddy/adopt-scope.test.ts +1 -1
  131. package/src/caddy/caddy-http-client.ts +229 -0
  132. package/src/caddy/config-adopt-provider.test.ts +139 -0
  133. package/src/caddy/config-adopt.test.ts +60 -126
  134. package/src/caddy/config-errors.ts +47 -0
  135. package/src/caddy/config-lifecycle.test.ts +55 -42
  136. package/src/caddy/config-lifecycle.ts +72 -162
  137. package/src/caddy/config-reconcile.ts +138 -0
  138. package/src/caddy/config.ts +36 -42
  139. package/src/caddy/fake-caddy.ts +20 -2
  140. package/src/caddy/index.ts +3 -8
  141. package/src/caddy/local-admin.test.ts +35 -21
  142. package/src/caddy/local-admin.ts +60 -167
  143. package/src/caddy/providers.test.ts +14 -6
  144. package/src/caddy/providers.ts +20 -4
  145. package/src/github/declare-repo-baseline-apply-order.test.ts +86 -0
  146. package/src/github/declare-repo-baseline.ts +40 -7
  147. package/src/github/index.ts +8 -4
  148. package/src/github/repo-apply-order-fake-providers.ts +119 -0
  149. package/src/github/repo-apply-order-fake-stack.ts +74 -0
  150. package/src/github/repo-auto-merge-gate.ts +57 -0
  151. package/src/github/repo-baseline-data.test.ts +13 -0
  152. package/src/github/repo-baseline-data.ts +11 -2
  153. package/src/github/repo-policy-apply-order.test.ts +72 -0
  154. package/src/github/repo-policy-stack.test.ts +59 -0
  155. package/src/github/repo-policy.ts +31 -3
  156. package/src/github/repository-ruleset-errors.ts +6 -4
  157. package/src/github/repository-ruleset-exact-adopt-k1.test.ts +109 -0
  158. package/src/github/repository-ruleset-exact-adopt.test.ts +14 -9
  159. package/src/github/repository-ruleset-form.ts +7 -3
  160. package/src/github/repository-ruleset-guards.ts +3 -2
  161. package/src/github/repository-ruleset-octokit.test.ts +141 -0
  162. package/src/github/repository-ruleset-octokit.ts +121 -30
  163. package/src/github/repository-ruleset-probe.ts +2 -1
  164. package/src/github/repository-ruleset-props.ts +7 -4
  165. package/src/github/repository-ruleset-providers.ts +46 -0
  166. package/src/github/repository-ruleset-wire.test.ts +38 -27
  167. package/src/github/repository-ruleset.ts +27 -3
  168. package/src/litellm/fake-litellm.ts +83 -78
  169. package/src/litellm/fake-stack.ts +13 -5
  170. package/src/litellm/index.ts +7 -21
  171. package/src/litellm/operations.ts +149 -0
  172. package/src/litellm/pass-through-endpoint-delete-swallow.test.ts +17 -20
  173. package/src/litellm/pass-through-endpoint-replace.test.ts +3 -4
  174. package/src/litellm/pass-through-endpoint.test.ts +8 -8
  175. package/src/litellm/pass-through-endpoint.ts +21 -31
  176. package/src/litellm/pass-through-errors.ts +37 -0
  177. package/src/litellm/pass-through-form.ts +20 -10
  178. package/src/litellm/providers.ts +8 -7
  179. package/src/paperless/custom-field.test.ts +49 -40
  180. package/src/paperless/custom-field.ts +57 -33
  181. package/src/paperless/document-type.test.ts +48 -0
  182. package/src/paperless/document-type.ts +51 -22
  183. package/src/paperless/fake-paperless.ts +63 -72
  184. package/src/paperless/index.ts +7 -13
  185. package/src/paperless/matching-locate.test.ts +102 -0
  186. package/src/paperless/matching-locate.ts +80 -86
  187. package/src/paperless/matching-types.ts +49 -16
  188. package/src/paperless/matching.ts +77 -90
  189. package/src/paperless/providers.ts +14 -10
  190. package/src/paperless/storage-path.test.ts +56 -0
  191. package/src/paperless/storage-path.ts +53 -24
  192. package/src/paperless/tag-identity.test.ts +127 -0
  193. package/src/paperless/tag.test.ts +100 -0
  194. package/src/paperless/tag.ts +62 -32
  195. package/src/proxmox/acl.test.ts +145 -0
  196. package/src/proxmox/acl.ts +128 -150
  197. package/src/proxmox/distilled-pve.test.ts +231 -0
  198. package/src/proxmox/distilled-pve.ts +147 -0
  199. package/src/proxmox/members-timeout.test.ts +161 -0
  200. package/src/proxmox/members.test.ts +9 -0
  201. package/src/proxmox/members.ts +36 -2
  202. package/dist/litellm/client.d.ts +0 -76
  203. package/dist/litellm/client.d.ts.map +0 -1
  204. package/dist/litellm/credentials.d.ts +0 -48
  205. package/dist/litellm/credentials.d.ts.map +0 -1
  206. package/dist/litellm/generated/pass-through.d.ts +0 -71
  207. package/dist/litellm/generated/pass-through.d.ts.map +0 -1
  208. package/dist/paperless/client.d.ts +0 -37
  209. package/dist/paperless/client.d.ts.map +0 -1
  210. package/dist/paperless/credentials.d.ts +0 -40
  211. package/dist/paperless/credentials.d.ts.map +0 -1
  212. package/dist/paperless/errors.d.ts +0 -49
  213. package/dist/paperless/errors.d.ts.map +0 -1
  214. package/src/litellm/client.ts +0 -195
  215. package/src/litellm/credentials.ts +0 -73
  216. package/src/litellm/generated/pass-through.ts +0 -73
  217. package/src/paperless/client.ts +0 -88
  218. package/src/paperless/credentials.ts +0 -69
  219. package/src/paperless/errors.ts +0 -62
  220. package/src/paperless/matching-identity.test.ts +0 -194
  221. package/src/paperless/matching.test.ts +0 -128
@@ -1,44 +1,47 @@
1
1
  import type { Input } from 'alchemy/Input';
2
+ import type { PaperlessNgxOpContext } from '@distilled.cloud/paperless-ngx/Protocol';
2
3
  import * as Effect from 'effect/Effect';
3
4
  import type { MatchingProps, MatchingSpec } from './matching-types.ts';
4
5
  /** Re-exported so `tag.ts`/`document-type.ts`/`storage-path.ts`/`custom-field.ts` keep importing the contract from `./matching.ts` — only the shape itself lives in `matching-types.ts`, split out to hold the file-size cap. */
5
- export type { FieldSpec, MatchingError, MatchingProps, MatchingRequirements, MatchingSpec, } from './matching-types.ts';
6
- export declare const matchingOperations: <Props extends MatchingProps, Attributes extends {
6
+ export type { FieldSpec, MatchingPage, MatchingProps, MatchingRequirements, MatchingSpec, } from './matching-types.ts';
7
+ export { LOCATE_PAGE, soleMatch } from './matching-locate.ts';
8
+ export declare const matchingOperations: <Props extends MatchingProps, Live extends {
7
9
  readonly id: number;
8
- }>(spec: MatchingSpec<Props, Attributes>) => {
9
- read: (props: Props) => Effect.Effect<Attributes | undefined, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessUnauthorized | import("./errors.ts").PaperlessUnavailable | import("./errors.ts").PaperlessValidation, import("./client.ts").PaperlessRequirements>;
10
+ readonly name: string;
11
+ }, Attributes extends {
12
+ readonly id: number;
13
+ }, E>(spec: MatchingSpec<Props, Live, Attributes, E>) => {
14
+ read: (props: Props) => Effect.Effect<Attributes | undefined, E, PaperlessNgxOpContext>;
10
15
  diff: (news: Input<Props>, output: Attributes | undefined) => Effect.Effect<{
11
16
  readonly action: 'update';
12
17
  } | {
13
18
  readonly action: 'noop';
14
19
  } | {
15
20
  readonly action: 'replace';
16
- } | undefined, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessUnauthorized | import("./errors.ts").PaperlessUnavailable | import("./errors.ts").PaperlessValidation, import("./client.ts").PaperlessRequirements>;
17
- reconcile: (news: Props, output: Attributes | undefined) => Effect.Effect<Attributes, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessError, import("./client.ts").PaperlessRequirements>;
18
- /**
19
- * ⛔ `output.id` FIRST, SAME SWITCH AS `fetchLive` (PR 163 re-review). The engine always
20
- * passes `output` here too (`Apply.ts`'s delete call sites all carry `output: attr`) —
21
- * `olds` is only the PROPS as last persisted, which drifts from the live object exactly
22
- * the way `news` did pre-fix: rename it out of band (by hand, or by another tool) after
23
- * the last successful reconcile, and a name-only locate silently finds nothing, `destroy`
24
- * returns as if there were nothing to delete, and the engine drops the state row anyway —
25
- * reporting "deleted" while the live object survives, permanently orphaned (the same
26
- * consequence `matching.ts`'s header describes for the original bug, on the delete path
27
- * the original fix didn't touch). A 404 on the `output.id` itself is NOT an error here,
28
- * unlike `fetchLive`'s die — it means the object is already gone, which is exactly the
29
- * idempotent success `delete` is supposed to report (S11, alchemy-provider-standard).
30
- */
31
- destroy: (olds: Props, output: Attributes | undefined) => Effect.Effect<void, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessUnauthorized | import("./errors.ts").PaperlessUnavailable | import("./errors.ts").PaperlessValidation, import("./client.ts").PaperlessRequirements>;
21
+ } | undefined, E, PaperlessNgxOpContext>;
22
+ reconcile: (news: Props, output: Attributes | undefined) => Effect.Effect<Attributes, E, PaperlessNgxOpContext>;
23
+ /** ⛔ `output.id` FIRST, SAME SWITCH AS `fetchLive` (PR 163 re-review). A 404 on `output.id` is idempotent success, not an error, unlike `fetchLive`'s die. */
24
+ destroy: (olds: Props, output: Attributes | undefined) => Effect.Effect<void, E, PaperlessNgxOpContext>;
32
25
  };
33
- /** The five provider handlers for a spec'd Paperless taxonomy object, wired once. */
34
- export declare const matchingHandlers: <Props extends MatchingProps, Attributes extends {
26
+ /**
27
+ * The five provider handlers for a spec'd Paperless taxonomy object, wired once.
28
+ *
29
+ * ★ CREDENTIALS ARE PROVIDED HERE, ONCE, NOT BY EVERY CALLER — the same shape
30
+ * `netboxHandlers`/`forgejoHandlers` use. `CredentialsFromEnv` resolves `PAPERLESS_URL` /
31
+ * `PAPERLESS_TOKEN` on the calling fiber per request, so this closure keeps that laziness —
32
+ * nothing is captured at module load. ⛔ THE TOKEN IS NEVER A PROP.
33
+ */
34
+ export declare const matchingHandlers: <Props extends MatchingProps, Live extends {
35
+ readonly id: number;
36
+ readonly name: string;
37
+ }, Attributes extends {
35
38
  readonly id: number;
36
- }>(spec: MatchingSpec<Props, Attributes>) => {
39
+ }, E>(spec: MatchingSpec<Props, Live, Attributes, E>) => {
37
40
  /** ⚠️ `[]` — Paperless index endpoints return the whole estate; adoption stays explicit. */
38
41
  list: () => Effect.Effect<never[], never, never>;
39
42
  read: ({ olds }: {
40
43
  olds: Props;
41
- }) => Effect.Effect<Attributes | undefined, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessUnauthorized | import("./errors.ts").PaperlessUnavailable | import("./errors.ts").PaperlessValidation, import("./client.ts").PaperlessRequirements>;
44
+ }) => Effect.Effect<Attributes | undefined, E, import("effect/unstable/http/HttpClient").HttpClient>;
42
45
  diff: ({ news, output }: {
43
46
  news: Input<Props>;
44
47
  output: Attributes | undefined;
@@ -48,14 +51,14 @@ export declare const matchingHandlers: <Props extends MatchingProps, Attributes
48
51
  readonly action: 'noop';
49
52
  } | {
50
53
  readonly action: 'replace';
51
- } | undefined, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessUnauthorized | import("./errors.ts").PaperlessUnavailable | import("./errors.ts").PaperlessValidation, import("./client.ts").PaperlessRequirements>;
54
+ } | undefined, E, import("effect/unstable/http/HttpClient").HttpClient>;
52
55
  reconcile: ({ news, output }: {
53
56
  news: Props;
54
57
  output?: Attributes | undefined;
55
- }) => Effect.Effect<Attributes, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessError, import("./client.ts").PaperlessRequirements>;
58
+ }) => Effect.Effect<Attributes, E, import("effect/unstable/http/HttpClient").HttpClient>;
56
59
  delete: ({ olds, output }: {
57
60
  olds: Props;
58
61
  output?: Attributes | undefined;
59
- }) => Effect.Effect<void, import("./credentials.ts").PaperlessCredentialsError | import("./errors.ts").PaperlessUnauthorized | import("./errors.ts").PaperlessUnavailable | import("./errors.ts").PaperlessValidation, import("./client.ts").PaperlessRequirements>;
62
+ }) => Effect.Effect<void, E, import("effect/unstable/http/HttpClient").HttpClient>;
60
63
  };
61
64
  //# sourceMappingURL=matching.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/paperless/matching.ts"],"names":[],"mappings":"AAiDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAMxC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE,iOAAiO;AACjO,YAAY,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAM7B,eAAO,MAAM,kBAAkB,GAC7B,KAAK,SAAS,aAAa,EAC3B,UAAU,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,QAEpC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC;kBAOhB,KAAK;iBAuDX,KAAK,CAAC,KAAK,CAAC,UAAU,UAAU,GAAG,SAAS;yBAIZ,QAAQ;;yBAGP,MAAM;;yBAEjC,SAAS;;sBAIV,KAAK,UAAU,UAAU,GAAG,SAAS;IAqCvD;;;;;;;;;;;;OAYG;oBACa,KAAK,UAAU,UAAU,GAAG,SAAS;CAOxD,CAAC;AAEF,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,GAC3B,KAAK,SAAS,aAAa,EAC3B,UAAU,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,QAEpC,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC;IAInC,4FAA4F;IAC5F,IAAI;IACJ,IAAI,aAAa;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;IAIhC,IAAI,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;yBAnFlC,QAAQ;;yBAGP,MAAM;;yBAEjC,SAAS;;IAqF5B,SAAS,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;IAI9E,MAAM,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;CAG9E,CAAC"}
1
+ {"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/paperless/matching.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AACrF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEvE,iOAAiO;AACjO,YAAY,EACV,SAAS,EACT,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAM9D,eAAO,MAAM,kBAAkB,GAC7B,KAAK,SAAS,aAAa,EAC3B,IAAI,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC3D,UAAU,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAC1C,CAAC,QAEK,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;kBAyBzB,KAAK;iBAgDX,KAAK,CAAC,KAAK,CAAC,UAAU,UAAU,GAAG,SAAS;yBAIZ,QAAQ;;yBAGP,MAAM;;yBAEjC,SAAS;;sBAIV,KAAK,UAAU,UAAU,GAAG,SAAS;IA+BvD,8JAA8J;oBAC9I,KAAK,UAAU,UAAU,GAAG,SAAS;CAOxD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,KAAK,SAAS,aAAa,EAC3B,IAAI,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC3D,UAAU,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAC1C,CAAC,QAEK,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAM5C,4FAA4F;IAC5F,IAAI;IACJ,IAAI,aAAa;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE;IAMhC,IAAI,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;yBA9ElC,QAAQ;;yBAGP,MAAM;;yBAEjC,SAAS;;IA2E5B,SAAS,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;IAE9E,MAAM,qBAAqB;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE;CAG9E,CAAC"}
@@ -1,15 +1,21 @@
1
1
  /**
2
- * All four Paperless taxonomy providers, one credentials layer shared between them.
2
+ * All four Paperless taxonomy providers.
3
3
  *
4
4
  * Layer.mergeAll(paperlessProviders(), …the stack's other providers)
5
5
  *
6
6
  * ⚠️ `HttpClient.HttpClient` IS NOT BUNDLED HERE, and that follows `../netbox/index.ts` and
7
- * `../forgejo/client.ts`'s own precedent (its header: "the idiom Alchemy's own providers
8
- * follow — `Hetzner/Providers.ts` builds on `FetchHttpClient.layer`") rather than diverging
9
- * from it: the transport is the consuming STACK's choice (`FetchHttpClient.layer` in
10
- * production, a fake `HttpClient` in a test), not a house default a provider file should pin.
7
+ * `../forgejo/client.ts`'s own precedent: the transport is the consuming STACK's choice
8
+ * (`FetchHttpClient.layer` in production, a fake `HttpClient` in a test), not a house default a
9
+ * provider file should pin.
10
+ *
11
+ * 🔴 NO `credentials` PARAMETER ANY MORE (2026-09-24, the `@distilled.cloud/paperless-ngx`
12
+ * migration — see `matching.ts`'s header). Each of the four `xxxProvider()`s now bakes in
13
+ * `CredentialsFromEnv` itself, the same way `netboxHandlers`/`forgejoHandlers` do — there is no
14
+ * longer a layer for this file to merge in or accept an override for. Nothing in this estate
15
+ * called `paperlessProviders(customLayer)` (measured 2026-09-24: no tray repo declares a
16
+ * Paperless resource at all — grep across `homeflare-landscape`'s tray repos' `origin/main`),
17
+ * so this is an uneventful simplification, not a behaviour change for anything live.
11
18
  */
12
19
  import * as Layer from 'effect/Layer';
13
- import { type PaperlessCredentials } from './credentials.ts';
14
- export declare const paperlessProviders: (credentials?: Layer.Layer<PaperlessCredentials>) => Layer.Layer<import("alchemy").Provider<import("./custom-field.ts").CustomField> | import("alchemy").Provider<import("./document-type.ts").DocumentType> | import("alchemy").Provider<import("./storage-path.ts").StoragePath> | import("alchemy").Provider<import("./tag.ts").Tag>, never, import("effect/unstable/http/HttpClient").HttpClient>;
20
+ export declare const paperlessProviders: () => Layer.Layer<import("alchemy").Provider<import("./custom-field.ts").CustomField> | import("alchemy").Provider<import("./document-type.ts").DocumentType> | import("alchemy").Provider<import("./storage-path.ts").StoragePath> | import("alchemy").Provider<import("./tag.ts").Tag>, never, import("effect/unstable/http/HttpClient").HttpClient>;
15
21
  //# sourceMappingURL=providers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/paperless/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAE,KAAK,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAI/E,eAAO,MAAM,kBAAkB,iBAChB,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,qVAOZ,CAAC"}
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/paperless/providers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAMtC,eAAO,MAAM,kBAAkB,wVAM5B,CAAC"}
@@ -1,14 +1,18 @@
1
1
  /**
2
2
  * `Paperless.StoragePath` — a Paperless-ngx storage path template, create-or-update and never
3
- * deleted. Same shape as `document-type.ts` plus the vendor-required `path` template string.
3
+ * deleted. Same shape as `document-type.ts` plus the vendor-required `path` template string; see
4
+ * `tag.ts`'s header for the 2026-09-24 transport migration this file follows exactly.
4
5
  */
5
6
  import { Resource } from 'alchemy';
6
7
  import * as Provider from 'alchemy/Provider';
8
+ import * as storagePaths from '@distilled.cloud/paperless-ngx/storage_paths';
9
+ import * as Effect from 'effect/Effect';
7
10
  import type { PaperlessStoragePathRequest } from './generated/types/storage-paths.ts';
8
- import { type MatchingProps, type MatchingRequirements } from './matching.ts';
9
- export interface StoragePathProps extends MatchingProps {
11
+ import { type MatchingRequirements, type MatchingSpec } from './matching.ts';
12
+ export interface StoragePathProps {
10
13
  /** ⚠️ maxLength 128 (generated constraint table). The locate key. */
11
14
  name: string;
15
+ owner?: number;
12
16
  /** ⚠️ minLength 1 (generated table). Paperless's storage-path template syntax, e.g. `{correspondent}/{title}`. */
13
17
  path: string;
14
18
  /** ⚠️ maxLength 256. */
@@ -28,5 +32,31 @@ export interface StoragePathAttributes {
28
32
  export interface StoragePath extends Resource<'Paperless.StoragePath', StoragePathProps, StoragePathAttributes, never, MatchingRequirements> {
29
33
  }
30
34
  export declare const StoragePath: import("alchemy").ResourceClass<StoragePath>;
31
- export declare const StoragePathProvider: () => import("effect/Layer").Layer<Provider.Provider<StoragePath>, never, import("./client.ts").PaperlessRequirements>;
35
+ /** ★ Exported for direct testing — see tag.ts's own note on this seam. */
36
+ export declare const spec: MatchingSpec<StoragePathProps, storagePaths.StoragePath, StoragePathAttributes, storagePaths.CreateStoragePathError | storagePaths.GetStoragePathError | storagePaths.ListStoragePathsError | storagePaths.UpdateStoragePathsPartialError | storagePaths.StoragePathsDestroyError>;
37
+ export declare const handlers: {
38
+ list: () => Effect.Effect<never[], never, never>;
39
+ read: ({ olds }: {
40
+ olds: StoragePathProps;
41
+ }) => Effect.Effect<StoragePathAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | storagePaths.BadRequest | import("@distilled.cloud/caddy").ConfigError | storagePaths.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | storagePaths.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
42
+ diff: ({ news, output }: {
43
+ news: import("alchemy").Input<StoragePathProps>;
44
+ output: StoragePathAttributes | undefined;
45
+ }) => Effect.Effect<{
46
+ readonly action: 'update';
47
+ } | {
48
+ readonly action: 'noop';
49
+ } | {
50
+ readonly action: 'replace';
51
+ } | undefined, import("@distilled.cloud/caddy").BadGateway | storagePaths.BadRequest | import("@distilled.cloud/caddy").ConfigError | storagePaths.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | storagePaths.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
52
+ reconcile: ({ news, output }: {
53
+ news: StoragePathProps;
54
+ output?: StoragePathAttributes | undefined;
55
+ }) => Effect.Effect<StoragePathAttributes, import("@distilled.cloud/caddy").BadGateway | storagePaths.BadRequest | import("@distilled.cloud/caddy").ConfigError | storagePaths.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | storagePaths.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
56
+ delete: ({ olds, output }: {
57
+ olds: StoragePathProps;
58
+ output?: StoragePathAttributes | undefined;
59
+ }) => Effect.Effect<void, import("@distilled.cloud/caddy").BadGateway | storagePaths.BadRequest | import("@distilled.cloud/caddy").ConfigError | storagePaths.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | storagePaths.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
60
+ };
61
+ export declare const StoragePathProvider: () => import("effect/Layer").Layer<Provider.Provider<StoragePath>, never, import("effect/unstable/http/HttpClient").HttpClient>;
32
62
  //# sourceMappingURL=storage-path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage-path.d.ts","sourceRoot":"","sources":["../../src/paperless/storage-path.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAoB,MAAM,eAAe,CAAC;AAEhG,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACrD,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,kHAAkH;IAClH,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,2BAA2B,CAAC,oBAAoB,CAAC,CAAC;IACtE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,EACL,oBAAoB,CACrB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAEtB,CAAC;AAmCH,eAAO,MAAM,mBAAmB,wHACiD,CAAC"}
1
+ {"version":3,"file":"storage-path.d.ts","sourceRoot":"","sources":["../../src/paperless/storage-path.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,YAAY,MAAM,8CAA8C,CAAC;AAC7E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kHAAkH;IAClH,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,2BAA2B,CAAC,oBAAoB,CAAC,CAAC;IACtE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,EACrB,KAAK,EACL,oBAAoB,CACrB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAEtB,CAAC;AAEH,0EAA0E;AAC1E,eAAO,MAAM,IAAI,EAAE,YAAY,CAC7B,gBAAgB,EAChB,YAAY,CAAC,WAAW,EACxB,qBAAqB,EACnB,YAAY,CAAC,sBAAsB,GACnC,YAAY,CAAC,mBAAmB,GAChC,YAAY,CAAC,qBAAqB,GAClC,YAAY,CAAC,8BAA8B,GAC3C,YAAY,CAAC,wBAAwB,CAyCxC,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;CAAyB,CAAC;AAE/C,eAAO,MAAM,mBAAmB,iIACiD,CAAC"}
@@ -2,22 +2,26 @@
2
2
  * `Paperless.Tag` — a Paperless-ngx tag, create-or-update and never deleted by default.
3
3
  *
4
4
  * ★ `matchingAlgorithm` AND THE OTHER ENUM-SHAPED FIELDS ARE INDEXED OFF THE GENERATED REQUEST
5
- * TYPE (`PaperlessTagRequest['matching_algorithm']`), NEVER RETYPED. The literal union `0 | 1 |
6
- * … | 6` comes from `codegen/paperless.ts`'s reading of the vendor's own `MatchingAlgorithm`
7
- * enum — copying it by hand here would be exactly the guess `schema-provenance` doctrine
8
- * forbids, and a vendor that adds a seventh algorithm would leave this type silently stale.
5
+ * TYPE (`PaperlessTagRequest['matching_algorithm']`), NEVER RETYPED — see this family's header
6
+ * in `docs/paperless.md`. Unchanged by the 2026-09-24 transport migration below: that generated
7
+ * table is `codegen/paperless.ts`'s own concern, not `@distilled.cloud/paperless-ngx`'s.
9
8
  *
10
- * ⛔ NO CREDENTIAL IS A PROP. `PAPERLESS_URL`/`PAPERLESS_TOKEN` come from `credentials.ts`.
9
+ * ⛔ NO CREDENTIAL IS A PROP. `PAPERLESS_URL`/`PAPERLESS_TOKEN` come from
10
+ * `@distilled.cloud/paperless-ngx`'s `CredentialsFromEnv` (matching.ts), the same two variable
11
+ * names the retired hand-rolled `credentials.ts` read.
11
12
  * ⛔ `defaultRemovalPolicy: 'retain'` — the reconciler this replaces never deletes taxonomy, and
12
13
  * a tag's id is referenced by every document it is attached to.
13
14
  */
14
15
  import { Resource } from 'alchemy';
15
16
  import * as Provider from 'alchemy/Provider';
17
+ import * as tags from '@distilled.cloud/paperless-ngx/tags';
18
+ import * as Effect from 'effect/Effect';
16
19
  import type { PaperlessTagRequest } from './generated/types/tags.ts';
17
- import { type MatchingProps, type MatchingRequirements } from './matching.ts';
18
- export interface TagProps extends MatchingProps {
20
+ import { type MatchingRequirements, type MatchingSpec } from './matching.ts';
21
+ export interface TagProps {
19
22
  /** ⚠️ maxLength 128 (generated constraint table). The locate key — see matching.ts's header. */
20
23
  name: string;
24
+ owner?: number;
21
25
  /** ⚠️ minLength 1, maxLength 7 (a CSS hex color, generated table doesn't enforce the `#`). */
22
26
  color?: string;
23
27
  /** ⚠️ maxLength 256. The text or pattern documents are matched against. */
@@ -43,5 +47,36 @@ export interface TagAttributes {
43
47
  export interface Tag extends Resource<'Paperless.Tag', TagProps, TagAttributes, never, MatchingRequirements> {
44
48
  }
45
49
  export declare const Tag: import("alchemy").ResourceClass<Tag>;
46
- export declare const TagProvider: () => import("effect/Layer").Layer<Provider.Provider<Tag>, never, import("./client.ts").PaperlessRequirements>;
50
+ /**
51
+ * ★ EXPORTED, NOT JUST PASSED INLINE — so a test can call `matchingOperations(spec)` directly
52
+ * (tag.test.ts does), against an explicit fake `Credentials` layer, without touching
53
+ * `matchingHandlers`'s baked-in `CredentialsFromEnv` — the same seam `../forgejo/repository.ts`
54
+ * and `../netbox/prefix.ts` use.
55
+ */
56
+ export declare const spec: MatchingSpec<TagProps, tags.Tag, TagAttributes, tags.CreateTagError | tags.GetTagError | tags.ListTagsError | tags.UpdateTagsPartialError | tags.TagsDestroyError>;
57
+ export declare const handlers: {
58
+ list: () => Effect.Effect<never[], never, never>;
59
+ read: ({ olds }: {
60
+ olds: TagProps;
61
+ }) => Effect.Effect<TagAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | tags.BadRequest | import("@distilled.cloud/caddy").ConfigError | tags.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | tags.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
62
+ diff: ({ news, output }: {
63
+ news: import("alchemy").Input<TagProps>;
64
+ output: TagAttributes | undefined;
65
+ }) => Effect.Effect<{
66
+ readonly action: 'update';
67
+ } | {
68
+ readonly action: 'noop';
69
+ } | {
70
+ readonly action: 'replace';
71
+ } | undefined, import("@distilled.cloud/caddy").BadGateway | tags.BadRequest | import("@distilled.cloud/caddy").ConfigError | tags.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | tags.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
72
+ reconcile: ({ news, output }: {
73
+ news: TagProps;
74
+ output?: TagAttributes | undefined;
75
+ }) => Effect.Effect<TagAttributes, import("@distilled.cloud/caddy").BadGateway | tags.BadRequest | import("@distilled.cloud/caddy").ConfigError | tags.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | tags.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
76
+ delete: ({ olds, output }: {
77
+ olds: TagProps;
78
+ output?: TagAttributes | undefined;
79
+ }) => Effect.Effect<void, import("@distilled.cloud/caddy").BadGateway | tags.BadRequest | import("@distilled.cloud/caddy").ConfigError | tags.Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | tags.NotFound | import("@distilled.cloud/paperless-ngx/Errors").PaperlessNgxParseError | import("@distilled.cloud/caddy").ServiceUnavailable | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/paperless-ngx/Errors").UnknownPaperlessNgxError, import("effect/unstable/http/HttpClient").HttpClient>;
80
+ };
81
+ export declare const TagProvider: () => import("effect/Layer").Layer<Provider.Provider<Tag>, never, import("effect/unstable/http/HttpClient").HttpClient>;
47
82
  //# sourceMappingURL=tag.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/paperless/tag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,oBAAoB,EAAoB,MAAM,eAAe,CAAC;AAEhG,MAAM,WAAW,QAAS,SAAQ,aAAa;IAC7C,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAC;IACb,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,GAAI,SAAQ,QAAQ,CACnC,eAAe,EACf,QAAQ,EACR,aAAa,EACb,KAAK,EACL,oBAAoB,CACrB;CAAG;AAEJ,eAAO,MAAM,GAAG,sCAAqE,CAAC;AAoCtF,eAAO,MAAM,WAAW,gHAAwE,CAAC"}
1
+ {"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/paperless/tag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,IAAI,MAAM,qCAAqC,CAAC;AAC5D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EAElB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,QAAQ;IACvB,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,GAAI,SAAQ,QAAQ,CACnC,eAAe,EACf,QAAQ,EACR,aAAa,EACb,KAAK,EACL,oBAAoB,CACrB;CAAG;AAEJ,eAAO,MAAM,GAAG,sCAAqE,CAAC;AAEtF;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAAE,YAAY,CAC7B,QAAQ,EACR,IAAI,CAAC,GAAG,EACR,aAAa,EACX,IAAI,CAAC,cAAc,GACnB,IAAI,CAAC,WAAW,GAChB,IAAI,CAAC,aAAa,GAClB,IAAI,CAAC,sBAAsB,GAC3B,IAAI,CAAC,gBAAgB,CAsCxB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;CAAyB,CAAC;AAE/C,eAAO,MAAM,WAAW,yHAAwE,CAAC"}
@@ -6,39 +6,52 @@
6
6
  * {path, user|group|token, role} exists. That is what makes those four families worth declaring,
7
7
  * and why the grants that let OpenBao mint a PVE token today are only clicks somebody made once.
8
8
  *
9
- * ⛔ THE ONE FAMILY THAT DOES NOT FIT `pveOperations` AS WRITTEN, AND THE MISFIT IS MEASURED. The
9
+ * ⛔ THE ONE FAMILY THAT DOES NOT FIT A GENERIC PATH+FORM SHAPE, AND THE MISFIT IS MEASURED. The
10
10
  * cluster's own schema — `/pve-docs/api-viewer/apidoc.js`, read unauthenticated 2026-09-13 —
11
11
  * lists exactly TWO methods on `/access/acl`: GET and PUT. There is no DELETE (it answers
12
- * "Method 'DELETE /access/acl' not implemented") and, less famously, NO POST either. So create
13
- * and update are the SAME call, `PUT /access/acl`, and removal is that PUT with `delete=1` —
14
- * which is why `delete` below does not use `ops.destroy`.
15
- * ⚠️ THE REAL FIX BELONGS IN `resource.ts`: give `PveSpec` a `deleteForm` and the method to go
16
- * with it, and this override disappears. Until then it is local and loud — do not "restore
17
- * symmetry" by pointing `delete` at `ops.destroy`, which reports every removal as a 501 while
18
- * the grant stays exactly where it was.
12
+ * "Method 'DELETE /access/acl' not implemented") and, less famously, NO POST either — which is
13
+ * why `@distilled.cloud/proxmox`'s generator, reading the same schema, emits `listAccessAcl` and
14
+ * `putAccessAcl` and NOTHING ELSE for this path. So create and update are the SAME call, `PUT
15
+ * /access/acl`, and removal is that PUT with `delete=1` — there is no `destroyAccessAcl` to call.
19
16
  *
20
17
  * ⛔ A SINGLE GRANT HAS NO URL OF ITS OWN. `GET /access/acl` answers ONE FLAT LIST for the whole
21
- * cluster, so identity is the tuple (path, type, ugid, roleid), matched client-side in
22
- * `attributes` below. Two resources declaring the SAME tuple are the SAME grant — Alchemy sees
23
- * two resource ids, not one collision — and deleting either takes the access away from both,
24
- * the same hazard as two guests declaring one vmid.
18
+ * cluster, so identity is the tuple (path, type, ugid, roleid), matched client-side in `find`
19
+ * below. Two resources declaring the SAME tuple are the SAME grant — Alchemy sees two resource
20
+ * ids, not one collision — and deleting either takes the access away from both, the same hazard
21
+ * as two guests declaring one vmid.
25
22
  *
26
23
  * ⛔ AND THAT LIST IS FILTERED BY WHO IS ASKING. The schema's own words for GET: "The returned list
27
24
  * is restricted to objects where you have rights to modify permissions." A credential that can
28
25
  * read the cluster but not modify permissions is answered `[]` — not a 403, not an error — so
29
26
  * the mount's `read` role needs permission-modify rights on the declared path exactly as
30
- * `provision` does. Work reported on a grant that is plainly there means that role is too narrow.
27
+ * `provision` does (below, `listAcl` reads with the `provision` role for this reason). Work
28
+ * reported on a grant that is plainly there means that role is too narrow.
29
+ *
30
+ * ★ MIGRATED OFF `client.ts`'s generic `pve()` ONTO `@distilled.cloud/proxmox`'s typed
31
+ * `access.listAccessAcl`/`access.putAccessAcl` (2026-09-23, decision 43's proxmox walk-down,
32
+ * the sub-area's first resource — ACL was already the misfit `pveOperations` could not cover
33
+ * cleanly, which is exactly why it goes first). `distilled-pve.ts`'s `runPve` replaces `pve()`:
34
+ * same lease reuse (lease-cache.ts), same cluster-member failover (members.ts), now handing the
35
+ * request itself to the SDK instead of a hand-assembled `HttpClientRequest`.
36
+ * ⛔ ONE DEAD BRANCH REMOVED, NOT PRESERVED: the old code's generic factory POSTed on a "live
37
+ * undefined" read, which its own header called unreachable on a healthy cluster and
38
+ * documented as MISLEADING — PVE has no POST here, so that 501 said nothing about the real
39
+ * failure. `@distilled.cloud/proxmox` has no `createAccessAcl` at all (the vendor schema has
40
+ * no POST to generate one from), so there is nothing to call that way. `reconcile` below
41
+ * always PUTs instead — the only write PVE actually implements for this path — so a read that
42
+ * genuinely failed now surfaces its REAL cause (a typed error, or `PveClusterExhausted`)
43
+ * rather than a confusing 501 from a verb that was never there.
31
44
  */
32
45
  import { Resource } from 'alchemy';
33
46
  import * as Provider from 'alchemy/Provider';
34
- import { type PveRequirements, type WithTarget } from './resource.ts';
47
+ import type { PveRequirements, WithTarget } from './resource-spec.ts';
35
48
  /** PVE's three kinds of subject. The read answers this word; the write wants its plural. */
36
49
  export type AclSubjectType = 'user' | 'group' | 'token';
37
50
  export interface AclProps extends WithTarget {
38
51
  /**
39
52
  * The PVE object path the grant is ON — `/`, `/pool/lab`, `/vms/101`, `/storage/local-zfs`.
40
- * ⚠️ NOT THE API PATH: `spec.path` below is the endpoint (`access/acl`). PVE's API overloads the
41
- * word, so this file does too rather than renaming a field the cluster calls `path`.
53
+ * ⚠️ NOT THE API PATH — the endpoint is fixed (`access/acl`). PVE's API overloads the word,
54
+ * so this file does too rather than renaming a field the cluster calls `path`.
42
55
  */
43
56
  path: string;
44
57
  /** Which kind of subject `ugid` names. Identity: changing it is a different grant. */
@@ -56,13 +69,7 @@ export interface AclAttributes {
56
69
  ugid: string;
57
70
  roleid: string;
58
71
  propagate: boolean;
59
- /**
60
- * ⛔ PRESENCE AS AN ATTRIBUTE, AND IT IS WHAT MAKES THE FACTORY WORK HERE. `attributes` never
61
- * returns undefined: if it did, `reconcile` would take the create branch and POST to
62
- * `access/acl`, which PVE does not implement. Present-but-unbound sends every write down the
63
- * PUT branch instead, the only branch PVE has. The cost: the factory's read-back guard cannot
64
- * fire, so `reconcile` below re-checks this field itself and dies with the same honesty.
65
- */
72
+ /** Presence, so a PUT-only family can tell "matches" from "does not exist yet" — see below. */
66
73
  bound: boolean;
67
74
  }
68
75
  export interface ProxmoxAcl extends Resource<'Proxmox.Acl', AclProps, AclAttributes, never, PveRequirements> {
@@ -1 +1 @@
1
- {"version":3,"file":"acl.d.ts","sourceRoot":"","sources":["../../src/proxmox/acl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAiB,MAAM,eAAe,CAAC;AAErF,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,IAAI,EAAE,cAAc,CAAC;IACrB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,QAAQ,EACR,aAAa,EACb,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAqH9D,eAAO,MAAM,kBAAkB,gIAqE5B,CAAC"}
1
+ {"version":3,"file":"acl.d.ts","sourceRoot":"","sources":["../../src/proxmox/acl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGtE,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,IAAI,EAAE,cAAc,CAAC;IACrB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,+FAA+F;IAC/F,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,QAAQ,EACR,aAAa,EACb,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAuF9D,eAAO,MAAM,kBAAkB,gIAoE5B,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Running one `@distilled.cloud/proxmox` typed operation the way `client.ts`'s `pve()` ran a raw
3
+ * HTTP call — same credential lease reuse (lease-cache.ts) and the same cluster-member failover
4
+ * safety rule (members.ts), now handing the request itself to the SDK instead of building one.
5
+ *
6
+ * ★ THIS IS THE SEAM A DISTILLED-BACKED FAMILY CALLS INSTEAD OF `pve()`. `client.ts` stays for
7
+ * every family not yet migrated — see acl.ts, the first one, for what a migrated family looks
8
+ * like. A family migrates by calling its own `@distilled.cloud/proxmox/<segment>` typed
9
+ * operations through `runPve` below, never through a generic method+path+form call: that is
10
+ * what "no hand-rolled client" means in practice (upstream Alchemy PR 1425).
11
+ *
12
+ * ⚠️ THE WHOLE OPERATION IS RE-RUN PER MEMBER, NOT JUST ONE HTTP CALL. `executeOnCluster` in
13
+ * members.ts retries a single already-built `HttpClientRequest`; a distilled operation builds
14
+ * its OWN request internally from whatever `Credentials` it is given, so there is no request to
15
+ * hand between attempts. Failover here instead re-provides `Credentials` with the next member's
16
+ * `apiBaseUrl` and re-runs the same operation value. This is safe under the identical rule
17
+ * `executeOnCluster` documents and members.ts's classifiers still enforce: a write may repeat
18
+ * only on a PROVABLY pre-send transport failure (connection refused, DNS, a refused
19
+ * certificate) — never on a timeout after connect, and never on an HTTP answer of any kind,
20
+ * because an answer (even a typed error the SDK decoded) proves the request reached a live
21
+ * member and must not be sent again elsewhere. Reads may fail over on any transport failure.
22
+ *
23
+ * ⛔ A TYPED ANSWER-ERROR IS NEVER A REASON TO TRY ANOTHER MEMBER. `Forbidden`,
24
+ * `ParameterVerificationFailed`, `ClusterNodeUnreachable`, … all mean the request reached a
25
+ * member and that member answered — `isTransportFailure`/`isPreSendTransport` (members.ts)
26
+ * return `false` for all of them, exactly as they do for the `HttpClientResponse` case in
27
+ * `executeOnCluster`, since neither function inspects anything but a transport-level
28
+ * `HttpClientError`. Such an error propagates from here UNCHANGED — not wrapped, not retried —
29
+ * which is what lets a caller `catchTag` it directly.
30
+ *
31
+ * TRAP FOUND WHILE WRITING THE FAILOVER TEST: `Retry.none` on every attempt, and it is not
32
+ * optional. `@distilled.cloud/core`'s DEFAULT policy retries any error in its `ServerError`
33
+ * category automatically, with no caller opt-in (protocol.ts's own header names the mechanism:
34
+ * `core/category.ts`'s `isTransientError` via `makeDefault`) -- and that category covers
35
+ * transport failures too, not just 5xx answers: MEASURED -- a plain `listAccessAcl({})` against
36
+ * a member that refuses the connection hung past a 5-second test timeout, backing off inside
37
+ * the SDK before this file's own failover loop ever saw a failure to classify. Left enabled, a
38
+ * WRITE could be resent to the SAME member several times before `runPveWith` gets a result at
39
+ * all -- silently reintroducing, inside one member, the exact risk `executeOnCluster`
40
+ * (members.ts) exists to rule out across members ("a request that may have reached a member
41
+ * must not be sent again"). The hand-rolled client never auto-retried anything; member failover
42
+ * was its only resilience. `Retry.none` below keeps that property true here too.
43
+ *
44
+ * ⛔ GAP FOUND ON REVIEW, FIXED 2026-09-24: `Retry.none` only stops the SDK re-sending to the SAME
45
+ * member -- it added no bound on how long ONE attempt may wait. A member that accepts the TCP
46
+ * connection but never answers hung this whole function forever, since the for-loop below never
47
+ * got a result to classify and so never reached a healthy member. `MEMBER_TIMEOUT` (members.ts,
48
+ * shared with `client.ts`'s `executeOnCluster`) now bounds each attempt; `isTransportFailure`
49
+ * treats the resulting `Cause.TimeoutError` as failover-eligible for a read, and
50
+ * `isPreSendTransport` still refuses it for a write, for the same reason a post-send timeout
51
+ * always was refused.
52
+ */
53
+ import type * as Cause from 'effect/Cause';
54
+ import type * as Duration from 'effect/Duration';
55
+ import * as Effect from 'effect/Effect';
56
+ import type * as HttpClient from 'effect/unstable/http/HttpClient';
57
+ import type { ProxmoxOpContext } from '@distilled.cloud/proxmox/Protocol';
58
+ import type { PveCredential, PveRole, PveTarget } from './credentials.ts';
59
+ import { type MemberAttempt } from './members.ts';
60
+ /** Every member answered nothing usable — the direct successor to `client.ts`'s `clusterExhausted`. */
61
+ export declare class PveClusterExhausted extends Error {
62
+ readonly attempts: readonly MemberAttempt[];
63
+ constructor(attempts: readonly MemberAttempt[]);
64
+ }
65
+ /**
66
+ * Run `op` against `target`'s cluster on an ALREADY-HELD credential — the direct successor to
67
+ * `client.ts`'s `pveWith`, for a caller reasoning about identity rather than cost (or a test that
68
+ * wants a fixed, explicit credential rather than a live OpenBao mint — see distilled-pve.test.ts).
69
+ *
70
+ * @param isWrite Whether `op` may have a side effect once sent — decides which transport
71
+ * failures may retry on the next member. Pass `true` for anything that is not a plain read.
72
+ * @param timeout Bound on ONE member's attempt — defaults to `MEMBER_TIMEOUT` (members.ts). A
73
+ * test passes a short one to prove failover/bounding without waiting out the real bound;
74
+ * production code never overrides it. A member that answers past this is failed over (a read)
75
+ * or failed outright (a write, since the request may already have landed) — see
76
+ * `isTransportFailure`/`isPreSendTransport`.
77
+ */
78
+ export declare const runPveWith: <A, E>(target: PveTarget, credential: PveCredential, isWrite: boolean, op: Effect.Effect<A, E, ProxmoxOpContext>, timeout?: Duration.Input) => Effect.Effect<A, E | Cause.TimeoutError | PveClusterExhausted, HttpClient.HttpClient>;
79
+ /**
80
+ * `runPveWith`, minting/reusing a `role` lease exactly as `pve()` did — the seam a migrated
81
+ * resource file calls.
82
+ *
83
+ * ⚠️ `| Error` IN THE RETURN TYPE IS `leased()`'s OWN FAILURE, NOT A NEW ONE THIS FILE ADDS.
84
+ * `credentials.ts`'s `mint` fails with a plain `Error` (an OpenBao refusal — sealed, denied, no
85
+ * such role) and was never typed more narrowly there; `pve()` carried the same untyped
86
+ * possibility before this file existed, just without a signature that said so.
87
+ */
88
+ export declare const runPve: <A, E>(target: PveTarget, role: PveRole, isWrite: boolean, op: Effect.Effect<A, E, ProxmoxOpContext>) => Effect.Effect<A, E | Cause.TimeoutError | PveClusterExhausted | Error, HttpClient.HttpClient>;
89
+ //# sourceMappingURL=distilled-pve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distilled-pve.d.ts","sourceRoot":"","sources":["../../src/proxmox/distilled-pve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE1E,OAAO,EAEL,KAAK,aAAa,EAOnB,MAAM,cAAc,CAAC;AAEtB,uGAAuG;AACvG,qBAAa,mBAAoB,SAAQ,KAAK;IAChC,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE;IAAvD,YAAqB,QAAQ,EAAE,SAAS,aAAa,EAAE,EAGtD;CACF;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,UACrB,SAAS,cACL,aAAa,WAChB,OAAO,MACZ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAAC,YAChC,QAAQ,CAAC,KAAK,KACtB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,mBAAmB,EAAE,UAAU,CAAC,UAAU,CA0BnF,CAAC;AAEL;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,CAAC,UACjB,SAAS,QACX,OAAO,WACJ,OAAO,MACZ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAAC,KACxC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,mBAAmB,GAAG,KAAK,EAAE,UAAU,CAAC,UAAU,CAI3F,CAAC"}