@cosmicdrift/kumiko-bundled-features 0.352.0 → 0.354.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/dist/agent-tools/agent-doc-lint.d.ts +2 -0
  2. package/dist/agent-tools/agent-doc-lint.js +61 -1
  3. package/dist/agent-tools/agent-manifest.d.ts +1 -0
  4. package/dist/agent-tools/agent-manifest.js +17 -5
  5. package/dist/agent-tools/feature.js +7 -2
  6. package/dist/agent-tools/index.d.ts +1 -1
  7. package/dist/agent-tools/index.js +1 -1
  8. package/dist/agent-tools/manifest-deny-qns.d.ts +3 -0
  9. package/dist/agent-tools/manifest-deny-qns.js +17 -0
  10. package/dist/agent-tools/tool-catalog.d.ts +2 -1
  11. package/dist/agent-tools/tool-catalog.js +4 -1
  12. package/dist/agent-tools/tool-dispatch.js +1 -1
  13. package/dist/audit/handlers/list.query.js +13 -8
  14. package/dist/auth-email-password/handlers/change-password.write.js +1 -0
  15. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +2 -2
  16. package/dist/auth-email-password/handlers/invite-accept.write.js +2 -2
  17. package/dist/auth-email-password/handlers/invite-create.write.js +17 -0
  18. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +4 -1
  19. package/dist/auth-email-password/handlers/login.write.js +1 -0
  20. package/dist/auth-email-password/handlers/reset-password.write.js +1 -0
  21. package/dist/auth-email-password/handlers/signup-confirm.write.js +6 -4
  22. package/dist/auth-email-password/handlers/signup-request.write.js +51 -77
  23. package/dist/auth-email-password/handlers/token-request-handler.js +1 -0
  24. package/dist/auth-email-password/handlers/verify-email.write.js +1 -0
  25. package/dist/auth-email-password/index.d.ts +2 -0
  26. package/dist/auth-email-password/index.js +2 -0
  27. package/dist/auth-email-password/seeding.d.ts +2 -0
  28. package/dist/auth-email-password/seeding.js +30 -8
  29. package/dist/auth-email-password/signup-activation.d.ts +24 -0
  30. package/dist/auth-email-password/signup-activation.js +41 -0
  31. package/dist/auth-email-password/signup-token-store.d.ts +5 -0
  32. package/dist/auth-email-password/signup-token-store.js +8 -3
  33. package/dist/auth-email-password/web/auth-gate.d.ts +2 -2
  34. package/dist/auth-email-password/web/auth-gate.js +5 -5
  35. package/dist/auth-email-password/web/auth-redirect.d.ts +1 -0
  36. package/dist/auth-email-password/web/auth-redirect.js +14 -0
  37. package/dist/auth-email-password/web/login-screen.js +2 -2
  38. package/dist/auth-email-password/web/user-menu.js +1 -1
  39. package/dist/auth-mfa/feature.js +5 -0
  40. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -0
  41. package/dist/auth-mfa/handlers/verify.write.js +1 -0
  42. package/dist/auth-mfa/schema/user-mfa.d.ts +6 -0
  43. package/dist/auth-mfa/screens.js +2 -2
  44. package/dist/auth-mfa/web/mfa-recovery-codes-reveal.js +1 -1
  45. package/dist/auth-mfa/web/mfa-setup-preauth-screen.d.ts +1 -1
  46. package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +3 -3
  47. package/dist/auth-mfa/web/mfa-verify-screen.d.ts +1 -1
  48. package/dist/auth-mfa/web/mfa-verify-screen.js +1 -1
  49. package/dist/billing-foundation/billing-info-query.d.ts +5 -2
  50. package/dist/billing-foundation/checkout-core.d.ts +7 -0
  51. package/dist/billing-foundation/checkout-core.js +7 -2
  52. package/dist/billing-foundation/entities.d.ts +8 -0
  53. package/dist/billing-foundation/handlers/start-plan-checkout.write.js +7 -1
  54. package/dist/billing-foundation/projection.d.ts +8 -0
  55. package/dist/cap-counter/entity.d.ts +1 -0
  56. package/dist/cap-overview/access.js +2 -9
  57. package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -2
  58. package/dist/cap-overview/handlers/tenant-options.query.js +4 -5
  59. package/dist/channel-in-app/in-app-channel.js +1 -1
  60. package/dist/channel-in-app/tables.js +4 -2
  61. package/dist/compliance-profiles/schema/profile-selection.d.ts +10 -8
  62. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +2 -4
  63. package/dist/config/handlers/values.query.d.ts +3 -1
  64. package/dist/config/handlers/values.query.js +7 -2
  65. package/dist/config/table.d.ts +6 -0
  66. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -0
  67. package/dist/crypto-shredding/handlers/forget-subject.write.js +110 -61
  68. package/dist/custom-fields/entity.d.ts +4 -0
  69. package/dist/data-retention/schema/tenant-retention-override.d.ts +4 -0
  70. package/dist/delivery/db/queries/address-opt-outs.d.ts +3 -1
  71. package/dist/delivery/db/queries/address-opt-outs.js +12 -7
  72. package/dist/delivery/delivery-service.js +60 -12
  73. package/dist/delivery/public-names.js +1 -1
  74. package/dist/delivery/tables.d.ts +6 -0
  75. package/dist/delivery/unsubscribe.js +66 -14
  76. package/dist/document-ingest-foundation/entity.d.ts +4 -0
  77. package/dist/feature-toggles/feature.js +2 -3
  78. package/dist/feature-toggles/toggle-runtime.d.ts +5 -1
  79. package/dist/feature-toggles/toggle-runtime.js +30 -6
  80. package/dist/feature-toggles/toggle-sync-signal.d.ts +3 -2
  81. package/dist/feature-toggles/toggle-sync-signal.js +29 -10
  82. package/dist/file-derivatives/handlers/public-variant.query.d.ts +1 -0
  83. package/dist/file-derivatives/handlers/public-variant.query.js +7 -1
  84. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +5 -0
  85. package/dist/files-tenant-data/hooks.js +61 -24
  86. package/dist/folders/entity.d.ts +8 -0
  87. package/dist/folders/feature.js +2 -10
  88. package/dist/folders/handlers/delete-folder.write.js +31 -4
  89. package/dist/form-draft/db/queries/cleanup.d.ts +1 -1
  90. package/dist/form-draft/db/queries/cleanup.js +4 -3
  91. package/dist/form-draft/entity.d.ts +2 -0
  92. package/dist/form-draft/handlers/cleanup.job.d.ts +5 -1
  93. package/dist/form-draft/handlers/cleanup.job.js +11 -5
  94. package/dist/foundation-shared/index.d.ts +1 -1
  95. package/dist/foundation-shared/index.js +1 -1
  96. package/dist/foundation-shared/mail-host-policy.d.ts +4 -0
  97. package/dist/foundation-shared/mail-host-policy.js +13 -4
  98. package/dist/inbound-mail-foundation/entities.d.ts +25 -0
  99. package/dist/inbound-mail-foundation/projection.d.ts +20 -0
  100. package/dist/inbound-provider-imap/feature.js +2 -0
  101. package/dist/inbound-provider-imap/imap-client.js +3 -4
  102. package/dist/jobs/constants.d.ts +1 -0
  103. package/dist/jobs/constants.js +1 -0
  104. package/dist/jobs/db/queries/retention.d.ts +1 -0
  105. package/dist/jobs/db/queries/retention.js +5 -0
  106. package/dist/jobs/db/queries/stale-run-sweep.d.ts +2 -0
  107. package/dist/jobs/db/queries/stale-run-sweep.js +13 -2
  108. package/dist/jobs/feature.js +7 -1
  109. package/dist/jobs/handlers/list.query.d.ts +2 -1
  110. package/dist/jobs/handlers/list.query.js +40 -15
  111. package/dist/jobs/handlers/tenant-failures.query.js +1 -1
  112. package/dist/jobs/handlers/tenant-runs.query.d.ts +17 -0
  113. package/dist/jobs/handlers/tenant-runs.query.js +72 -0
  114. package/dist/jobs/i18n.js +1 -0
  115. package/dist/jobs/index.d.ts +2 -0
  116. package/dist/jobs/index.js +1 -0
  117. package/dist/jobs/job-run-logger.d.ts +2 -2
  118. package/dist/jobs/job-run-logger.js +98 -9
  119. package/dist/jobs/job-run-table.d.ts +6 -0
  120. package/dist/jobs/tenant-job-failure-table.js +15 -2
  121. package/dist/jobs/tenant-job-run-table.d.ts +4 -0
  122. package/dist/jobs/tenant-job-run-table.js +34 -0
  123. package/dist/ledger/entity.d.ts +24 -8
  124. package/dist/ledger/entity.js +17 -5
  125. package/dist/ledger/feature.js +3 -0
  126. package/dist/ledger/handlers/confirm-schedule-period.write.js +9 -3
  127. package/dist/ledger/handlers/create-transaction.write.js +1 -0
  128. package/dist/ledger/handlers/reverse-transaction.write.js +1 -0
  129. package/dist/ledger/schedule-subject-pair.d.ts +2 -0
  130. package/dist/ledger/schedule-subject-pair.js +24 -0
  131. package/dist/ledger/schemas.js +8 -2
  132. package/dist/mail-transport-smtp/feature.d.ts +3 -4
  133. package/dist/mail-transport-smtp/feature.js +4 -13
  134. package/dist/managed-pages/feature.js +28 -10
  135. package/dist/managed-pages/table.d.ts +12 -0
  136. package/dist/notes-history/entity.d.ts +12 -0
  137. package/dist/notes-history/entity.js +4 -0
  138. package/dist/notes-history/feature.js +2 -10
  139. package/dist/personal-access-tokens/handlers/create.write.js +1 -0
  140. package/dist/personal-access-tokens/schema/api-token.d.ts +6 -0
  141. package/dist/personal-access-tokens/screens.js +14 -3
  142. package/dist/secrets/table.d.ts +1 -0
  143. package/dist/seo/feature.js +28 -6
  144. package/dist/sessions/feature.d.ts +1 -0
  145. package/dist/sessions/feature.js +9 -8
  146. package/dist/sessions/handlers/detail.query.d.ts +1 -1
  147. package/dist/sessions/handlers/detail.query.js +2 -2
  148. package/dist/sessions/handlers/list.query.d.ts +1 -1
  149. package/dist/sessions/handlers/list.query.js +5 -3
  150. package/dist/sessions/schema/user-session.d.ts +4 -0
  151. package/dist/sessions/screens.d.ts +2 -2
  152. package/dist/sessions/screens.js +6 -7
  153. package/dist/shared/assert-no-where-rule-in-ownership-write.d.ts +2 -0
  154. package/dist/shared/assert-no-where-rule-in-ownership-write.js +18 -0
  155. package/dist/shared/encrypt-for-direct-write.js +10 -2
  156. package/dist/shared/index.d.ts +4 -3
  157. package/dist/shared/index.js +4 -3
  158. package/dist/shared/parent-visibility.d.ts +2 -1
  159. package/dist/shared/parent-visibility.js +21 -0
  160. package/dist/shared/rate-limited-text-response.d.ts +2 -0
  161. package/dist/shared/rate-limited-text-response.js +9 -0
  162. package/dist/shared/row-bound-grant.js +16 -2
  163. package/dist/shared/session-locale-field.d.ts +1 -0
  164. package/dist/shared/session-locale-field.js +6 -0
  165. package/dist/tags/entity.d.ts +9 -0
  166. package/dist/tags/feature.js +2 -10
  167. package/dist/template-resolver/api.d.ts +2 -2
  168. package/dist/template-resolver/handlers/list.query.d.ts +2 -0
  169. package/dist/template-resolver/handlers/list.query.js +2 -2
  170. package/dist/template-resolver/table.d.ts +48 -30
  171. package/dist/template-resolver/user-content-table.d.ts +34 -20
  172. package/dist/tenant/decrypt-tenant-names.d.ts +3 -0
  173. package/dist/tenant/decrypt-tenant-names.js +10 -0
  174. package/dist/tenant/feature.js +7 -1
  175. package/dist/tenant/handlers/me.query.js +5 -1
  176. package/dist/tenant/handlers/memberships.query.js +3 -2
  177. package/dist/tenant/handlers/tenant-directory.query.js +9 -3
  178. package/dist/tenant/handlers/toggle-enabled.write.js +2 -0
  179. package/dist/tenant/handlers/update-member-roles.write.js +1 -0
  180. package/dist/tenant/index.d.ts +1 -0
  181. package/dist/tenant/index.js +1 -0
  182. package/dist/tenant/invitation-table.d.ts +54 -8
  183. package/dist/tenant/invitation-table.js +6 -1
  184. package/dist/tenant/invited-membership.d.ts +8 -6
  185. package/dist/tenant/invited-membership.js +28 -7
  186. package/dist/tenant/membership-table.d.ts +4 -0
  187. package/dist/tenant/schema/tenant.d.ts +18 -10
  188. package/dist/tenant/schema/tenant.js +4 -6
  189. package/dist/tenant/screens.js +1 -1
  190. package/dist/tenant-handover/move-entity-graph.js +11 -18
  191. package/dist/tenant-handover/transfer-graph.d.ts +2 -21
  192. package/dist/tenant-handover/transfer-graph.js +8 -75
  193. package/dist/tenant-lifecycle/boot-checks.d.ts +1 -0
  194. package/dist/tenant-lifecycle/boot-checks.js +13 -0
  195. package/dist/tenant-lifecycle/constants.d.ts +3 -0
  196. package/dist/tenant-lifecycle/constants.js +5 -0
  197. package/dist/tenant-lifecycle/events.d.ts +5 -0
  198. package/dist/tenant-lifecycle/events.js +5 -0
  199. package/dist/tenant-lifecycle/feature.js +6 -3
  200. package/dist/tenant-lifecycle/run-tenant-destroy.d.ts +10 -5
  201. package/dist/tenant-lifecycle/run-tenant-destroy.js +59 -17
  202. package/dist/tenant-lifecycle/stages.d.ts +8 -1
  203. package/dist/tenant-lifecycle/stages.js +33 -4
  204. package/dist/tenant-lifecycle/testing.d.ts +8 -0
  205. package/dist/tenant-lifecycle/testing.js +42 -0
  206. package/dist/tier-engine/entity.d.ts +2 -0
  207. package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -0
  208. package/dist/tier-engine/tier-resolver.d.ts +2 -0
  209. package/dist/user/handlers/detail.query.js +2 -0
  210. package/dist/user/handlers/list.query.js +6 -2
  211. package/dist/user/handlers/update.write.js +1 -0
  212. package/dist/user/schema/user.d.ts +22 -8
  213. package/dist/user/seeding.d.ts +1 -0
  214. package/dist/user/seeding.js +20 -0
  215. package/dist/user-data-rights/boot-checks.js +5 -0
  216. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +2 -2
  217. package/dist/user-data-rights/handlers/request-deletion.write.js +1 -0
  218. package/dist/user-data-rights/index.d.ts +1 -0
  219. package/dist/user-data-rights/index.js +1 -0
  220. package/dist/user-data-rights/schema/download-attempt.d.ts +14 -0
  221. package/dist/user-data-rights/schema/download-attempt.js +17 -9
  222. package/dist/user-data-rights/schema/download-token.d.ts +8 -0
  223. package/dist/user-data-rights/schema/export-job.d.ts +16 -8
  224. package/dist/user-profile/handlers/change-email.write.js +8 -2
  225. package/dist/waitlist/entity.d.ts +22 -6
  226. package/dist/workflow-runner/event-trigger.d.ts +1 -0
  227. package/dist/workflow-runner/event-trigger.js +63 -15
  228. package/dist/workflow-runner/handlers/resume-run.write.js +8 -2
  229. package/dist/workflow-runner/runner.d.ts +2 -1
  230. package/dist/workflow-runner/runner.js +5 -1
  231. package/package.json +35 -10
  232. package/src/agent-tools/changes.json +12 -0
  233. package/src/audit/changes.json +6 -0
  234. package/src/auth-email-password/changes.json +24 -0
  235. package/src/auth-mfa/changes.json +7 -0
  236. package/src/billing-foundation/changes.json +6 -0
  237. package/src/channel-in-app/changes.json +8 -1
  238. package/src/crypto-shredding/changes.json +12 -0
  239. package/src/delivery/changes.json +6 -0
  240. package/src/files/changes.json +24 -0
  241. package/src/files-tenant-data/changes.json +5 -0
  242. package/src/folders/changes.json +6 -0
  243. package/src/form-draft/changes.json +7 -1
  244. package/src/inbound-provider-imap/changes.json +6 -0
  245. package/src/jobs/changes.json +30 -0
  246. package/src/ledger/changes.json +23 -0
  247. package/src/managed-pages/changes.json +6 -0
  248. package/src/notes-history/changes.json +13 -0
  249. package/src/seo/changes.json +5 -0
  250. package/src/template-resolver/changes.json +5 -0
  251. package/src/tenant/changes.json +19 -0
  252. package/src/tenant-handover/changes.json +12 -0
  253. package/src/tenant-lifecycle/changes.json +22 -0
  254. package/src/tier-engine/changes.json +5 -0
  255. package/src/user/changes.json +15 -0
  256. package/src/user-data-rights/changes.json +6 -0
  257. package/src/workflow-runner/changes.json +5 -0
  258. package/dist/shared/has-where-rule.d.ts +0 -2
  259. package/dist/shared/has-where-rule.js +0 -10
