@cosmicdrift/kumiko-framework 0.387.0 → 0.389.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 (375) hide show
  1. package/AGENTS.md +9 -1
  2. package/agents/examples/anonymous-access.md +1 -1
  3. package/agents/examples/apex-landing.md +204 -0
  4. package/agents/examples/api-worker-split.md +64 -0
  5. package/agents/examples/app-config.md +14 -0
  6. package/agents/examples/auth-mfa.md +115 -0
  7. package/agents/examples/env-composition.md +28 -1
  8. package/agents/examples/golden-path.md +13 -1
  9. package/agents/examples/legal-pages.md +1 -1
  10. package/agents/examples/lifecycle-hooks.md +55 -2
  11. package/agents/examples/list-table-options.md +466 -0
  12. package/agents/examples/pdf-audit-export.md +4 -2
  13. package/agents/examples/prod-boot-options.md +16 -0
  14. package/agents/examples/rate-limiting.md +48 -0
  15. package/agents/examples/record-detail-layout.md +692 -0
  16. package/agents/examples/seed-migration.md +212 -0
  17. package/agents/examples/state-machine.md +3 -2
  18. package/agents/examples/tenant-isolation.md +73 -1
  19. package/agents/examples/wizard-form.md +941 -0
  20. package/agents/examples/writeform-section.md +548 -0
  21. package/agents/examples.md +1 -0
  22. package/agents/features.md +19 -2
  23. package/agents/widgets.md +2 -0
  24. package/dist/api/api-constants.d.ts +1 -0
  25. package/dist/api/api-constants.js +2 -0
  26. package/dist/api/auth-routes-shared.d.ts +2 -0
  27. package/dist/api/auth-routes-shared.js +5 -0
  28. package/dist/api/client-error-route.js +10 -5
  29. package/dist/api/entity-read-access.d.ts +2 -1
  30. package/dist/api/entity-read-access.js +14 -0
  31. package/dist/api/export/export-cells-reference.d.ts +9 -0
  32. package/dist/api/export/export-cells-reference.js +21 -0
  33. package/dist/api/export/export-cells.d.ts +11 -0
  34. package/dist/api/export/export-cells.js +136 -0
  35. package/dist/api/export/export-ciphertext-guard.d.ts +2 -0
  36. package/dist/api/export/export-ciphertext-guard.js +27 -0
  37. package/dist/api/export/export-columns.d.ts +29 -0
  38. package/dist/api/export/export-columns.js +85 -0
  39. package/dist/api/export/export-errors.d.ts +4 -0
  40. package/dist/api/export/export-errors.js +14 -0
  41. package/dist/api/export/export-route.d.ts +4 -0
  42. package/dist/api/export/export-route.js +74 -0
  43. package/dist/api/export/export-rows.d.ts +13 -0
  44. package/dist/api/export/export-rows.js +62 -0
  45. package/dist/api/export/export-screen.d.ts +12 -0
  46. package/dist/api/export/export-screen.js +47 -0
  47. package/dist/api/export/export-xlsx-writer.d.ts +4 -0
  48. package/dist/api/export/export-xlsx-writer.js +21 -0
  49. package/dist/api/extra-route.d.ts +4 -0
  50. package/dist/api/index.d.ts +3 -1
  51. package/dist/api/index.js +3 -1
  52. package/dist/api/pii-leak-guard.d.ts +3 -0
  53. package/dist/api/pii-leak-guard.js +3 -2
  54. package/dist/api/request-context.d.ts +1 -1
  55. package/dist/api/request-context.js +1 -1
  56. package/dist/api/routes.d.ts +16 -0
  57. package/dist/api/routes.js +2 -2
  58. package/dist/api/server-boot-checks.d.ts +10 -0
  59. package/dist/api/server-boot-checks.js +157 -0
  60. package/dist/api/server-event-dispatcher.d.ts +26 -0
  61. package/dist/api/server-event-dispatcher.js +208 -0
  62. package/dist/api/server-extra-routes.d.ts +11 -0
  63. package/dist/api/server-extra-routes.js +206 -0
  64. package/dist/api/server-middleware.d.ts +20 -0
  65. package/dist/api/server-middleware.js +211 -0
  66. package/dist/api/server-routes.d.ts +19 -0
  67. package/dist/api/server-routes.js +299 -0
  68. package/dist/api/server-websocket-routes.d.ts +4 -0
  69. package/dist/api/server-websocket-routes.js +108 -0
  70. package/dist/api/server-wiring.d.ts +32 -0
  71. package/dist/api/server-wiring.js +238 -0
  72. package/dist/api/server.d.ts +10 -15
  73. package/dist/api/server.js +48 -1251
  74. package/dist/api/session-cookies.js +4 -4
  75. package/dist/api/sse-route.d.ts +2 -1
  76. package/dist/api/sse-route.js +27 -13
  77. package/dist/config/index.d.ts +3 -1
  78. package/dist/crypto/owner-transition-rekey.d.ts +5 -1
  79. package/dist/crypto/owner-transition-rekey.js +1 -1
  80. package/dist/crypto/pg-kms-adapter.d.ts +1 -0
  81. package/dist/crypto/pg-kms-adapter.js +12 -18
  82. package/dist/crypto/pii-field-encryption.d.ts +5 -1
  83. package/dist/crypto/pii-field-encryption.js +3 -1
  84. package/dist/db/aggregate-sql.d.ts +23 -0
  85. package/dist/db/aggregate-sql.js +165 -0
  86. package/dist/db/closed-connection.d.ts +9 -0
  87. package/dist/db/closed-connection.js +88 -0
  88. package/dist/db/connection.d.ts +4 -5
  89. package/dist/db/connection.js +29 -20
  90. package/dist/db/dialect.js +1 -1
  91. package/dist/db/distinct-on.d.ts +1 -1
  92. package/dist/db/driver-row-coercion.d.ts +2 -0
  93. package/dist/db/driver-row-coercion.js +186 -0
  94. package/dist/db/driver-value-preparation.d.ts +16 -0
  95. package/dist/db/driver-value-preparation.js +101 -0
  96. package/dist/db/entity-field-encryption.d.ts +1 -0
  97. package/dist/db/entity-field-encryption.js +1 -1
  98. package/dist/db/entity-table-meta.js +103 -110
  99. package/dist/db/event-store-executor-context.d.ts +2 -1
  100. package/dist/db/event-store-executor-read-aggregate-currencies.d.ts +17 -0
  101. package/dist/db/event-store-executor-read-aggregate-currencies.js +40 -0
  102. package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
  103. package/dist/db/event-store-executor-read-aggregate.js +143 -0
  104. package/dist/db/event-store-executor-read-filter.d.ts +31 -0
  105. package/dist/db/event-store-executor-read-filter.js +206 -0
  106. package/dist/db/event-store-executor-read-paging.d.ts +14 -0
  107. package/dist/db/event-store-executor-read-paging.js +99 -0
  108. package/dist/db/event-store-executor-read-rows.d.ts +6 -0
  109. package/dist/db/event-store-executor-read-rows.js +32 -0
  110. package/dist/db/event-store-executor-read-search.d.ts +28 -0
  111. package/dist/db/event-store-executor-read-search.js +221 -0
  112. package/dist/db/event-store-executor-read-sort.d.ts +41 -0
  113. package/dist/db/event-store-executor-read-sort.js +130 -0
  114. package/dist/db/event-store-executor-read-where.d.ts +24 -0
  115. package/dist/db/event-store-executor-read-where.js +81 -0
  116. package/dist/db/event-store-executor-read.d.ts +2 -9
  117. package/dist/db/event-store-executor-read.js +48 -701
  118. package/dist/db/event-store-executor-write-atomic.d.ts +4 -0
  119. package/dist/db/event-store-executor-write-atomic.js +41 -0
  120. package/dist/db/event-store-executor-write-steps.d.ts +17 -0
  121. package/dist/db/event-store-executor-write-steps.js +95 -0
  122. package/dist/db/event-store-executor-write.js +405 -509
  123. package/dist/db/event-store-executor.js +2 -1
  124. package/dist/db/executor-managed-tables.js +1 -1
  125. package/dist/db/index.d.ts +7 -3
  126. package/dist/db/index.js +6 -2
  127. package/dist/db/list-aggregate-labels.d.ts +14 -0
  128. package/dist/db/list-aggregate-labels.js +26 -0
  129. package/dist/db/migrate-generator.js +71 -86
  130. package/dist/db/migrate-runner.js +7 -4
  131. package/dist/db/pg-error.js +26 -21
  132. package/dist/db/queries/backfill-pii.js +3 -6
  133. package/dist/db/queries/database-now.js +2 -1
  134. package/dist/db/queries/shadow-swap.js +2 -3
  135. package/dist/db/query.d.ts +16 -15
  136. package/dist/db/query.js +76 -804
  137. package/dist/db/reference-data.js +19 -2
  138. package/dist/db/statement-timeout.js +2 -1
  139. package/dist/db/table-builder.js +113 -166
  140. package/dist/db/table-info.d.ts +10 -0
  141. package/dist/db/table-info.js +45 -0
  142. package/dist/db/temporal-value-guards.d.ts +6 -0
  143. package/dist/db/temporal-value-guards.js +15 -0
  144. package/dist/db/tenant-db-runner.d.ts +1 -0
  145. package/dist/db/tenant-db-runner.js +3 -0
  146. package/dist/db/tenant-db-upsert.d.ts +5 -0
  147. package/dist/db/tenant-db-upsert.js +91 -0
  148. package/dist/db/tenant-db.js +50 -10
  149. package/dist/db/where-clause.d.ts +6 -0
  150. package/dist/db/where-clause.js +236 -0
  151. package/dist/derivatives/delete-stored-file.js +2 -1
  152. package/dist/engine/boot-validator/boot-check.js +1 -1
  153. package/dist/engine/boot-validator/bundled-lists-table.d.ts +2 -0
  154. package/dist/engine/boot-validator/bundled-lists-table.js +36 -0
  155. package/dist/engine/boot-validator/detail-screens.js +2 -2
  156. package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
  157. package/dist/engine/boot-validator/entity-handler.js +17 -0
  158. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +3 -0
  159. package/dist/engine/boot-validator/entity-list-aggregate-options.js +23 -0
  160. package/dist/engine/boot-validator/form-derivations.js +35 -1
  161. package/dist/engine/boot-validator/i18n-keys.js +5 -3
  162. package/dist/engine/boot-validator/index.js +2 -0
  163. package/dist/engine/boot-validator/list-bulk-actions.d.ts +3 -0
  164. package/dist/engine/boot-validator/list-bulk-actions.js +49 -0
  165. package/dist/engine/boot-validator/list-column-layout.d.ts +8 -0
  166. package/dist/engine/boot-validator/list-column-layout.js +41 -0
  167. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +24 -0
  168. package/dist/engine/boot-validator/list-table-aggregate-options.js +145 -0
  169. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +10 -0
  170. package/dist/engine/boot-validator/list-table-aggregate-query.js +31 -0
  171. package/dist/engine/boot-validator/list-table-export-options.d.ts +1 -0
  172. package/dist/engine/boot-validator/list-table-export-options.js +27 -0
  173. package/dist/engine/boot-validator/list-table-options.d.ts +3 -0
  174. package/dist/engine/boot-validator/list-table-options.js +77 -0
  175. package/dist/engine/boot-validator/list-table-reject-unknown-keys.d.ts +1 -0
  176. package/dist/engine/boot-validator/list-table-reject-unknown-keys.js +7 -0
  177. package/dist/engine/boot-validator/pii-retention.js +233 -155
  178. package/dist/engine/boot-validator/projection-list-screens.d.ts +1 -1
  179. package/dist/engine/boot-validator/projection-list-screens.js +3 -13
  180. package/dist/engine/boot-validator/related-list-table-rules.d.ts +4 -0
  181. package/dist/engine/boot-validator/related-list-table-rules.js +42 -0
  182. package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
  183. package/dist/engine/boot-validator/screens-actions.js +8 -1
  184. package/dist/engine/boot-validator/screens-dashboard.js +2 -5
  185. package/dist/engine/boot-validator/screens-forms.js +2 -6
  186. package/dist/engine/boot-validator/screens-kind-config-edit.d.ts +3 -0
  187. package/dist/engine/boot-validator/screens-kind-config-edit.js +88 -0
  188. package/dist/engine/boot-validator/screens-kind-entity-edit.d.ts +3 -0
  189. package/dist/engine/boot-validator/screens-kind-entity-edit.js +55 -0
  190. package/dist/engine/boot-validator/screens-kind-entity-list.d.ts +3 -0
  191. package/dist/engine/boot-validator/screens-kind-entity-list.js +235 -0
  192. package/dist/engine/boot-validator/screens-kind-projection-detail.d.ts +3 -0
  193. package/dist/engine/boot-validator/screens-kind-projection-detail.js +235 -0
  194. package/dist/engine/boot-validator/screens-kind-projection-list.d.ts +3 -0
  195. package/dist/engine/boot-validator/screens-kind-projection-list.js +56 -0
  196. package/dist/engine/boot-validator/screens-kind-secret-mint.d.ts +3 -0
  197. package/dist/engine/boot-validator/screens-kind-secret-mint.js +28 -0
  198. package/dist/engine/boot-validator/screens-kind-shared.d.ts +37 -0
  199. package/dist/engine/boot-validator/screens-kind-shared.js +142 -0
  200. package/dist/engine/boot-validator/screens-lists.d.ts +2 -1
  201. package/dist/engine/boot-validator/screens-lists.js +24 -11
  202. package/dist/engine/boot-validator/screens.d.ts +0 -2
  203. package/dist/engine/boot-validator/screens.js +99 -860
  204. package/dist/engine/build-app-schema.d.ts +2 -1
  205. package/dist/engine/build-app-schema.js +65 -97
  206. package/dist/engine/build-config-feature-schema.js +6 -1
  207. package/dist/engine/define-feature.js +13 -2
  208. package/dist/engine/define-handler.js +1 -0
  209. package/dist/engine/entity-handlers.d.ts +13 -0
  210. package/dist/engine/entity-handlers.js +10 -21
  211. package/dist/engine/entity-list-runtime-options.d.ts +8 -0
  212. package/dist/engine/entity-list-runtime-options.js +18 -0
  213. package/dist/engine/feature-ast/extractors/handlers.js +1 -0
  214. package/dist/engine/feature-ast/extractors/index.d.ts +1 -1
  215. package/dist/engine/feature-ast/extractors/index.js +1 -1
  216. package/dist/engine/feature-ast/extractors/round1.d.ts +2 -1
  217. package/dist/engine/feature-ast/extractors/round1.js +6 -0
  218. package/dist/engine/feature-ast/extractors/round2.js +25 -6
  219. package/dist/engine/feature-ast/index.d.ts +1 -1
  220. package/dist/engine/feature-ast/parse.js +3 -1
  221. package/dist/engine/feature-ast/patch.d.ts +2 -0
  222. package/dist/engine/feature-ast/patch.js +5 -182
  223. package/dist/engine/feature-ast/pattern-change-schema.d.ts +10 -245
  224. package/dist/engine/feature-ast/pattern-change-schema.js +10 -163
  225. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
  226. package/dist/engine/feature-ast/pattern-id-matchers.js +211 -0
  227. package/dist/engine/feature-ast/pattern-id-schema.d.ts +251 -0
  228. package/dist/engine/feature-ast/pattern-id-schema.js +166 -0
  229. package/dist/engine/feature-ast/patterns.d.ts +14 -1
  230. package/dist/engine/feature-ast/patterns.js +44 -51
  231. package/dist/engine/feature-ast/render.js +52 -87
  232. package/dist/engine/feature-builder-state.d.ts +1 -0
  233. package/dist/engine/feature-builder-state.js +1 -0
  234. package/dist/engine/feature-entity-handlers.js +3 -0
  235. package/dist/engine/feature-manifest.d.ts +1 -0
  236. package/dist/engine/feature-manifest.js +1 -0
  237. package/dist/engine/field-access.d.ts +1 -0
  238. package/dist/engine/field-access.js +12 -0
  239. package/dist/engine/form-derivations.js +18 -7
  240. package/dist/engine/handler-field-references.js +1 -1
  241. package/dist/engine/index.d.ts +2 -2
  242. package/dist/engine/index.js +1 -1
  243. package/dist/engine/pattern-library/library.js +2 -1
  244. package/dist/engine/pattern-library/static-schemas.d.ts +1 -0
  245. package/dist/engine/pattern-library/static-schemas.js +9 -0
  246. package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
  247. package/dist/engine/project-app-schema-for-roles.js +6 -4
  248. package/dist/engine/registry-ingest.js +1 -1
  249. package/dist/engine/schema-builder.js +228 -212
  250. package/dist/engine/screen-filter-ops.js +2 -0
  251. package/dist/engine/screen-helpers.js +1 -1
  252. package/dist/engine/screen-kind.d.ts +7 -0
  253. package/dist/engine/screen-kind.js +1 -0
  254. package/dist/engine/strip-disabled-features-from-app-schema.js +58 -17
  255. package/dist/engine/types/feature.d.ts +1 -0
  256. package/dist/engine/types/index.d.ts +4 -3
  257. package/dist/engine/types/screen.d.ts +1 -1
  258. package/dist/engine/types/screen.js +1 -1
  259. package/dist/engine/validate-projection-allowlist.js +2 -1
  260. package/dist/entrypoint/index.d.ts +6 -1
  261. package/dist/entrypoint/index.js +10 -1
  262. package/dist/errors/docs-url.d.ts +1 -1
  263. package/dist/errors/docs-url.js +22 -2
  264. package/dist/es-ops/context.js +1 -1
  265. package/dist/event-store/admin-api.js +1 -1
  266. package/dist/event-store/event-store.d.ts +1 -0
  267. package/dist/event-store/event-store.js +17 -8
  268. package/dist/event-store/provenance-append.js +1 -1
  269. package/dist/files/bind-pending-file-refs.js +3 -3
  270. package/dist/files/create-file-ref-from-bytes.js +7 -1
  271. package/dist/files/create-file-ref.d.ts +3 -0
  272. package/dist/files/create-file-ref.js +11 -2
  273. package/dist/files/file-handle.js +2 -3
  274. package/dist/files/file-routes.d.ts +2 -0
  275. package/dist/files/file-routes.js +40 -10
  276. package/dist/files/provider-resolver.d.ts +1 -0
  277. package/dist/files/provider-resolver.js +1 -1
  278. package/dist/files/record-write-check.d.ts +6 -0
  279. package/dist/files/record-write-check.js +13 -0
  280. package/dist/files/resolve-content-type.js +43 -0
  281. package/dist/files/upload-ledger.d.ts +2 -2
  282. package/dist/files/upload-ledger.js +11 -4
  283. package/dist/i18n/required-surface-keys.js +189 -208
  284. package/dist/internal/stack-support.d.ts +2 -1
  285. package/dist/internal/stack-support.js +1 -1
  286. package/dist/internal/testing.js +1 -1
  287. package/dist/jobs/job-runner-context.d.ts +32 -0
  288. package/dist/jobs/job-runner-context.js +305 -0
  289. package/dist/jobs/job-runner-execution.d.ts +7 -0
  290. package/dist/jobs/job-runner-execution.js +160 -0
  291. package/dist/jobs/job-runner-gates.d.ts +19 -0
  292. package/dist/jobs/job-runner-gates.js +198 -0
  293. package/dist/jobs/job-runner-helpers.d.ts +17 -3
  294. package/dist/jobs/job-runner-helpers.js +61 -2
  295. package/dist/jobs/job-runner-scope.d.ts +44 -0
  296. package/dist/jobs/job-runner-scope.js +102 -0
  297. package/dist/jobs/job-runner-types.d.ts +12 -0
  298. package/dist/jobs/job-runner.d.ts +0 -1
  299. package/dist/jobs/job-runner.js +50 -657
  300. package/dist/observability/escape-hatch-report.d.ts +3 -0
  301. package/dist/observability/escape-hatch-report.js +21 -3
  302. package/dist/pipeline/after-rollback-sink.d.ts +6 -0
  303. package/dist/pipeline/after-rollback-sink.js +32 -0
  304. package/dist/pipeline/cascade-handler.js +165 -138
  305. package/dist/pipeline/dispatch-batch.js +8 -1
  306. package/dist/pipeline/dispatch-query.js +10 -3
  307. package/dist/pipeline/dispatch-shared.d.ts +13 -3
  308. package/dist/pipeline/dispatch-shared.js +62 -710
  309. package/dist/pipeline/dispatch-write.js +296 -189
  310. package/dist/pipeline/event-dispatcher-admin.js +2 -1
  311. package/dist/pipeline/event-dispatcher-delivery.js +6 -6
  312. package/dist/pipeline/event-dispatcher.d.ts +1 -0
  313. package/dist/pipeline/event-dispatcher.js +6 -9
  314. package/dist/pipeline/handler-context-auth.d.ts +9 -0
  315. package/dist/pipeline/handler-context-auth.js +54 -0
  316. package/dist/pipeline/handler-context-config.d.ts +14 -0
  317. package/dist/pipeline/handler-context-config.js +113 -0
  318. package/dist/pipeline/handler-context-db.d.ts +24 -0
  319. package/dist/pipeline/handler-context-db.js +149 -0
  320. package/dist/pipeline/handler-context-dispatch.d.ts +23 -0
  321. package/dist/pipeline/handler-context-dispatch.js +101 -0
  322. package/dist/pipeline/handler-context-events.d.ts +41 -0
  323. package/dist/pipeline/handler-context-events.js +239 -0
  324. package/dist/pipeline/handler-context-notify.d.ts +12 -0
  325. package/dist/pipeline/handler-context-notify.js +55 -0
  326. package/dist/pipeline/handler-context-observability.d.ts +7 -0
  327. package/dist/pipeline/handler-context-observability.js +21 -0
  328. package/dist/pipeline/handler-context-scope.d.ts +48 -0
  329. package/dist/pipeline/handler-context-scope.js +88 -0
  330. package/dist/pipeline/notify-scope.js +12 -1
  331. package/dist/pipeline/pre-handler-gates.js +20 -4
  332. package/dist/pipeline/pre-transaction-reservations.d.ts +1 -0
  333. package/dist/pipeline/pre-transaction-reservations.js +9 -3
  334. package/dist/pipeline/projection-rebuild.js +2 -1
  335. package/dist/pipeline/system-hooks.d.ts +3 -1
  336. package/dist/pipeline/system-hooks.js +55 -6
  337. package/dist/pipeline/write-result-masking.js +13 -10
  338. package/dist/schema-cli/apply-command.d.ts +2 -0
  339. package/dist/schema-cli/apply-command.js +97 -0
  340. package/dist/schema-cli/baseline-command.d.ts +2 -0
  341. package/dist/schema-cli/baseline-command.js +33 -0
  342. package/dist/schema-cli/generate-command.d.ts +2 -0
  343. package/dist/schema-cli/generate-command.js +90 -0
  344. package/dist/schema-cli/shared.d.ts +39 -0
  345. package/dist/schema-cli/shared.js +95 -0
  346. package/dist/schema-cli/status-command.d.ts +2 -0
  347. package/dist/schema-cli/status-command.js +73 -0
  348. package/dist/schema-cli/validate-boot-input.d.ts +5 -0
  349. package/dist/schema-cli/validate-boot-input.js +130 -0
  350. package/dist/schema-cli/validate-command.d.ts +2 -0
  351. package/dist/schema-cli/validate-command.js +130 -0
  352. package/dist/schema-cli.d.ts +2 -18
  353. package/dist/schema-cli.js +47 -604
  354. package/dist/search/meilisearch-adapter.js +2 -1
  355. package/dist/search/reindex-entity.js +15 -5
  356. package/dist/ui-types/index.d.ts +2 -2
  357. package/dist/ui-types/index.js +1 -1
  358. package/dist/upgrade-changelog.d.ts +2 -0
  359. package/dist/upgrade-changelog.js +14 -0
  360. package/dist/upgrade-cli.d.ts +3 -12
  361. package/dist/upgrade-cli.js +171 -197
  362. package/dist/upgrade-marker-parse.d.ts +32 -0
  363. package/dist/upgrade-marker-parse.js +73 -0
  364. package/package.json +9 -6
  365. package/src/changes.json +555 -0
  366. package/src/scripts/codemod/codemod-support.ts +1 -1
  367. package/src/scripts/codemod/db-factory.ts +1 -1
  368. package/src/scripts/codemod/feature-layout.ts +10 -2
  369. package/src/scripts/codemod/object-form.ts +41 -4
  370. package/src/scripts/codemod/package-merge.ts +58 -8
  371. package/src/scripts/codemod/pii-personal-migration.ts +175 -145
  372. package/src/scripts/codemod/testing-injection.ts +122 -42
  373. package/src/scripts/codemod/testing-move.ts +29 -7
  374. package/dist/engine/provider-plugin-context.d.ts +0 -3
  375. package/dist/engine/provider-plugin-context.js +0 -28
