@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
@@ -4,6 +4,7 @@ export declare const tagEntity: EntityDefinition<{
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 const tagEntity: EntityDefinition<{
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 const tagEntity: EntityDefinition<{
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;
@@ -69,6 +72,7 @@ export declare function createTagAssignmentEntity(access?: EntityDefinition["acc
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;
@@ -90,6 +94,7 @@ export declare function createTagAssignmentEntity(access?: EntityDefinition["acc
90
94
  readonly type: "text";
91
95
  readonly description?: string;
92
96
  readonly maxLength?: number;
97
+ readonly minLength?: number;
93
98
  readonly required?: boolean;
94
99
  readonly searchable?: boolean;
95
100
  readonly sortable?: boolean;
@@ -111,6 +116,7 @@ export declare function createTagAssignmentEntity(access?: EntityDefinition["acc
111
116
  readonly type: "text";
112
117
  readonly description?: string;
113
118
  readonly maxLength?: number;
119
+ readonly minLength?: number;
114
120
  readonly required?: boolean;
115
121
  readonly searchable?: boolean;
116
122
  readonly sortable?: boolean;
@@ -134,6 +140,7 @@ export declare const tagAssignmentEntity: EntityDefinition<{
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 tagAssignmentEntity: EntityDefinition<{
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 tagAssignmentEntity: EntityDefinition<{
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;
@@ -18,7 +18,7 @@
18
18
  // entityList/entityEdit catalog screens (legacy QNs stay for TagManager).
19
19
  // Deferred: optional host-projection decoration (`wireTagsFor`), search indexing.
20
20
  import { defineEntityDetailHandler, defineEntityListHandler, defineEntityUpdateHandler, defineFeature, } from "@cosmicdrift/kumiko-framework/engine";
21
- import { hasWhereRule } from "../shared/index.js";
21
+ import { assertNoWhereRuleInOwnershipWrite } from "../shared/index.js";
22
22
  import { DEFAULT_TAG_ACCESS, TAGS_FEATURE_NAME } from "./constants.js";
23
23
  import { createTagAssignmentEntity, tagEntity } from "./entity.js";
24
24
  import { createTagAssignmentExecutor } from "./executor.js";
@@ -109,15 +109,7 @@ export function createTagsFeature(opts = {}) {
109
109
  "assignment row. Omit `parents` to keep every registered entity " +
110
110
  "admissible as a host instead.");
111
111
  }
112
- if (hasWhereRule(opts.ownership?.write)) {
113
- throw new Error("createTagsFeature({ ownership }): ownership.write must not contain a " +
114
- '`{ kind: "where" }` rule — where-rules are evaluated only at the SQL ' +
115
- "layer (the read path, via buildOwnershipClause). Write paths that " +
116
- "consult access.write (userCanCreateFieldRow/userCanWriteFieldRow) can't " +
117
- "evaluate them, so such a rule can only ever deny — boot validation " +
118
- "rejects it too (fw#2626). Use a `from()` rule for ownership.write, or " +
119
- "leave it unset.");
120
- }
112
+ assertNoWhereRuleInOwnershipWrite("createTagsFeature", opts.ownership?.write);
121
113
  const access = resolveAccess(opts);
122
114
  return defineFeature(TAGS_FEATURE_NAME, (r) => registerTags(r, access, opts.toggleable, opts.ownership, opts.parents));
123
115
  }
@@ -1,4 +1,4 @@
1
- import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
1
+ import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
2
2
  import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
4
4
  import type { ContentFormat, TemplateKind } from "./constants.js";
@@ -61,7 +61,7 @@ export type TemplateResolverApi = {
61
61
  */
62
62
  readonly resolveTemplate: (args: ResolveRequest) => Promise<TemplateResource>;
63
63
  };
64
- export declare function createTemplateResolverApi(db: DbConnection): TemplateResolverApi;
64
+ export declare function createTemplateResolverApi(db: DbRunner): TemplateResolverApi;
65
65
  export declare class TemplateNotFoundError extends Error {
66
66
  readonly query: {
67
67
  slug: string;
@@ -1,10 +1,12 @@
1
1
  import * as z from "zod";
2
2
  export declare const listQuery: import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"list", z.ZodObject<{
3
3
  kind: z.ZodOptional<z.ZodEnum<{
4
+ "ai-prompt": "ai-prompt";
4
5
  "document-pdf": "document-pdf";
5
6
  "image-snapshot": "image-snapshot";
6
7
  "mail-html": "mail-html";
7
8
  notification: "notification";
9
+ "text-block": "text-block";
8
10
  }>>;
9
11
  locale: z.ZodOptional<z.ZodString>;
10
12
  status: z.ZodOptional<z.ZodEnum<{
@@ -1,7 +1,7 @@
1
1
  import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import * as z from "zod";
4
- import { RENDER_KINDS, TEMPLATE_STATUSES } from "../constants.js";
4
+ import { TEMPLATE_KINDS, TEMPLATE_STATUSES } from "../constants.js";
5
5
  import { templateResourcesTable } from "../table.js";
6
6
  // List für Admin-UI: filterbar nach kind / locale / status. Liefert
7
7
  // system-templates + tenant's eigene zusammen — Admin-UI rendert beide
@@ -9,7 +9,7 @@ import { templateResourcesTable } from "../table.js";
9
9
  export const listQuery = defineQueryHandler({
10
10
  name: "list",
11
11
  schema: z.object({
12
- kind: z.enum(RENDER_KINDS).optional(),
12
+ kind: z.enum(TEMPLATE_KINDS).optional(),
13
13
  locale: z.string().min(2).max(8).optional(),
14
14
  status: z.enum(TEMPLATE_STATUSES).optional(),
15
15
  includeSystem: z.boolean().default(true),
@@ -4,6 +4,7 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
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;
@@ -33,16 +34,17 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
33
34
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
34
35
  readonly display?: "radio" | "dropdown";
35
36
  readonly optionTones?: {
36
- readonly "ai-prompt"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
37
- readonly "document-pdf"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
38
- readonly "image-snapshot"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
39
- readonly "mail-html"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
40
- readonly notification?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
41
- readonly "text-block"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
37
+ readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
38
+ readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
39
+ readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
40
+ readonly "mail-html"?: "bad" | "neutral" | "ok" | "warn" | undefined;
41
+ readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
42
+ readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
42
43
  } | undefined;
43
44
  readonly optionsQuery?: string;
44
45
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
45
46
  readonly optionsAvailabilityQuery?: string;
47
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block">[] | undefined;
46
48
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
47
49
  required: true;
48
50
  };
@@ -50,6 +52,7 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
50
52
  readonly type: "text";
51
53
  readonly description?: string;
52
54
  readonly maxLength?: number;
55
+ readonly minLength?: number;
53
56
  readonly required?: boolean;
54
57
  readonly searchable?: boolean;
55
58
  readonly sortable?: boolean;
@@ -71,6 +74,7 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
71
74
  readonly type: "text";
72
75
  readonly description?: string;
73
76
  readonly maxLength?: number;
77
+ readonly minLength?: number;
74
78
  readonly required?: boolean;
75
79
  readonly searchable?: boolean;
76
80
  readonly sortable?: boolean;
@@ -92,6 +96,7 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
92
96
  readonly type: "text";
93
97
  readonly description?: string;
94
98
  readonly maxLength?: number;
99
+ readonly minLength?: number;
95
100
  readonly required?: boolean;
96
101
  readonly searchable?: boolean;
97
102
  readonly sortable?: boolean;
@@ -137,14 +142,15 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
137
142
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
138
143
  readonly display?: "radio" | "dropdown";
139
144
  readonly optionTones?: {
140
- readonly html?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
141
- readonly markdown?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
142
- readonly mjml?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
143
- readonly plain?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
145
+ readonly html?: "bad" | "neutral" | "ok" | "warn" | undefined;
146
+ readonly markdown?: "bad" | "neutral" | "ok" | "warn" | undefined;
147
+ readonly mjml?: "bad" | "neutral" | "ok" | "warn" | undefined;
148
+ readonly plain?: "bad" | "neutral" | "ok" | "warn" | undefined;
144
149
  } | undefined;
145
150
  readonly optionsQuery?: string;
146
151
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
147
152
  readonly optionsAvailabilityQuery?: string;
153
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"html" | "markdown" | "mjml" | "plain">[] | undefined;
148
154
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
149
155
  required: true;
150
156
  };
@@ -192,12 +198,13 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
192
198
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
193
199
  readonly display?: "radio" | "dropdown";
194
200
  readonly optionTones?: {
195
- readonly system?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
196
- readonly tenant?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
201
+ readonly system?: "bad" | "neutral" | "ok" | "warn" | undefined;
202
+ readonly tenant?: "bad" | "neutral" | "ok" | "warn" | undefined;
197
203
  } | undefined;
198
204
  readonly optionsQuery?: string;
199
205
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
200
206
  readonly optionsAvailabilityQuery?: string;
207
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"system" | "tenant">[] | undefined;
201
208
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
202
209
  required: true;
203
210
  };
@@ -205,6 +212,7 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
205
212
  readonly type: "text";
206
213
  readonly description?: string;
207
214
  readonly maxLength?: number;
215
+ readonly minLength?: number;
208
216
  readonly required?: boolean;
209
217
  readonly searchable?: boolean;
210
218
  readonly sortable?: boolean;
@@ -234,13 +242,14 @@ export declare const templateResourceEntity: import("@cosmicdrift/kumiko-types/f
234
242
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
235
243
  readonly display?: "radio" | "dropdown";
236
244
  readonly optionTones?: {
237
- readonly active?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
238
- readonly archived?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
239
- readonly draft?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
245
+ readonly active?: "bad" | "neutral" | "ok" | "warn" | undefined;
246
+ readonly archived?: "bad" | "neutral" | "ok" | "warn" | undefined;
247
+ readonly draft?: "bad" | "neutral" | "ok" | "warn" | undefined;
240
248
  } | undefined;
241
249
  readonly optionsQuery?: string;
242
250
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
243
251
  readonly optionsAvailabilityQuery?: string;
252
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"active" | "archived" | "draft">[] | undefined;
244
253
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
245
254
  required: true;
246
255
  };
@@ -250,6 +259,7 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
250
259
  readonly type: "text";
251
260
  readonly description?: string;
252
261
  readonly maxLength?: number;
262
+ readonly minLength?: number;
253
263
  readonly required?: boolean;
254
264
  readonly searchable?: boolean;
255
265
  readonly sortable?: boolean;
@@ -279,16 +289,17 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
279
289
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
280
290
  readonly display?: "radio" | "dropdown";
281
291
  readonly optionTones?: {
282
- readonly "ai-prompt"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
283
- readonly "document-pdf"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
284
- readonly "image-snapshot"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
285
- readonly "mail-html"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
286
- readonly notification?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
287
- readonly "text-block"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
292
+ readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
293
+ readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
294
+ readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
295
+ readonly "mail-html"?: "bad" | "neutral" | "ok" | "warn" | undefined;
296
+ readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
297
+ readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
288
298
  } | undefined;
289
299
  readonly optionsQuery?: string;
290
300
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
291
301
  readonly optionsAvailabilityQuery?: string;
302
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block">[] | undefined;
292
303
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
293
304
  required: true;
294
305
  };
@@ -296,6 +307,7 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
296
307
  readonly type: "text";
297
308
  readonly description?: string;
298
309
  readonly maxLength?: number;
310
+ readonly minLength?: number;
299
311
  readonly required?: boolean;
300
312
  readonly searchable?: boolean;
301
313
  readonly sortable?: boolean;
@@ -317,6 +329,7 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
317
329
  readonly type: "text";
318
330
  readonly description?: string;
319
331
  readonly maxLength?: number;
332
+ readonly minLength?: number;
320
333
  readonly required?: boolean;
321
334
  readonly searchable?: boolean;
322
335
  readonly sortable?: boolean;
@@ -338,6 +351,7 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
338
351
  readonly type: "text";
339
352
  readonly description?: string;
340
353
  readonly maxLength?: number;
354
+ readonly minLength?: number;
341
355
  readonly required?: boolean;
342
356
  readonly searchable?: boolean;
343
357
  readonly sortable?: boolean;
@@ -383,14 +397,15 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
383
397
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
384
398
  readonly display?: "radio" | "dropdown";
385
399
  readonly optionTones?: {
386
- readonly html?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
387
- readonly markdown?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
388
- readonly mjml?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
389
- readonly plain?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
400
+ readonly html?: "bad" | "neutral" | "ok" | "warn" | undefined;
401
+ readonly markdown?: "bad" | "neutral" | "ok" | "warn" | undefined;
402
+ readonly mjml?: "bad" | "neutral" | "ok" | "warn" | undefined;
403
+ readonly plain?: "bad" | "neutral" | "ok" | "warn" | undefined;
390
404
  } | undefined;
391
405
  readonly optionsQuery?: string;
392
406
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
393
407
  readonly optionsAvailabilityQuery?: string;
408
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"html" | "markdown" | "mjml" | "plain">[] | undefined;
394
409
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
395
410
  required: true;
396
411
  };
@@ -438,12 +453,13 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
438
453
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
439
454
  readonly display?: "radio" | "dropdown";
440
455
  readonly optionTones?: {
441
- readonly system?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
442
- readonly tenant?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
456
+ readonly system?: "bad" | "neutral" | "ok" | "warn" | undefined;
457
+ readonly tenant?: "bad" | "neutral" | "ok" | "warn" | undefined;
443
458
  } | undefined;
444
459
  readonly optionsQuery?: string;
445
460
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
446
461
  readonly optionsAvailabilityQuery?: string;
462
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"system" | "tenant">[] | undefined;
447
463
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
448
464
  required: true;
449
465
  };
@@ -451,6 +467,7 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
451
467
  readonly type: "text";
452
468
  readonly description?: string;
453
469
  readonly maxLength?: number;
470
+ readonly minLength?: number;
454
471
  readonly required?: boolean;
455
472
  readonly searchable?: boolean;
456
473
  readonly sortable?: boolean;
@@ -480,13 +497,14 @@ export declare const templateResourcesTable: import("@cosmicdrift/kumiko-framewo
480
497
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
481
498
  readonly display?: "radio" | "dropdown";
482
499
  readonly optionTones?: {
483
- readonly active?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
484
- readonly archived?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
485
- readonly draft?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
500
+ readonly active?: "bad" | "neutral" | "ok" | "warn" | undefined;
501
+ readonly archived?: "bad" | "neutral" | "ok" | "warn" | undefined;
502
+ readonly draft?: "bad" | "neutral" | "ok" | "warn" | undefined;
486
503
  } | undefined;
487
504
  readonly optionsQuery?: string;
488
505
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
489
506
  readonly optionsAvailabilityQuery?: string;
507
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"active" | "archived" | "draft">[] | undefined;
490
508
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
491
509
  required: true;
492
510
  };
@@ -4,6 +4,7 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
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 const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
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;
@@ -54,16 +56,17 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
54
56
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
55
57
  readonly display?: "radio" | "dropdown";
56
58
  readonly optionTones?: {
57
- readonly "ai-prompt"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
58
- readonly "document-pdf"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
59
- readonly "image-snapshot"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
60
- readonly "mail-html"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
61
- readonly notification?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
62
- readonly "text-block"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
59
+ readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
60
+ readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
61
+ readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
62
+ readonly "mail-html"?: "bad" | "neutral" | "ok" | "warn" | undefined;
63
+ readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
64
+ readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
63
65
  } | undefined;
64
66
  readonly optionsQuery?: string;
65
67
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
66
68
  readonly optionsAvailabilityQuery?: string;
69
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block">[] | undefined;
67
70
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
68
71
  required: true;
69
72
  };
@@ -71,6 +74,7 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
71
74
  readonly type: "text";
72
75
  readonly description?: string;
73
76
  readonly maxLength?: number;
77
+ readonly minLength?: number;
74
78
  readonly required?: boolean;
75
79
  readonly searchable?: boolean;
76
80
  readonly sortable?: boolean;
@@ -92,6 +96,7 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
92
96
  readonly type: "text";
93
97
  readonly description?: string;
94
98
  readonly maxLength?: number;
99
+ readonly minLength?: number;
95
100
  readonly required?: boolean;
96
101
  readonly searchable?: boolean;
97
102
  readonly sortable?: boolean;
@@ -113,6 +118,7 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
113
118
  readonly type: "text";
114
119
  readonly description?: string;
115
120
  readonly maxLength?: number;
121
+ readonly minLength?: number;
116
122
  readonly required?: boolean;
117
123
  readonly searchable?: boolean;
118
124
  readonly sortable?: boolean;
@@ -158,14 +164,15 @@ export declare const userContentEntryEntity: import("@cosmicdrift/kumiko-types/f
158
164
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
159
165
  readonly display?: "radio" | "dropdown";
160
166
  readonly optionTones?: {
161
- readonly html?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
162
- readonly markdown?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
163
- readonly mjml?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
164
- readonly plain?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
167
+ readonly html?: "bad" | "neutral" | "ok" | "warn" | undefined;
168
+ readonly markdown?: "bad" | "neutral" | "ok" | "warn" | undefined;
169
+ readonly mjml?: "bad" | "neutral" | "ok" | "warn" | undefined;
170
+ readonly plain?: "bad" | "neutral" | "ok" | "warn" | undefined;
165
171
  } | undefined;
166
172
  readonly optionsQuery?: string;
167
173
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
168
174
  readonly optionsAvailabilityQuery?: string;
175
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"html" | "markdown" | "mjml" | "plain">[] | undefined;
169
176
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
170
177
  required: true;
171
178
  };
@@ -175,6 +182,7 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
175
182
  readonly type: "text";
176
183
  readonly description?: string;
177
184
  readonly maxLength?: number;
185
+ readonly minLength?: number;
178
186
  readonly required?: boolean;
179
187
  readonly searchable?: boolean;
180
188
  readonly sortable?: boolean;
@@ -196,6 +204,7 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
196
204
  readonly type: "text";
197
205
  readonly description?: string;
198
206
  readonly maxLength?: number;
207
+ readonly minLength?: number;
199
208
  readonly required?: boolean;
200
209
  readonly searchable?: boolean;
201
210
  readonly sortable?: boolean;
@@ -225,16 +234,17 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
225
234
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
226
235
  readonly display?: "radio" | "dropdown";
227
236
  readonly optionTones?: {
228
- readonly "ai-prompt"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
229
- readonly "document-pdf"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
230
- readonly "image-snapshot"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
231
- readonly "mail-html"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
232
- readonly notification?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
233
- readonly "text-block"?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
237
+ readonly "ai-prompt"?: "bad" | "neutral" | "ok" | "warn" | undefined;
238
+ readonly "document-pdf"?: "bad" | "neutral" | "ok" | "warn" | undefined;
239
+ readonly "image-snapshot"?: "bad" | "neutral" | "ok" | "warn" | undefined;
240
+ readonly "mail-html"?: "bad" | "neutral" | "ok" | "warn" | undefined;
241
+ readonly notification?: "bad" | "neutral" | "ok" | "warn" | undefined;
242
+ readonly "text-block"?: "bad" | "neutral" | "ok" | "warn" | undefined;
234
243
  } | undefined;
235
244
  readonly optionsQuery?: string;
236
245
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
237
246
  readonly optionsAvailabilityQuery?: string;
247
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"ai-prompt" | "document-pdf" | "image-snapshot" | "mail-html" | "notification" | "text-block">[] | undefined;
238
248
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
239
249
  required: true;
240
250
  };
@@ -242,6 +252,7 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
242
252
  readonly type: "text";
243
253
  readonly description?: string;
244
254
  readonly maxLength?: number;
255
+ readonly minLength?: number;
245
256
  readonly required?: boolean;
246
257
  readonly searchable?: boolean;
247
258
  readonly sortable?: boolean;
@@ -263,6 +274,7 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
263
274
  readonly type: "text";
264
275
  readonly description?: string;
265
276
  readonly maxLength?: number;
277
+ readonly minLength?: number;
266
278
  readonly required?: boolean;
267
279
  readonly searchable?: boolean;
268
280
  readonly sortable?: boolean;
@@ -284,6 +296,7 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
284
296
  readonly type: "text";
285
297
  readonly description?: string;
286
298
  readonly maxLength?: number;
299
+ readonly minLength?: number;
287
300
  readonly required?: boolean;
288
301
  readonly searchable?: boolean;
289
302
  readonly sortable?: boolean;
@@ -329,14 +342,15 @@ export declare const userContentEntriesTable: import("@cosmicdrift/kumiko-framew
329
342
  readonly access?: import("@cosmicdrift/kumiko-types/fields").FieldAccess;
330
343
  readonly display?: "radio" | "dropdown";
331
344
  readonly optionTones?: {
332
- readonly html?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
333
- readonly markdown?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
334
- readonly mjml?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
335
- readonly plain?: import("@cosmicdrift/kumiko-types/fields").SelectOptionTone | undefined;
345
+ readonly html?: "bad" | "neutral" | "ok" | "warn" | undefined;
346
+ readonly markdown?: "bad" | "neutral" | "ok" | "warn" | undefined;
347
+ readonly mjml?: "bad" | "neutral" | "ok" | "warn" | undefined;
348
+ readonly plain?: "bad" | "neutral" | "ok" | "warn" | undefined;
336
349
  } | undefined;
337
350
  readonly optionsQuery?: string;
338
351
  readonly optionsQueryPayload?: import("@cosmicdrift/kumiko-types/fields").OptionsQueryPayload;
339
352
  readonly optionsAvailabilityQuery?: string;
353
+ readonly conditionalOptions?: readonly import("@cosmicdrift/kumiko-types/fields").SelectConditionalOptions<"html" | "markdown" | "mjml" | "plain">[] | undefined;
340
354
  } & import("@cosmicdrift/kumiko-types/fields").ResolvedPiiFlags & {
341
355
  required: true;
342
356
  };
@@ -0,0 +1,3 @@
1
+ export declare function decryptTenantNames<T extends {
2
+ readonly name?: unknown;
3
+ }>(rows: readonly T[], fallbackRequestId: string): Promise<T[]>;
@@ -0,0 +1,10 @@
1
+ import { decryptStoredPii, mapWithConcurrency } from "../shared/index.js";
2
+ // Bounded like tenant:query:members: each decrypt hits the KMS adapter's small pool.
3
+ const KMS_POOL_CONCURRENCY = 4;
4
+ // Raw reads of read_tenants return the stored column, which is ciphertext
5
+ // under an active KMS; executor reads (crud.list/detail) decrypt on their own.
6
+ export async function decryptTenantNames(rows, fallbackRequestId) {
7
+ return mapWithConcurrency(rows, KMS_POOL_CONCURRENCY, async (row) => typeof row.name === "string"
8
+ ? { ...row, name: await decryptStoredPii(row.name, "name", fallbackRequestId) }
9
+ : row);
10
+ }
@@ -39,8 +39,14 @@ export function createTenantFeature(options) {
39
39
  r.systemScope();
40
40
  r.requires("config");
41
41
  r.extendsRegistrar(EXT_ASSIGNABLE_ROLE, {});
42
+ // The elevation guards read the registry, the screens only these options: a role the
43
+ // server accepts but the screen omits is silently stripped on the next member-roles save.
42
44
  r.bootCheck(({ features }) => {
43
- collectAssignableAppRoles(features);
45
+ for (const [role, assignableFrom] of collectAssignableAppRoles(features)) {
46
+ if (options?.assignableAppRoles?.get(role) === assignableFrom)
47
+ continue;
48
+ throw new Error(`[tenant] assignable app role "${role}" (assignableFrom "${assignableFrom}") is declared but missing from the tenant screens' options; pass assignableAppRoles: collectAssignableAppRoles(appFeatures) to createTenantFeature.`);
49
+ }
44
50
  });
45
51
  r.entity("tenant", tenantEntity);
46
52
  r.entity("tenant-membership", tenantMembershipEntity);
@@ -2,6 +2,7 @@ import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import * as z from "zod";
5
+ import { decryptTenantNames } from "../decrypt-tenant-names.js";
5
6
  import { tenantTable } from "../schema/tenant.js";
6
7
  // Direct query — query handlers don't have a tenant-crud handle. A direct
7
8
  // select is trivial: WHERE id = tenantId (both UUID). No CRUD detour needed.
@@ -28,6 +29,9 @@ export const meQuery = defineQueryHandler({
28
29
  }
29
30
  const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
30
31
  const row = await fetchOne(db, tenantTable, { id: query.user.tenantId });
31
- return row ?? null;
32
+ if (row === undefined)
33
+ return null;
34
+ const [decrypted] = await decryptTenantNames([row], "tenant:me");
35
+ return decrypted ?? null;
32
36
  },
33
37
  });
@@ -3,6 +3,7 @@ import { defineQueryHandler, SYSTEM_ROLE } from "@cosmicdrift/kumiko-framework/e
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
5
5
  import * as z from "zod";
6
+ import { decryptTenantNames } from "../decrypt-tenant-names.js";
6
7
  import { tenantMembershipsTable } from "../membership-table.js";
7
8
  import { tenantTable } from "../schema/tenant.js";
8
9
  export const membershipsQuery = defineQueryHandler({
@@ -22,9 +23,9 @@ export const membershipsQuery = defineQueryHandler({
22
23
  const rows = await selectMany(db, tenantMembershipsTable, { userId: query.payload.userId });
23
24
  if (rows.length === 0)
24
25
  return [];
25
- const tenants = await selectMany(db, tenantTable, {
26
+ const tenants = await decryptTenantNames(await selectMany(db, tenantTable, {
26
27
  id: rows.map((row) => row["tenantId"]),
27
- });
28
+ }), "tenant:memberships");
28
29
  const tenantById = new Map(tenants.map((t) => [t.id, t]));
29
30
  return rows
30
31
  .map((row) => {