@@ -3,6 +3,7 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
3
3
  readonly type: "text";
4
4
  readonly description?: string;
5
5
  readonly maxLength?: number;
6
+ readonly minLength?: number;
6
7
  readonly required?: boolean;
7
8
  readonly searchable?: boolean;
8
9
  readonly sortable?: boolean;
@@ -32,15 +33,16 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
32
33
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
33
34
  readonly display?: "radio" | "dropdown";
34
35
  readonly optionTones?: {
35
- readonly asset?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
36
- readonly equity?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
37
- readonly expense?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
38
- readonly income?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
39
- readonly liability?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
36
+ readonly asset?: "bad" | "neutral" | "ok" | "warn" | undefined;
37
+ readonly equity?: "bad" | "neutral" | "ok" | "warn" | undefined;
38
+ readonly expense?: "bad" | "neutral" | "ok" | "warn" | undefined;
39
+ readonly income?: "bad" | "neutral" | "ok" | "warn" | undefined;
40
+ readonly liability?: "bad" | "neutral" | "ok" | "warn" | undefined;
40
41
  } | undefined;
41
42
  readonly optionsQuery?: string;
42
43
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
43
44
  readonly optionsAvailabilityQuery?: string;
45
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"asset" | "equity" | "expense" | "income" | "liability">[] | undefined;
44
46
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
45
47
  required: true;