@@ -9,16 +9,17 @@ import { createProjectingTenantDb } from "../db/tenant-db.js";
9
9
  import { createDerivativesContext, resolveFieldVariant, resolveRenderer, } from "../derivatives/index.js";
10
10
  import { isAnonymousSessionUser, SYSTEM_USER_ID } from "../engine/system-user.js";
11
11
  import { isFileField, isUuid, } from "../engine/types/index.js";
12
+ import { createFailOpenReporter, respondRateLimited } from "../rate-limit/middleware.js";
12
13
  import { listActionFormFileFields, mayUseActionForm } from "./action-form-upload.js";
13
14
  import { buildContentDispositionHeader } from "./content-disposition.js";
14
15
  import { DEFAULT_MAX_UPLOAD_SIZE, getFileRefExecutor, storeFileAsFileRef, } from "./create-file-ref.js";
15
- import { createFileContext } from "./file-handle.js";
16
+ import { createFileContext, createTenantFileContext } from "./file-handle.js";
16
17
  import { fileRefEntity } from "./file-ref-entity.js";
17
18
  import { fileRefsTable } from "./file-ref-table.js";
18
- import { RecordWriteDecisions } from "./record-write-check.js";
19
+ import { isStoredRecordLocked, RecordWriteDecisions, } from "./record-write-check.js";
19
20
  import { neutralFileNameForMimeType } from "./resolve-content-type.js";