46
48
  };
@@ -48,6 +50,7 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
48
50
  readonly type: "text";
49
51
  readonly description?: string;
50
52
  readonly maxLength?: number;
53
+ readonly minLength?: number;
51
54
  readonly required?: boolean;
52
55
  readonly searchable?: boolean;
53
56
  readonly sortable?: boolean;
@@ -69,6 +72,7 @@ export declare const accountEntity: import("@cosmicdrift/kumiko-types/fields").E
69
72
  readonly type: "text";
70
73
  readonly description?: string;
71
74
  readonly maxLength?: number;
75
+ readonly minLength?: number;
72
76
  readonly required?: boolean;
73
77
  readonly searchable?: boolean;
74
78
  readonly sortable?: boolean;
@@ -106,6 +110,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
106
110
  readonly type: "text";
107
111
  readonly description?: string;
108
112
  readonly maxLength?: number;
113
+ readonly minLength?: number;
109
114
  readonly required?: boolean;
110
115
  readonly searchable?: boolean;
111
116
  readonly sortable?: boolean;
@@ -127,6 +132,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
127
132
  readonly type: "text";
128
133
  readonly description?: string;
129
134
  readonly maxLength?: number;
135
+ readonly minLength?: number;
130
136
  readonly required?: boolean;
131
137
  readonly searchable?: boolean;
132
138
  readonly sortable?: boolean;
@@ -156,12 +162,13 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
156
162
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
157
163
  readonly display?: "radio" | "dropdown";
158
164
  readonly optionTones?: {
159
- readonly draft?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
160
- readonly posted?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
165
+ readonly draft?: "bad" | "neutral" | "ok" | "warn" | undefined;
166
+ readonly posted?: "bad" | "neutral" | "ok" | "warn" | undefined;
161
167
  } | undefined;
162
168
  readonly optionsQuery?: string;
163
169
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
164
170
  readonly optionsAvailabilityQuery?: string;
171
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"draft" | "posted">[] | undefined;
165
172
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
166
173
  required: true;
167
174
  };
@@ -185,6 +192,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
185
192
  readonly type: "text";
186
193
  readonly description?: string;
187
194
  readonly maxLength?: number;
195
+ readonly minLength?: number;
188
196
  readonly required?: boolean;
189
197
  readonly searchable?: boolean;
190
198
  readonly sortable?: boolean;
@@ -206,6 +214,7 @@ export declare const transactionEntity: import("@cosmicdrift/kumiko-types/fields
206
214
  readonly type: "text";
207
215
  readonly description?: string;
208
216
  readonly maxLength?: number;
217
+ readonly minLength?: number;
209
218
  readonly required?: boolean;
210
219
  readonly searchable?: boolean;
211
220
  readonly sortable?: boolean;
@@ -229,6 +238,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
229
238
  readonly type: "text";
230
239
  readonly description?: string;
231
240
  readonly maxLength?: number;
241
+ readonly minLength?: number;
232
242
  readonly required?: boolean;
233
243
  readonly searchable?: boolean;
234
244
  readonly sortable?: boolean;
@@ -286,11 +296,12 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
286
296
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
287
297
  readonly display?: "radio" | "dropdown";
288
298
  readonly optionTones?: {
289
- readonly monthly?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
299
+ readonly monthly?: "bad" | "neutral" | "ok" | "warn" | undefined;
290
300
  } | undefined;
291
301
  readonly optionsQuery?: string;
292
302
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
293
303
  readonly optionsAvailabilityQuery?: string;
304
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"monthly">[] | undefined;
294
305
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
295
306
  required: true;
296
307
  };
@@ -317,6 +328,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
317
328
  readonly type: "text";
318
329
  readonly description?: string;
319
330
  readonly maxLength?: number;
331
+ readonly minLength?: number;
320
332
  readonly required?: boolean;
321
333
  readonly searchable?: boolean;
322
334
  readonly sortable?: boolean;
@@ -338,6 +350,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
338
350
  readonly type: "text";
339
351
  readonly description?: string;
340
352
  readonly maxLength?: number;
353
+ readonly minLength?: number;
341
354
  readonly required?: boolean;
342
355
  readonly searchable?: boolean;
343
356
  readonly sortable?: boolean;
@@ -359,6 +372,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
359
372
  readonly type: "text";
360
373
  readonly description?: string;
361
374
  readonly maxLength?: number;
375
+ readonly minLength?: number;
362
376
  readonly required?: boolean;
363
377
  readonly searchable?: boolean;
364
378
  readonly sortable?: boolean;
@@ -380,6 +394,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
380
394
  readonly type: "text";
381
395
  readonly description?: string;
382
396
  readonly maxLength?: number;
397
+ readonly minLength?: number;
383
398
  readonly required?: boolean;
384
399
  readonly searchable?: boolean;
385
400
  readonly sortable?: boolean;
@@ -401,6 +416,7 @@ export declare const scheduleEntity: import("@cosmicdrift/kumiko-types/fields").
401
416
  readonly type: "text";
402
417
  readonly description?: string;
403
418
  readonly maxLength?: number;
419
+ readonly minLength?: number;
404
420
  readonly required?: boolean;
405
421
  readonly searchable?: boolean;
406
422
  readonly sortable?: boolean;
@@ -80,18 +80,22 @@ export const transactionEntity = createEntity({
80
80
  // Optional business-object reference (e.g. a lease contract) so entries can
81
81
  // be filtered by what they're about, not just grepped out of `reference`.
82
82
  subjectType: createTextField({
83
+ minLength: 1,
83
84
  maxLength: 64,
84
85
  personal: false,
85
86
  reason: "technical_reference",
86
87
  filterable: true,
87
88
  }),
88
89
  subjectId: createTextField({
90
+ minLength: 1,
89
91
  maxLength: 128,
90
92
  personal: false,
91
93
  reason: "technical_reference",
92
94
  filterable: true,
93
95
  }),
94
96
  },
97
+ // Subject ids are only unique within their type, so lookups filter on both
98
+ // columns; a subjectId-only filter would not be served by this index.
95
99
  indexes: [{ columns: ["tenantId", "subjectType", "subjectId"] }],
96
100
  });
97
101
  // schedule — a recurring booking template (Dauerauftrag): "book `amount` from