20
21
  import { parseMaxSize, resolveServedContentType } from "./types.js";
21
- import { createFileUploadLedger } from "./upload-ledger.js";
22
+ import { withUploadLedger } from "./upload-ledger.js";
22
23
  // Exactly the httpStatus values declared by KumikoError subclasses across packages/*.
23
24
  const ERROR_STATUSES = [400, 401, 403, 404, 409, 422, 429, 500, 503, 504];
24
25
  export function deleteFailureResponseFor(error) {
@@ -31,6 +32,8 @@ const DEFAULT_PRIVILEGED_ROLES = ["Admin", "SystemAdmin"];
31
32
  // credential (see "Signed-URL default expiry" in core-files.md).
32
33
  const SIGNED_URL_DEFAULT_EXPIRY_SECONDS = 15 * 60;
33
34
  const MAX_BATCH_META_IDS = 100;
35
+ const META_BATCH_IDS_PER_WINDOW = 1_000;
36
+ const META_BATCH_WINDOW_SECONDS = 60;
34
37
  // Each detail() read decrypts through the KMS pool; a bounded chunk keeps one batch from hogging it.
35
38
  const BATCH_META_CONCURRENCY = 10;
36
39
  // Default guard: on attached files, allow the uploader or a privileged role,
@@ -101,7 +104,12 @@ export function readFilesRouteOptions(registry) {
101
104
  return {};
102
105
  }
103
106
  export function createFileRoutes(options) {
104
- const { db } = options;
107
+ const { db, metaBatchRateLimitResolver } = options;
108
+ const reportMetaBatchLimiterFailOpen = createFailOpenReporter("files-meta-batch");
109
+ // Plain resolvers (not built via withFileProviderResolver) get the ledger on the route's own root connection.
110
+ const resolveProvider = options.resolveProvider.uploadLedgerFor
111
+ ? options.resolveProvider
112
+ : withUploadLedger(options.resolveProvider, db);
105
113
  const privilegedRoles = options.privilegedRoles ?? DEFAULT_PRIVILEGED_ROLES;
106
114
  const guard = options.accessGuard ??
107
115
  createDefaultGuard(privilegedRoles, options.canReadRecord, options.unclaimedUploadReaders ?? []);
@@ -200,19 +208,23 @@ export function createFileRoutes(options) {
200
208
  }
201
209
  }
202
210
  const data = new Uint8Array(await file.arrayBuffer());
203
- const storageProvider = await options.resolveProvider(user.tenantId);
204
- const uploadLedger = createFileUploadLedger(db, user.tenantId);
211
+ const files = createTenantFileContext(resolveProvider, user.tenantId);
212
+ const { registry } = options;
213
+ const isAttachTargetLocked = registry !== undefined && entityType !== undefined && entityId !== undefined
214
+ ? (rowDb) => isStoredRecordLocked({ registry, db: rowDb, entityType, entityId })
215
+ : undefined;
205
216
  const outcome = await storeFileAsFileRef({
206
217
  user,
207
218
  tenantDb: tenantDbFor(user.tenantId),
208
219
  rowInOwnTransaction: true,
209
220
  registry: options.registry,
210
221
  defaultMaxUploadSize: options.maxUploadSize ?? DEFAULT_MAX_UPLOAD_SIZE,
211
- writeBytes: async (key, bytes, mimeType) => {
212
- await uploadLedger.record(key);
213
- await storageProvider.write(key, bytes, mimeType);
222
+ writeBytes: (key, bytes, mimeType) => files.writeUploadBytes(key, bytes, mimeType),
223
+ deleteBytes: async (key) => {
224
+ await files.ref(key).delete();
225
+ await files.forgetUploadBytes(key);
214
226
  },
215
- deleteBytes: (key) => storageProvider.delete(key),
227
+ ...(isAttachTargetLocked ? { isAttachTargetLocked } : {}),
216
228
  }, {
217
229
  fileName: file.name,
218
230
  declaredMimeType: file.type,
@@ -224,6 +236,9 @@ export function createFileRoutes(options) {
224
236
  });
225
237
  if (outcome.kind === "rejected")
226
238
  return c.json({ error: outcome.error }, 400);
239
+ if (outcome.kind === "target-locked") {
240
+ return c.json({ error: "record_locked: the record is locked" }, 409);
241
+ }
227
242
  if (outcome.kind === "failed")
228
243
  return c.json({ error: "upload_failed" }, 500);
229
244
  return c.json(outcome.fileRef, 201);
@@ -237,6 +252,21 @@ export function createFileRoutes(options) {
237
252
  const ids = [...new Set((c.req.query("ids") ?? "").split(",").filter((id) => isUuid(id)))];
238
253
  if (ids.length > MAX_BATCH_META_IDS)
239
254
  return c.json({ error: "too_many_ids" }, 400);
255
+ if (metaBatchRateLimitResolver && ids.length > 0) {
256
+ const bucket = `files-meta:${user.tenantId}:${user.id}`;
257
+ try {
258
+ const decision = await metaBatchRateLimitResolver.check(bucket, {
259
+ limit: META_BATCH_IDS_PER_WINDOW,
260
+ windowSeconds: META_BATCH_WINDOW_SECONDS,
261
+ cost: ids.length,
262
+ });
263
+ if (!decision.allowed)
264
+ return respondRateLimited(c, decision, bucket);
265
+ }
266
+ catch (e) {
267
+ reportMetaBatchLimiterFailOpen(e);
268
+ }
269
+ }
240
270
  const files = [];
241
271
  for (let start = 0; start < ids.length; start += BATCH_META_CONCURRENCY) {
242
272
  const chunk = ids.slice(start, start + BATCH_META_CONCURRENCY);
@@ -56,5 +56,6 @@ export type FileProviderResolverDeps = {
56
56
  readonly secrets?: SecretsContext;
57
57
  readonly db?: DbConnection | TenantDb;
58
58
  readonly cacheSync?: CacheSyncBus;
59
+ readonly now?: () => Temporal.Instant;
59
60
  };
60
61
  export declare function makeFileProviderResolver(deps: FileProviderResolverDeps): FileProviderResolver;
@@ -119,5 +119,5 @@ export function makeFileProviderResolver(deps) {
119
119
  cache.set(tenantId, built);
120
120
  return built;
121
121
  };
122
- return deps.db ? withUploadLedger(resolveProvider, deps.db) : resolveProvider;
122
+ return deps.db ? withUploadLedger(resolveProvider, deps.db, deps.now) : resolveProvider;
123
123
  }
@@ -20,3 +20,9 @@ export declare function createRecordWriteCheck(args: {
20
20
  readonly canReadRecord: RecordReadCheck;
21
21
  readonly tenantDbFor: (tenantId: TenantId) => TenantDb;
22
22
  }): RecordWriteCheck;
23
+ export declare function isStoredRecordLocked(args: {
24
+ readonly registry: Registry;
25
+ readonly db: TenantDb;
26
+ readonly entityType: string;
27
+ readonly entityId: string;
28
+ }): Promise<boolean>;
@@ -62,3 +62,16 @@ export function createRecordWriteCheck(args) {
62
62
  return RecordWriteDecisions.writable;
63
63
  };
64
64
  }
65
+ // The stored row, read through the given db so a transaction sees the lock state it commits against.
66
+ export async function isStoredRecordLocked(args) {
67
+ const { registry, db, entityType, entityId } = args;
68
+ const entity = registry.getEntity(entityType);
69
+ const table = findImplicitEntityTable(registry, entityType);
70
+ if (!entity || !table || entity.lockedWhen === undefined)
71
+ return false;
72
+ const row = await db.fetchOne(table, {
73
+ id: entityId,
74
+ ...(entity.softDelete === true && { isDeleted: false }),
75
+ });
76
+ return row !== undefined && isRecordLocked(entity.lockedWhen, row);
77
+ }
@@ -46,6 +46,49 @@ const NON_XML_ROOT_ELEMENTS = new Set([
46
46
  "article",
47
47
  "font",
48
48
  "center",
49
+ "form",
50
+ "iframe",
51
+ "input",
52
+ "button",
53
+ "nav",
54
+ "header",
55
+ "footer",
56
+ "main",
57
+ "pre",
58
+ "code",
59
+ "b",
60
+ "i",
61
+ "strong",
62
+ "em",
63
+ "label",
64
+ "textarea",
65
+ "select",
66
+ "fieldset",
67
+ "legend",
68
+ "tr",
69
+ "td",
70
+ "th",
71
+ "thead",
72
+ "tbody",
73
+ "tfoot",
74
+ "object",
75
+ "embed",
76
+ "video",
77
+ "audio",
78
+ "canvas",
79
+ "math",
80
+ "picture",
81
+ "figure",
82
+ "figcaption",
83
+ "blockquote",
84
+ "dl",
85
+ "dt",
86
+ "dd",
87
+ "aside",
88
+ "details",
89
+ "summary",
90
+ "dialog",
91
+ "noscript",
49
92
  ]);
50
93
  const ROOT_ELEMENT_PATTERN = /^<(?:[A-Za-z_][\w.-]*:)?([A-Za-z_][\w.-]*)/;
51
94
  const EXTENSION_FALLBACK = {
@@ -5,6 +5,6 @@ import type { TenantId } from "@cosmicdrift/kumiko-types/identifiers";
5
5
  import type { DbConnection } from "../db/connection.ts";
6
6
  import { type TenantDb } from "../db/tenant-db.ts";
7
7
  export declare const fileUploadLedgerTable: WritableTable;
8
- export declare function createFileUploadLedger(db: DbConnection | TenantDb, tenantId: TenantId): FileUploadLedger;
9
- export declare function withUploadLedger(resolver: (tenantId: TenantId) => Promise<FileStorageProvider>, db: DbConnection | TenantDb): FileProviderResolver;
8
+ export declare function createFileUploadLedger(db: DbConnection | TenantDb, tenantId: TenantId, now?: () => Temporal.Instant): FileUploadLedger;
9
+ export declare function withUploadLedger(resolver: (tenantId: TenantId) => Promise<FileStorageProvider>, db: DbConnection | TenantDb, now?: () => Temporal.Instant): FileProviderResolver;
10
10
  export declare function takeUploadLedgerEntry(txDb: TenantDb, storageKey: string): Promise<boolean>;
@@ -1,6 +1,8 @@
1
1
  import { defineUnmanagedTable } from "../db/entity-table-meta.js";
2
+ import { runnerCanBeginTransaction } from "../db/query.js";
2
3
  import { createTenantDb } from "../db/tenant-db.js";
3
4
  import { tenantDbRunner } from "../db/tenant-db-runner.js";
5
+ import { InternalError } from "../errors/index.js";
4
6
  const CREATED_AT_INDEX = "store_file_upload_ledger_created_at_idx";
5
7
  // One row per upload whose bytes are in storage but whose fileRef row is not committed yet. The
6
8
  // commit path deletes it inside the transaction that creates the fileRef; the sweep finds the
@@ -19,15 +21,20 @@ function isTenantDb(db) {
19
21
  }
20
22
  // The ledger writes on a connection of its own, never on a handler transaction: a rollback of the
21
23
  // handler must not take the row with it, or the bytes it uploaded would be unfindable.
22
- export function createFileUploadLedger(db, tenantId) {
24
+ export function createFileUploadLedger(db, tenantId, now = () => Temporal.Now.instant()) {
23
25
  const runner = isTenantDb(db) ? tenantDbRunner(db) : db;
26
+ if (!runnerCanBeginTransaction(runner)) {
27
+ throw new InternalError({
28
+ message: "createFileUploadLedger: the connection is already inside a transaction; the ledger row would roll back with it and the uploaded bytes become unfindable",
29
+ });
30
+ }
24
31
  const ledgerDb = createTenantDb({ db: runner, tenantId });
25
32
  return {
26
33
  record: async (storageKey) => {
27
34
  await ledgerDb.insertOne(fileUploadLedgerTable, {
28
35
  storageKey,
29
36
  tenantId,
30
- createdAt: Temporal.Now.instant(),
37
+ createdAt: now(),
31
38
  });
32
39
  },
33
40
  forget: async (storageKey) => {
@@ -35,9 +42,9 @@ export function createFileUploadLedger(db, tenantId) {
35
42
  },
36
43
  };
37
44
  }
38
- export function withUploadLedger(resolver, db) {
45
+ export function withUploadLedger(resolver, db, now) {
39
46
  return Object.assign(resolver, {
40
- uploadLedgerFor: (tenantId) => createFileUploadLedger(db, tenantId),
47
+ uploadLedgerFor: (tenantId) => createFileUploadLedger(db, tenantId, now),
41
48
  });
42
49
  }
43
50
  // Runs inside the transaction that creates the fileRef row. False means no ledger row was left to