@@ -131,20 +135,22 @@ export const scheduleEntity = createEntity({
131
135
  // Confirmed periods inherit this from the schedule (see
132
136
  // confirm-schedule-period.write.ts) rather than repeating it per period.
133
137
  subjectType: createTextField({
138
+ minLength: 1,
134
139
  maxLength: 64,
135
140
  personal: false,
136
141
  reason: "technical_reference",
137
142
  filterable: true,
138
143
  }),
139
144
  subjectId: createTextField({
145
+ minLength: 1,
140
146
  maxLength: 128,
141
147
  personal: false,
142
148
  reason: "technical_reference",
143
149
  filterable: true,
144
150
  }),
145
151
  // Caller-assigned stable key (e.g. one id per lease position) to find the
146
- // schedule again. Not unique: callers keep their own find-then-create;
147
- // `description` stays pure display text instead of a lookup key.
152
+ // schedule again; unique per tenant when set. `description` stays pure
153
+ // display text instead of a lookup key.
148
154
  sourceRef: createTextField({
149
155
  maxLength: 128,
150
156
  personal: false,
@@ -152,10 +158,16 @@ export const scheduleEntity = createEntity({
152
158
  filterable: true,
153
159
  }),
154
160
  },
155
- // A separate non-unique index: changing the subject index would drop and
156
- // recreate it, an additional one is a plain CREATE INDEX.
161
+ // Find-then-create by sourceRef races across tabs/devices; only the DB closes
162
+ // that gap. Partial because sourceRef is optional. A new name (not the old
163
+ // non-unique default) keeps the migration an in-place CREATE UNIQUE INDEX.
157
164
  indexes: [
158
165
  { columns: ["tenantId", "subjectType", "subjectId"] },
159
- { columns: ["tenantId", "sourceRef"] },
166
+ {
167
+ columns: ["tenantId", "sourceRef"],
168
+ unique: true,
169
+ where: sql `"source_ref" IS NOT NULL`,
170
+ name: "read_ledger_schedules_tenant_id_source_ref_uidx",
171
+ },
160
172
  ],
161
173
  });
@@ -18,6 +18,7 @@ import { createConfirmSchedulePeriodHandler } from "./handlers/confirm-schedule-
18
18
  import { createCreateTransactionHandler } from "./handlers/create-transaction.write.js";
19
19
  import { createBalanceSheetHandler, createBalancesReportHandler, createIncomeStatementHandler, } from "./handlers/reports.query.js";
20
20
  import { createReverseTransactionHandler } from "./handlers/reverse-transaction.write.js";
21
+ import { requireScheduleSubjectPair } from "./schedule-subject-pair.js";
21
22
  function registerLedger(r, access, toggleable) {
22
23
  r.describe("Double-entry bookkeeping primitive. Owns two event-sourced entities — the per-tenant `account` chart of accounts (`read_ledger_accounts`, self-referential via parentId, typed asset/liability/equity/income/expense) and immutable `transaction` journal entries (`read_ledger_transactions`) whose balanced posting lines are embedded as jsonb (Σ amount = 0, signed integer minor units). The account catalog uses the generic entity handlers (create, update, list, detail); create-transaction books a balanced entry (Σ=0 and ≥2 distinct accounts enforced at the command boundary, referential integrity against accounts checked) and reverse-transaction books its Storno mirror — there is deliberately NO transaction update/delete, so a posted entry is an immutable fact and the audit trail stays intact. Recurring schedules (`read_ledger_schedules`) layer Dauerauftrag templates on top — a schedule names debit/credit accounts, an amount, a monthly interval and an optional caller-assigned `sourceRef` key (filterable, to find a schedule again), from which the Soll (forecast) is a pure projection (projectSchedule) needing no bookings, and confirm-schedule-period materialises one period as an idempotent, reversal-aware balanced entry referencing scheduleReference(id, period); only confirming writes. Balances and reports (balance sheet, P&L, cashflow) derive as pure queries over the postings. Everything financial — banking, accounting, rent cashflow, credits, invoices — models as accounts + balanced transactions on top. Pin roles with createLedgerFeature({ roles }) or adopt the host model with { access }; pass { toggleable: { default: false } } to tier-gate the whole feature.");
23
24
  r.uiHints({
@@ -72,6 +73,8 @@ function registerLedger(r, access, toggleable) {
72
73
  access,
73
74
  description: "Changes a recurring booking template's description, accounts, amount, interval or date window; use it when a standing order's terms change, already confirmed periods stay booked as they were.",
74
75
  }));
76
+ r.hook("preSave", "schedule:create", requireScheduleSubjectPair);
77
+ r.hook("preSave", "schedule:update", requireScheduleSubjectPair);
75
78
  r.writeHandler(createConfirmSchedulePeriodHandler(access));
76
79
  r.queryHandler(defineEntityListHandler("schedule", scheduleEntity, {
77
80
  access,
@@ -1,3 +1,4 @@
1
+ import { acquireNamespacedAdvisoryLock } from "@cosmicdrift/kumiko-framework/db";
1
2
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
2
3
  import { generateId } from "@cosmicdrift/kumiko-framework/utils";
3
4
  import { DEFAULT_LEDGER_ACCESS } from "../constants.js";
@@ -5,6 +6,10 @@ import { accountExecutor, scheduleExecutor, transactionExecutor, transactionTabl
5
6
  import { findReversedIds, isoMonth, scheduleReference } from "../recurring.js";
6
7
  import { confirmSchedulePeriodPayloadSchema, } from "../schemas.js";
7
8
  import { readSubjectReference } from "../subject-reference.js";
9
+ // pg_advisory_xact_lock namespace (int4): 'lcsp' as ASCII, disjoint from the
10
+ // framework's other fixed advisory-lock keys.
11
+ const CONFIRM_PERIOD_LOCK_NAMESPACE = 0x6c637370;
12
+ const CONFIRM_PERIOD_LOCK_REASON = "takes the per-(tenant, reference) advisory lock so parallel confirms cannot both pass the already-booked check; TenantDb has no lock API";
8
13
  // confirm-schedule-period — turn ONE projected period of a schedule into a posted,
9
14
  // balanced transaction (debit +amount / credit −amount), tagged with
10
15
  // scheduleReference(scheduleId, period) so the host can merge Soll vs. Ist.
@@ -19,6 +24,7 @@ export function createConfirmSchedulePeriodHandler(access = DEFAULT_LEDGER_ACCES
19
24
  name: "confirm-schedule-period",
20
25
  schema: confirmSchedulePeriodPayloadSchema,
21
26
  access,
27
+ escapeHatch: { grants: ["unsafeRaw"], reason: CONFIRM_PERIOD_LOCK_REASON },
22
28
  description: "Turns one month of a recurring schedule into a posted balanced entry between its debit and credit account, returning the existing booking instead when that period is already booked and not reversed; use it to move a forecast period into the actual books.",
23
29
  handler: async (event, ctx) => {
24
30
  const payload = event.payload; // @cast-boundary engine-payload
@@ -42,9 +48,9 @@ export function createConfirmSchedulePeriodHandler(access = DEFAULT_LEDGER_ACCES
42
48
  // normally 0 or 1 row, never O(tenant's-full-history); (2) any Storno
43
49
  // that mirrors one of those candidates (a tx is reversed when ANOTHER
44
50
  // tx's `reference` names its id).
45
- // ponytail: read-then-write, so two confirms racing the same period could
46
- // double-book; add a unique index on (tenantId, reference) when concurrent
47
- // confirms become real.
51
+ // No unique index on (tenantId, reference): a Storno makes re-confirming the
52
+ // same reference legitimate, so the check-then-write is serialized by a lock.
53
+ await acquireNamespacedAdvisoryLock(ctx.db.unsafeRaw(), CONFIRM_PERIOD_LOCK_NAMESPACE, `${event.user.tenantId}:${reference}`);
48
54
  const candidates = await ctx.db.selectMany(transactionTable, {
49
55
  tenantId: event.user.tenantId,
50
56
  reference,
@@ -14,6 +14,7 @@ export function createCreateTransactionHandler(access = DEFAULT_LEDGER_ACCESS) {
14
14
  schema: createTransactionPayloadSchema,
15
15
  access,
16
16
  description: "Books one balanced journal entry from a date, description and at least two posting lines summing to zero, after verifying every named account exists; use it to record any financial movement in the tenant's books.",
17
+ agent: { risk: "high" },
17
18
  handler: async (event, ctx) => {
18
19
  const payload = event.payload; // @cast-boundary engine-payload
19
20
  for (const accountId of new Set(payload.lines.map((l) => l.accountId))) {
@@ -16,6 +16,7 @@ export function createReverseTransactionHandler(access = DEFAULT_LEDGER_ACCESS)
16
16
  schema: reverseTransactionPayloadSchema,
17
17
  access,
18
18
  description: "Books the mirror image of a posted journal entry as a new entry referencing the original, refusing entries that are not posted or already reversed; use it as the only way to correct a booking, since entries themselves are immutable.",
19
+ agent: { risk: "high" },
19
20
  handler: async (event, ctx) => {
20
21
  const payload = event.payload; // @cast-boundary engine-payload
21
22
  const original = await transactionExecutor.detail({ id: payload.id }, event.user, ctx.db);
@@ -0,0 +1,2 @@
1
+ import type { PreSaveHookFn } from "@cosmicdrift/kumiko-framework/engine";
2
+ export declare const requireScheduleSubjectPair: PreSaveHookFn;
@@ -0,0 +1,24 @@
1
+ import { ValidationError } from "@cosmicdrift/kumiko-framework/errors";
2
+ function isSet(value) {
3
+ return value !== undefined && value !== null && value !== "";
4
+ }
5
+ // subjectId is only unique within its subjectType, so a schedule with one of
6
+ // the two would be found by a lone-subjectId filter among other object types.
7
+ // The effective pair is checked (changes over the stored row) because an
8
+ // update may touch only one of the two fields.
9
+ export const requireScheduleSubjectPair = async (changes, ctx) => {
10
+ const effective = (key) => key in changes ? changes[key] : ctx.previous[key];
11
+ const hasType = isSet(effective("subjectType"));
12
+ const hasId = isSet(effective("subjectId"));
13
+ if (hasType === hasId)
14
+ return changes;
15
+ throw new ValidationError({
16
+ fields: [
17
+ {
18
+ path: hasType ? "subjectId" : "subjectType",
19
+ code: "required",
20
+ i18nKey: "errors.validation.required",
21
+ },
22
+ ],
23
+ });
24
+ };
@@ -21,8 +21,14 @@ export const createTransactionPayloadSchema = z
21
21
  status: z.enum(TRANSACTION_STATUS).optional(),
22
22
  lines: z.array(postingSchema).min(2),
23
23
  // Business-object reference (e.g. a lease contract) this entry is about.
24
- subjectType: z.string().max(64).optional(),
25
- subjectId: z.string().max(128).optional(),
24
+ subjectType: z.string().min(1).max(64).optional(),
25
+ subjectId: z.string().min(1).max(128).optional(),
26
+ })
27
+ // Ids are only unique within their type, so a lone subjectId would match
28
+ // bookings of a different object type.
29
+ .refine((p) => (p.subjectType === undefined) === (p.subjectId === undefined), {
30
+ message: "subjectType and subjectId must be set together",
31
+ path: ["subjectId"],
26
32
  })
27
33
  .refine((p) => sumIsZero(p.lines), {
28
34
  message: "Transaction must balance: Σ of posting amounts must equal 0",
@@ -1,8 +1,7 @@
1
1
  import type { lookup } from "node:dns/promises";
2
- import * as z from "zod";
3
- export declare const mailTransportSmtpEnvSchema: z.ZodObject<{
4
- KUMIKO_MAIL_ALLOWED_PRIVATE_HOSTS: z.ZodOptional<z.ZodString>;
5
- }, z.core.$strip>;
2
+ export declare const mailTransportSmtpEnvSchema: import("zod").ZodObject<{
3
+ KUMIKO_MAIL_ALLOWED_PRIVATE_HOSTS: import("zod").ZodOptional<import("zod").ZodString>;
4
+ }, import("zod/v4/core").$strip>;
6
5
  export declare function setSmtpMailHostLookup(fn: typeof lookup | undefined): void;
7
6
  export declare const mailTransportSmtpFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
8
7
  readonly exports: {
@@ -25,29 +25,20 @@
25
25
  // - `config` — für die Tenant-Config-Keys
26
26
  // - `secrets` — für das verschlüsselte SMTP-Password
27
27
  import { createSmtpTransport, } from "@cosmicdrift/kumiko-bundled-features/channel-email";
28
- import { BlockedHostError, HostResolutionError, MAIL_ALLOWED_PRIVATE_HOSTS_ENV_VAR, readAllowedPrivateMailHostsFromEnv, requireDefined, requireNonEmpty, requireSecretSet, resolveMailConnectTarget, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
28
+ import { BlockedHostError, HostResolutionError, mailAllowedPrivateHostsEnvSchema, readAllowedPrivateMailHostsFromEnv, requireDefined, requireNonEmpty, requireSecretSet, resolveMailConnectTarget, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
29
29
  import { MAIL_TRANSPORT_EXTENSION, } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
30
30
  import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
31
31
  import { access, createTenantConfig, defineFeature } from "@cosmicdrift/kumiko-framework/engine";
32
32
  import { UnconfiguredError } from "@cosmicdrift/kumiko-framework/errors";
33
33
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
34
- import * as z from "zod";
35
34
  const FEATURE_NAME = "mail-transport-smtp";
36
35
  const log = createFallbackLogger(FEATURE_NAME);
37
36
  // Operator escape hatch for an internal relay or a dev/test SMTP server
38
37
  // (mailpit, MailHog): KUMIKO_MAIL_ALLOWED_PRIVATE_HOSTS, an operator env
39
38
  // var never a tenant-config value, so a tenant can never grant themselves
40
- // the private-host bypass. Declared here (not duplicated in
41
- // inbound-provider-imap's envSchema) since both features read the same
42
- // var and composeEnvSchema rejects two features declaring the same key —
43
- // see foundation-shared/mail-host-policy.ts for the shared reader + the
44
- // guard this feeds.
45
- export const mailTransportSmtpEnvSchema = z.object({
46
- [MAIL_ALLOWED_PRIVATE_HOSTS_ENV_VAR]: z
47
- .string()
48
- .optional()
49
- .describe("Comma-separated operator allowlist of private/internal hosts (e.g. a local mailpit/greenmail dev server) that bypass the public-address check for SMTP and IMAP host config. Shared with inbound-provider-imap — never a tenant-config value."),
50
- });
39
+ // the private-host bypass. The schema instance is shared with
40
+ // inbound-provider-imap (see foundation-shared/mail-host-policy.ts).
41
+ export const mailTransportSmtpEnvSchema = mailAllowedPrivateHostsEnvSchema;
51
42
  // Test-only DNS seam — production never calls this, resolveMailConnectTarget
52
43
  // defaults to the real resolver. Lets tests pin deterministic, network-free
53
44
  // host resolutions instead of depending on real DNS for a placeholder host.
@@ -1,6 +1,8 @@
1
1
  import { computeRevisionEtag, etagMatches } from "@cosmicdrift/kumiko-framework/api";
2
2
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
3
+ import { RateLimitError } from "@cosmicdrift/kumiko-framework/errors";
3
4
  import { cachedSecurePageResponse, EMPTY_BRANDING, renderSafeMarkdown, wrapInLayout, } from "../page-render/index.js";
5
+ import { rateLimitedTextResponse } from "../shared/index.js";
4
6
  import { BRANDING_KEYS, BRANDING_QUERY_QN, CUSTOM_CSS_KEY, coerceBranding } from "./branding.js";
5
7
  import { createBrandingQuery } from "./handlers/branding.query.js";
6
8
  import { bySlugQuery } from "./handlers/by-slug.query.js";
@@ -28,14 +30,17 @@ function brandingRevisionSeed(branding) {
28
30
  branding.customCss,
29
31
  ]);
30
32
  }
31
- // Never throws: a query failure or malformed result degrades to the
32
- // unbranded default (branding is decoration, not a hard dependency of the
33
- // page render).
33
+ // A query failure or malformed result degrades to the unbranded default
34
+ // (branding is decoration, not a hard dependency of the page render). A rate
35
+ // limit is rethrown so the route answers 429 instead of serving (and caching)
36
+ // an unbranded page.
34
37
  async function readBrandingViaSystemQuery(systemQuery, tenantId) {
35
38
  try {
36
39
  return coerceBranding(await systemQuery(BRANDING_QUERY_QN, {}, tenantId));
37
40
  }
38
- catch {
41
+ catch (error) {
42
+ if (error instanceof RateLimitError)
43
+ throw error;
39
44
  return EMPTY_BRANDING;
40
45
  }
41
46
  }
@@ -125,12 +130,25 @@ export function createManagedPagesFeature(opts) {
125
130
  // von resolverTrust: "authoritative" zurecht abgelehnt; siehe
126
131
  // systemQuery's Doc in http-route.ts). Branding ist Deko → ein
127
132
  // Fehlschlag degradiert zum unbranded Default, blockt nie die Page.
128
- const [pageSettled, brandingResult] = await Promise.all([
129
- systemQuery(BY_SLUG_QN, { slug, lang }, tenantId)
130
- .then((data) => ({ ok: true, data: data }))
131
- .catch(() => ({ ok: false, data: null })),
132
- readBrandingViaSystemQuery(systemQuery, tenantId),
133
- ]);
133
+ let pageSettled;
134
+ let brandingResult;
135
+ try {
136
+ [pageSettled, brandingResult] = await Promise.all([
137
+ systemQuery(BY_SLUG_QN, { slug, lang }, tenantId)
138
+ .then((data) => ({ ok: true, data: data }))
139
+ .catch((error) => {
140
+ if (error instanceof RateLimitError)
141
+ throw error;
142
+ return { ok: false };
143
+ }),
144
+ readBrandingViaSystemQuery(systemQuery, tenantId),
145
+ ]);
146
+ }
147
+ catch (error) {
148
+ if (error instanceof RateLimitError)
149
+ return rateLimitedTextResponse(error);
150
+ throw error;
151
+ }
134
152
  if (!pageSettled.ok)
135
153
  return c.text("page unavailable", 503);
136
154
  const data = pageSettled.data;
@@ -3,6 +3,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
3
3
  readonly type: "text";
4
4
  readonly description?: string;
5
5
  readonly maxLength?: number;
6
+ readonly minLength?: number;
6
7
  readonly required?: boolean;
7
8
  readonly searchable?: boolean;
8
9
  readonly sortable?: boolean;
@@ -24,6 +25,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
24
25
  readonly type: "text";
25
26
  readonly description?: string;
26
27
  readonly maxLength?: number;
28
+ readonly minLength?: number;
27
29
  readonly required?: boolean;
28
30
  readonly searchable?: boolean;
29
31
  readonly sortable?: boolean;
@@ -45,6 +47,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
45
47
  readonly type: "text";
46
48
  readonly description?: string;
47
49
  readonly maxLength?: number;
50
+ readonly minLength?: number;
48
51
  readonly required?: boolean;
49
52
  readonly searchable?: boolean;
50
53
  readonly sortable?: boolean;
@@ -66,6 +69,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
66
69
  readonly type: "text";
67
70
  readonly description?: string;
68
71
  readonly maxLength?: number;
72
+ readonly minLength?: number;
69
73
  readonly required?: boolean;
70
74
  readonly searchable?: boolean;
71
75
  readonly sortable?: boolean;
@@ -87,6 +91,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
87
91
  readonly type: "text";
88
92
  readonly description?: string;
89
93
  readonly maxLength?: number;
94
+ readonly minLength?: number;
90
95
  readonly required?: boolean;
91
96
  readonly searchable?: boolean;
92
97
  readonly sortable?: boolean;
@@ -108,6 +113,7 @@ export declare const pageEntity: import("@cosmicdrift/kumiko-types/fields").Enti
108
113
  readonly type: "text";
109
114
  readonly description?: string;
110
115
  readonly maxLength?: number;
116
+ readonly minLength?: number;
111
117
  readonly required?: boolean;
112
118
  readonly searchable?: boolean;
113
119
  readonly sortable?: boolean;
@@ -134,6 +140,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
134
140
  readonly type: "text";
135
141
  readonly description?: string;
136
142
  readonly maxLength?: number;
143
+ readonly minLength?: number;
137
144
  readonly required?: boolean;
138
145
  readonly searchable?: boolean;
139
146
  readonly sortable?: boolean;
@@ -155,6 +162,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
155
162
  readonly type: "text";
156
163
  readonly description?: string;
157
164
  readonly maxLength?: number;
165
+ readonly minLength?: number;
158
166
  readonly required?: boolean;
159
167
  readonly searchable?: boolean;
160
168
  readonly sortable?: boolean;
@@ -176,6 +184,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
176
184
  readonly type: "text";
177
185
  readonly description?: string;
178
186
  readonly maxLength?: number;
187
+ readonly minLength?: number;
179
188
  readonly required?: boolean;
180
189
  readonly searchable?: boolean;
181
190
  readonly sortable?: boolean;
@@ -197,6 +206,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
197
206
  readonly type: "text";
198
207
  readonly description?: string;
199
208
  readonly maxLength?: number;
209
+ readonly minLength?: number;
200
210
  readonly required?: boolean;
201
211
  readonly searchable?: boolean;
202
212
  readonly sortable?: boolean;
@@ -218,6 +228,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
218
228
  readonly type: "text";
219
229
  readonly description?: string;
220
230
  readonly maxLength?: number;
231
+ readonly minLength?: number;
221
232
  readonly required?: boolean;
222
233
  readonly searchable?: boolean;
223
234
  readonly sortable?: boolean;
@@ -239,6 +250,7 @@ export declare const pagesTable: import("@cosmicdrift/kumiko-framework/db").Enti
239
250
  readonly type: "text";
240
251
  readonly description?: string;
241
252
  readonly maxLength?: number;
253
+ readonly minLength?: number;
242
254
  readonly required?: boolean;
243
255
  readonly searchable?: boolean;
244
256
  readonly sortable?: boolean;
@@ -4,6 +4,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
4
4
  readonly type: "text";
5
5
  readonly description?: string;
6
6
  readonly maxLength?: number;
7
+ readonly minLength?: number;
7
8
  readonly required?: boolean;
8
9
  readonly searchable?: boolean;
9
10
  readonly sortable?: boolean;
@@ -25,6 +26,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
25
26
  readonly type: "text";
26
27
  readonly description?: string;
27
28
  readonly maxLength?: number;
29
+ readonly minLength?: number;
28
30
  readonly required?: boolean;
29
31
  readonly searchable?: boolean;
30
32
  readonly sortable?: boolean;
@@ -46,6 +48,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
46
48
  readonly type: "text";
47
49
  readonly description?: string;
48
50
  readonly maxLength?: number;
51
+ readonly minLength?: number;
49
52
  readonly required?: boolean;
50
53
  readonly searchable?: boolean;
51
54
  readonly sortable?: boolean;
@@ -67,6 +70,7 @@ export declare function createNoteEntryEntity(access?: EntityDefinition["access"
67
70
  readonly type: "text";
68
71
  readonly description?: string;
69
72
  readonly maxLength?: number;
73
+ readonly minLength?: number;
70
74
  readonly required?: boolean;
71
75
  readonly searchable?: boolean;
72
76
  readonly sortable?: boolean;
@@ -106,6 +110,7 @@ export declare const noteEntryEntity: EntityDefinition<{
106
110
  readonly type: "text";
107
111
  readonly description?: string;
108
112
  readonly maxLength?: number;
113
+ readonly minLength?: number;
109
114
  readonly required?: boolean;
110
115
  readonly searchable?: boolean;
111
116
  readonly sortable?: boolean;
@@ -127,6 +132,7 @@ export declare const noteEntryEntity: EntityDefinition<{
127
132
  readonly type: "text";
128
133
  readonly description?: string;
129
134
  readonly maxLength?: number;
135
+ readonly minLength?: number;
130
136
  readonly required?: boolean;
131
137
  readonly searchable?: boolean;
132
138
  readonly sortable?: boolean;
@@ -148,6 +154,7 @@ export declare const noteEntryEntity: EntityDefinition<{
148
154
  readonly type: "text";
149
155
  readonly description?: string;
150
156
  readonly maxLength?: number;
157
+ readonly minLength?: number;
151
158
  readonly required?: boolean;
152
159
  readonly searchable?: boolean;
153
160
  readonly sortable?: boolean;
@@ -169,6 +176,7 @@ export declare const noteEntryEntity: EntityDefinition<{
169
176
  readonly type: "text";
170
177
  readonly description?: string;
171
178
  readonly maxLength?: number;
179
+ readonly minLength?: number;
172
180
  readonly required?: boolean;
173
181
  readonly searchable?: boolean;
174
182
  readonly sortable?: boolean;
@@ -208,6 +216,7 @@ export declare function createNoteMentionEntity(): EntityDefinition<{
208
216
  readonly type: "text";
209
217
  readonly description?: string;
210
218
  readonly maxLength?: number;
219
+ readonly minLength?: number;
211
220
  readonly required?: boolean;
212
221
  readonly searchable?: boolean;
213
222
  readonly sortable?: boolean;
@@ -229,6 +238,7 @@ export declare function createNoteMentionEntity(): EntityDefinition<{
229
238
  readonly type: "text";
230
239
  readonly description?: string;
231
240
  readonly maxLength?: number;
241
+ readonly minLength?: number;
232
242
  readonly required?: boolean;
233
243
  readonly searchable?: boolean;
234
244
  readonly sortable?: boolean;
@@ -252,6 +262,7 @@ export declare const noteMentionEntity: EntityDefinition<{
252
262
  readonly type: "text";
253
263
  readonly description?: string;
254
264
  readonly maxLength?: number;
265
+ readonly minLength?: number;
255
266
  readonly required?: boolean;
256
267
  readonly searchable?: boolean;
257
268
  readonly sortable?: boolean;
@@ -273,6 +284,7 @@ export declare const noteMentionEntity: EntityDefinition<{
273
284
  readonly type: "text";
274
285
  readonly description?: string;
275
286
  readonly maxLength?: number;
287
+ readonly minLength?: number;
276
288
  readonly required?: boolean;
277
289
  readonly searchable?: boolean;
278
290
  readonly sortable?: boolean;