@cosmicdrift/kumiko-framework 0.389.0 → 0.390.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 (616) hide show
  1. package/AGENTS.md +9 -4
  2. package/README.md +1 -1
  3. package/agents/examples/apex-surface-auth.md +2 -3
  4. package/agents/examples/api-worker-split.md +9 -2
  5. package/agents/examples/auth-claims.md +1 -1
  6. package/agents/examples/cross-feature-events.md +12 -12
  7. package/agents/examples/crypto-shredding-hr.md +2 -2
  8. package/agents/examples/encrypted-tenant-config.md +1 -1
  9. package/agents/examples/error-contract.md +12 -7
  10. package/agents/examples/event-sourcing.md +29 -29
  11. package/agents/examples/files-post-processing.md +10 -8
  12. package/agents/examples/inbound-mail-triage.md +1 -0
  13. package/agents/examples/lane-routing.md +2 -1
  14. package/agents/examples/legal-pages.md +2 -2
  15. package/agents/examples/lifecycle-hooks.md +3 -3
  16. package/agents/examples/managed-config.md +4 -4
  17. package/agents/examples/managed-pages.md +1 -1
  18. package/agents/examples/relations.md +19 -4
  19. package/agents/examples/search.md +4 -4
  20. package/agents/examples/secrets-demo.md +9 -6
  21. package/agents/examples/state-machine.md +2 -2
  22. package/agents/examples/tenant-settings.md +1 -1
  23. package/agents/examples/user-data-rights.md +3 -6
  24. package/agents/examples/workflow-engine.md +53 -47
  25. package/agents/examples.md +4 -4
  26. package/agents/features.md +1 -1
  27. package/dist/api/auth-middleware.js +1 -1
  28. package/dist/api/auth-routes-invite.js +2 -1
  29. package/dist/api/entity-read-access.d.ts +3 -1
  30. package/dist/api/export/export-columns.d.ts +3 -1
  31. package/dist/api/export/export-route.js +3 -2
  32. package/dist/api/export/export-screen.d.ts +2 -1
  33. package/dist/api/extra-route.d.ts +3 -1
  34. package/dist/api/index.d.ts +23 -27
  35. package/dist/api/index.js +13 -15
  36. package/dist/api/jwt.js +1 -1
  37. package/dist/api/observability-middleware.d.ts +1 -1
  38. package/dist/api/observability-middleware.js +2 -1
  39. package/dist/api/request-context-internals.d.ts +31 -0
  40. package/dist/api/request-context-internals.js +11 -0
  41. package/dist/api/request-context-scopes.d.ts +14 -0
  42. package/dist/api/request-context-scopes.js +69 -0
  43. package/dist/api/request-context.d.ts +1 -40
  44. package/dist/api/request-context.js +22 -51
  45. package/dist/api/request-id-middleware.d.ts +1 -1
  46. package/dist/api/route-registrars.d.ts +2 -1
  47. package/dist/api/route-registrars.js +1 -1
  48. package/dist/api/routes.js +7 -3
  49. package/dist/api/server-boot-checks.d.ts +1 -1
  50. package/dist/api/server-boot-checks.js +2 -2
  51. package/dist/api/server-event-dispatcher.d.ts +6 -1
  52. package/dist/api/server-event-dispatcher.js +3 -4
  53. package/dist/api/server-extra-routes.d.ts +1 -1
  54. package/dist/api/server-extra-routes.js +2 -1
  55. package/dist/api/server-middleware.js +3 -1
  56. package/dist/api/server-routes.d.ts +2 -1
  57. package/dist/api/server-wiring.js +6 -4
  58. package/dist/api/server.d.ts +2 -1
  59. package/dist/api/sse-route.d.ts +2 -1
  60. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  61. package/dist/api/tenant-scoped-secrets.js +13 -0
  62. package/dist/api/websocket-route.d.ts +1 -1
  63. package/dist/auth/index.d.ts +0 -1
  64. package/dist/auth/roles.d.ts +0 -5
  65. package/dist/compliance/duration-spec.d.ts +0 -1
  66. package/dist/compliance/duration-spec.js +0 -5
  67. package/dist/compliance/index.d.ts +4 -4
  68. package/dist/compliance/index.js +2 -2
  69. package/dist/compliance/profiles.d.ts +0 -15
  70. package/dist/compliance/profiles.js +0 -23
  71. package/dist/config/index.d.ts +10 -10
  72. package/dist/config/index.js +13 -1
  73. package/dist/config/internals.d.ts +9 -0
  74. package/dist/config/internals.js +1 -0
  75. package/dist/consumer-cli-internals.d.ts +4 -0
  76. package/dist/consumer-cli-internals.js +1 -0
  77. package/dist/consumer-cli.d.ts +1 -4
  78. package/dist/consumer-cli.js +5 -1
  79. package/dist/crypto/event-pii.js +1 -1
  80. package/dist/crypto/index.d.ts +8 -9
  81. package/dist/crypto/index.js +7 -8
  82. package/dist/crypto/pg-kms-adapter.js +6 -1
  83. package/dist/db/apply-entity-event.d.ts +1 -1
  84. package/dist/db/apply-entity-event.js +15 -47
  85. package/dist/db/blind-index-cleanup.js +91 -77
  86. package/dist/db/collect-table-metas.js +1 -1
  87. package/dist/db/compound-types.d.ts +1 -1
  88. package/dist/db/compound-types.js +0 -7
  89. package/dist/db/config-seed.d.ts +2 -1
  90. package/dist/db/config-seed.js +6 -1
  91. package/dist/db/connection.d.ts +3 -1
  92. package/dist/db/connection.js +15 -5
  93. package/dist/db/cross-tenant-reads.d.ts +1 -1
  94. package/dist/db/cross-tenant-reads.js +1 -1
  95. package/dist/db/dialect.d.ts +0 -5
  96. package/dist/db/dialect.js +0 -3
  97. package/dist/db/eagerload.d.ts +2 -1
  98. package/dist/db/entity-field-encryption.d.ts +1 -1
  99. package/dist/db/entity-table-meta.d.ts +1 -1
  100. package/dist/db/event-store-executor-context.d.ts +3 -1
  101. package/dist/db/event-store-executor-context.js +4 -3
  102. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  103. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  104. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  105. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  106. package/dist/db/event-store-executor-read.js +2 -2
  107. package/dist/db/event-store-executor-write-atomic.js +8 -7
  108. package/dist/db/event-store-executor-write-steps.d.ts +3 -2
  109. package/dist/db/event-store-executor-write.js +7 -4
  110. package/dist/db/event-store-executor.d.ts +1 -1
  111. package/dist/db/executor-managed-tables.d.ts +7 -1
  112. package/dist/db/executor-managed-tables.js +11 -2
  113. package/dist/db/index.d.ts +29 -28
  114. package/dist/db/index.js +22 -20
  115. package/dist/db/known-table-names.d.ts +6 -0
  116. package/dist/db/known-table-names.js +21 -0
  117. package/dist/db/list-aggregate-labels.d.ts +1 -1
  118. package/dist/db/located-timestamp.d.ts +1 -1
  119. package/dist/db/located-timestamp.js +0 -5
  120. package/dist/db/migrate-generator.d.ts +17 -1
  121. package/dist/db/migrate-generator.js +50 -20
  122. package/dist/db/migrate-primary-key.d.ts +12 -0
  123. package/dist/db/migrate-primary-key.js +45 -0
  124. package/dist/db/migrate-rls-diff.d.ts +20 -0
  125. package/dist/db/migrate-rls-diff.js +61 -0
  126. package/dist/db/migrate-runner.js +4 -0
  127. package/dist/db/money.d.ts +1 -1
  128. package/dist/db/money.js +1 -1
  129. package/dist/db/parent-ref-clause.d.ts +2 -1
  130. package/dist/db/pg-error.d.ts +2 -0
  131. package/dist/db/pg-error.js +11 -0
  132. package/dist/db/queries/ddl.d.ts +3 -0
  133. package/dist/db/queries/ddl.js +34 -1
  134. package/dist/db/queries/event-store.js +4 -2
  135. package/dist/db/queries/event-tenants.d.ts +2 -0
  136. package/dist/db/queries/event-tenants.js +17 -0
  137. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  138. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  139. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  140. package/dist/db/queries/rls-boot-catalog.js +39 -0
  141. package/dist/db/queries/rls-catalog.d.ts +6 -0
  142. package/dist/db/queries/rls-catalog.js +82 -0
  143. package/dist/db/queries/rls-scope.d.ts +3 -0
  144. package/dist/db/queries/rls-scope.js +17 -0
  145. package/dist/db/queries/rls-shape.d.ts +10 -0
  146. package/dist/db/queries/rls-shape.js +42 -0
  147. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  148. package/dist/db/queries/session-advisory-lock.js +23 -0
  149. package/dist/db/queries/shadow-swap.d.ts +1 -2
  150. package/dist/db/queries/shadow-swap.js +9 -25
  151. package/dist/db/queries/test-stack.d.ts +4 -1
  152. package/dist/db/queries/test-stack.js +83 -2
  153. package/dist/db/query.js +11 -7
  154. package/dist/db/reference-data.d.ts +1 -1
  155. package/dist/db/reference-data.js +6 -1
  156. package/dist/db/render-ddl.d.ts +6 -2
  157. package/dist/db/render-ddl.js +7 -7
  158. package/dist/db/render-rls-ddl.d.ts +35 -0
  159. package/dist/db/render-rls-ddl.js +127 -0
  160. package/dist/db/replay-migration-sql.d.ts +3 -1
  161. package/dist/db/replay-migration-sql.js +22 -5
  162. package/dist/db/replay-rls.d.ts +25 -0
  163. package/dist/db/replay-rls.js +156 -0
  164. package/dist/db/row-level-security-boot-check.d.ts +5 -0
  165. package/dist/db/row-level-security-boot-check.js +85 -0
  166. package/dist/db/row-level-security-connection.d.ts +3 -0
  167. package/dist/db/row-level-security-connection.js +213 -0
  168. package/dist/db/row-level-security-scope.d.ts +33 -0
  169. package/dist/db/row-level-security-scope.js +127 -0
  170. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  171. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  172. package/dist/db/sql-identifier.d.ts +1 -0
  173. package/dist/db/sql-identifier.js +3 -0
  174. package/dist/db/table-builder.d.ts +2 -1
  175. package/dist/db/table-builder.js +1 -1
  176. package/dist/db/table-info.js +1 -1
  177. package/dist/db/table-push.d.ts +11 -2
  178. package/dist/db/table-push.js +15 -2
  179. package/dist/db/tenant-db-runner.d.ts +3 -1
  180. package/dist/db/tenant-db-runner.js +4 -3
  181. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  182. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  183. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  184. package/dist/db/tenant-db-statement-runner.js +48 -0
  185. package/dist/db/tenant-db.d.ts +17 -12
  186. package/dist/db/tenant-db.js +49 -120
  187. package/dist/db/tenant-id-filter.d.ts +3 -0
  188. package/dist/db/tenant-id-filter.js +30 -0
  189. package/dist/db/transaction-serialization.d.ts +6 -0
  190. package/dist/db/transaction-serialization.js +60 -0
  191. package/dist/derivatives/delete-stored-file.js +1 -1
  192. package/dist/derivatives/index.d.ts +2 -5
  193. package/dist/derivatives/index.js +2 -3
  194. package/dist/engine/access.d.ts +2 -1
  195. package/dist/engine/access.js +1 -1
  196. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  197. package/dist/engine/boot-validator/entity-handler.js +1 -1
  198. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +1 -1
  199. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
  200. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
  201. package/dist/engine/boot-validator/nav.d.ts +3 -1
  202. package/dist/engine/boot-validator/nav.js +1 -1
  203. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  204. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  205. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  206. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  207. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  208. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  209. package/dist/engine/boot-validator/screens.d.ts +2 -1
  210. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  211. package/dist/engine/bridge-stub.d.ts +5 -2
  212. package/dist/engine/bridge-stub.js +39 -24
  213. package/dist/engine/config-helpers.d.ts +2 -2
  214. package/dist/engine/config-helpers.js +0 -9
  215. package/dist/engine/constants.d.ts +0 -10
  216. package/dist/engine/constants.js +0 -8
  217. package/dist/engine/create-app.js +1 -1
  218. package/dist/engine/define-feature.d.ts +2 -1
  219. package/dist/engine/define-feature.js +1 -2
  220. package/dist/engine/define-handler.d.ts +1 -1
  221. package/dist/engine/define-step.d.ts +0 -1
  222. package/dist/engine/define-step.js +0 -3
  223. package/dist/engine/embedded-derived.d.ts +1 -1
  224. package/dist/engine/entity-handlers.d.ts +2 -1
  225. package/dist/engine/entity-handlers.js +7 -7
  226. package/dist/engine/entity-list-runtime-options.js +3 -1
  227. package/dist/engine/entity-list-searchability.d.ts +2 -1
  228. package/dist/engine/event-def.d.ts +2 -1
  229. package/dist/engine/event-helpers.d.ts +3 -1
  230. package/dist/engine/event-helpers.js +3 -3
  231. package/dist/engine/extension-names.d.ts +2 -8
  232. package/dist/engine/extension-names.js +2 -2
  233. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  234. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  235. package/dist/engine/extensions/user-data.d.ts +0 -8
  236. package/dist/engine/factories.d.ts +2 -1
  237. package/dist/engine/feature-builder-state.d.ts +8 -1
  238. package/dist/engine/feature-changelog.d.ts +1 -1
  239. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  240. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  241. package/dist/engine/feature-manifest.js +1 -1
  242. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  243. package/dist/engine/feature-ui-extensions.js +6 -4
  244. package/dist/engine/field-access.d.ts +2 -1
  245. package/dist/engine/handler-field-references.d.ts +0 -4
  246. package/dist/engine/index.d.ts +57 -54
  247. package/dist/engine/index.js +22 -27
  248. package/dist/engine/instruction-fields.d.ts +1 -1
  249. package/dist/engine/personal-data-fields.d.ts +1 -1
  250. package/dist/engine/qualified-name.d.ts +0 -1
  251. package/dist/engine/read-claim.d.ts +2 -1
  252. package/dist/engine/registry-facade.js +0 -3
  253. package/dist/engine/registry-ingest.d.ts +2 -1
  254. package/dist/engine/registry-ingest.js +1 -2
  255. package/dist/engine/registry-state.d.ts +12 -2
  256. package/dist/engine/registry-state.js +2 -3
  257. package/dist/engine/registry-validate.d.ts +3 -1
  258. package/dist/engine/registry-validate.js +7 -7
  259. package/dist/engine/run-in.d.ts +1 -1
  260. package/dist/engine/run-in.js +0 -1
  261. package/dist/engine/schema-builder.d.ts +1 -1
  262. package/dist/engine/schema-builder.js +1 -1
  263. package/dist/engine/screen-filter-ops.d.ts +2 -1
  264. package/dist/engine/screen-filter-ops.js +0 -5
  265. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  266. package/dist/engine/soft-delete-cleanup.js +4 -4
  267. package/dist/engine/state-machine.js +2 -1
  268. package/dist/engine/steps/_read-source.js +1 -1
  269. package/dist/engine/steps/aggregate-append-event.js +2 -2
  270. package/dist/engine/steps/call-feature.js +2 -2
  271. package/dist/engine/steps/mail-send.js +1 -1
  272. package/dist/engine/steps/retry.js +1 -1
  273. package/dist/engine/steps/wait-for-event.js +1 -1
  274. package/dist/engine/steps/wait.js +1 -1
  275. package/dist/engine/steps/webhook-send.js +1 -1
  276. package/dist/engine/template-variables.d.ts +2 -1
  277. package/dist/engine/transfer-adjacency.d.ts +1 -1
  278. package/dist/engine/types/index.d.ts +8 -31
  279. package/dist/engine/types/index.js +2 -10
  280. package/dist/engine/validation.d.ts +2 -1
  281. package/dist/entrypoint/index.d.ts +7 -35
  282. package/dist/entrypoint/index.js +7 -1
  283. package/dist/entrypoint/internals.d.ts +40 -0
  284. package/dist/entrypoint/internals.js +1 -0
  285. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  286. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  287. package/dist/env/dry-run-internals.d.ts +10 -0
  288. package/dist/env/dry-run-internals.js +1 -0
  289. package/dist/env/dry-run.d.ts +1 -10
  290. package/dist/env/dry-run.js +2 -1
  291. package/dist/env/index.d.ts +1 -85
  292. package/dist/env/index.js +6 -50
  293. package/dist/env/internals.d.ts +87 -0
  294. package/dist/env/internals.js +53 -0
  295. package/dist/errors/classes.js +2 -2
  296. package/dist/errors/index.d.ts +5 -14
  297. package/dist/errors/index.js +4 -9
  298. package/dist/errors/member-resolution.js +1 -1
  299. package/dist/errors/reasons.d.ts +0 -1
  300. package/dist/errors/reasons.js +7 -7
  301. package/dist/errors/serialize.d.ts +0 -18
  302. package/dist/errors/serialize.js +0 -27
  303. package/dist/es-ops/index.d.ts +4 -4
  304. package/dist/es-ops/index.js +2 -2
  305. package/dist/es-ops/operations-schema.d.ts +1 -1
  306. package/dist/es-ops/types.d.ts +4 -5
  307. package/dist/event-store/admin-api-internals.d.ts +14 -0
  308. package/dist/event-store/admin-api-internals.js +1 -0
  309. package/dist/event-store/admin-api.d.ts +1 -14
  310. package/dist/event-store/admin-api.js +11 -6
  311. package/dist/event-store/archive.js +4 -2
  312. package/dist/event-store/errors.js +2 -2
  313. package/dist/event-store/event-store.js +41 -34
  314. package/dist/event-store/events-schema.js +4 -1
  315. package/dist/event-store/index.d.ts +11 -13
  316. package/dist/event-store/index.js +7 -9
  317. package/dist/event-store/rebuild-dead-letter.js +4 -2
  318. package/dist/event-store/snapshot.js +4 -3
  319. package/dist/event-store/stream-scope.d.ts +2 -0
  320. package/dist/event-store/stream-scope.js +6 -0
  321. package/dist/event-store/upcaster-dead-letter.js +4 -2
  322. package/dist/event-store/upcaster.d.ts +2 -1
  323. package/dist/files/action-form-upload.d.ts +2 -1
  324. package/dist/files/action-form-upload.js +1 -1
  325. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  326. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  327. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  328. package/dist/files/bind-pending-file-refs.js +2 -1
  329. package/dist/files/bind-referenced-files.write.js +1 -1
  330. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  331. package/dist/files/create-file-ref-from-bytes.js +3 -3
  332. package/dist/files/create-file-ref.d.ts +3 -2
  333. package/dist/files/create-file-ref.js +2 -2
  334. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  335. package/dist/files/dispose-removed-file-refs.js +1 -1
  336. package/dist/files/feature.js +2 -2
  337. package/dist/files/file-handle.js +1 -1
  338. package/dist/files/file-routes.d.ts +1 -1
  339. package/dist/files/file-routes.js +12 -2
  340. package/dist/files/index.d.ts +11 -13
  341. package/dist/files/index.js +5 -7
  342. package/dist/files/load-save-file-refs.d.ts +2 -1
  343. package/dist/files/load-save-file-refs.js +1 -1
  344. package/dist/files/provider-resolver.d.ts +5 -4
  345. package/dist/files/provider-resolver.js +4 -4
  346. package/dist/files/storage-tracking.js +4 -2
  347. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  348. package/dist/files/sweep-orphaned-uploads.js +1 -1
  349. package/dist/i18n/index.d.ts +2 -8
  350. package/dist/i18n/index.js +1 -1
  351. package/dist/i18n/internals.d.ts +7 -0
  352. package/dist/i18n/internals.js +1 -0
  353. package/dist/i18n/required-surface-keys.d.ts +4 -1
  354. package/dist/internal/row-level-security.d.ts +3 -0
  355. package/dist/internal/row-level-security.js +3 -0
  356. package/dist/internal/stack-support.d.ts +1 -1
  357. package/dist/internal/stack-support.js +1 -1
  358. package/dist/internal/testing.d.ts +1 -0
  359. package/dist/internal/testing.js +9 -5
  360. package/dist/jobs/index.d.ts +1 -1
  361. package/dist/jobs/job-append-event.d.ts +12 -0
  362. package/dist/jobs/job-append-event.js +30 -0
  363. package/dist/jobs/job-runner-context.d.ts +2 -2
  364. package/dist/jobs/job-runner-context.js +46 -16
  365. package/dist/jobs/job-runner-execution.d.ts +1 -1
  366. package/dist/jobs/job-runner-execution.js +6 -4
  367. package/dist/jobs/job-runner-gates.d.ts +1 -1
  368. package/dist/jobs/job-runner-gates.js +0 -1
  369. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  370. package/dist/jobs/job-runner-helpers.js +10 -1
  371. package/dist/jobs/job-runner-scope.d.ts +5 -2
  372. package/dist/jobs/job-runner-types.d.ts +2 -1
  373. package/dist/jobs/job-runner.js +19 -6
  374. package/dist/jobs/max-per-tenant.d.ts +1 -1
  375. package/dist/logging/index.d.ts +1 -2
  376. package/dist/logging/index.js +1 -1
  377. package/dist/logging/pino-logger.js +1 -1
  378. package/dist/logging/utils.d.ts +1 -0
  379. package/dist/logging/utils.js +6 -0
  380. package/dist/migrations/index.d.ts +3 -3
  381. package/dist/migrations/index.js +3 -3
  382. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  383. package/dist/migrations/pending-rebuilds.js +1 -1
  384. package/dist/migrations/pii-event-backfill.js +4 -1
  385. package/dist/observability/escape-hatch-report.d.ts +2 -1
  386. package/dist/observability/index.d.ts +7 -15
  387. package/dist/observability/index.js +4 -12
  388. package/dist/observability/metric-validator.js +1 -1
  389. package/dist/observability/metrics-handle.d.ts +0 -1
  390. package/dist/observability/metrics-handle.js +2 -15
  391. package/dist/observability/recording-tracer.d.ts +1 -2
  392. package/dist/observability/recording-tracer.js +0 -6
  393. package/dist/observability/sensitive-filter.d.ts +0 -2
  394. package/dist/observability/sensitive-filter.js +0 -29
  395. package/dist/pipeline/active-membership.d.ts +2 -1
  396. package/dist/pipeline/active-membership.js +6 -2
  397. package/dist/pipeline/append-event-core.d.ts +2 -1
  398. package/dist/pipeline/append-event-core.js +2 -2
  399. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  400. package/dist/pipeline/attach-outside-transaction.js +13 -0
  401. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  402. package/dist/pipeline/cascade-handler.d.ts +2 -1
  403. package/dist/pipeline/cascade-handler.js +3 -2
  404. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  405. package/dist/pipeline/config-accessor-factory.js +1 -1
  406. package/dist/pipeline/context-services.d.ts +56 -0
  407. package/dist/pipeline/context-services.js +73 -0
  408. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  409. package/dist/pipeline/dispatch-batch.js +31 -18
  410. package/dist/pipeline/dispatch-query.js +5 -4
  411. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  412. package/dist/pipeline/dispatch-scope.js +27 -0
  413. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  414. package/dist/pipeline/dispatch-shared.js +75 -198
  415. package/dist/pipeline/dispatch-stream.js +8 -4
  416. package/dist/pipeline/dispatch-write.d.ts +2 -1
  417. package/dist/pipeline/dispatch-write.js +10 -8
  418. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  419. package/dist/pipeline/dispatcher-utils.js +8 -2
  420. package/dist/pipeline/dispatcher.d.ts +3 -2
  421. package/dist/pipeline/dispatcher.js +4 -3
  422. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  423. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  424. package/dist/pipeline/event-dispatcher-delivery.js +4 -2
  425. package/dist/pipeline/event-dispatcher.d.ts +2 -2
  426. package/dist/pipeline/event-dispatcher.js +7 -3
  427. package/dist/pipeline/event-retention.js +59 -56
  428. package/dist/pipeline/handler-access-error.js +2 -1
  429. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  430. package/dist/pipeline/handler-context-auth.js +7 -4
  431. package/dist/pipeline/handler-context-config.d.ts +2 -5
  432. package/dist/pipeline/handler-context-config.js +2 -2
  433. package/dist/pipeline/handler-context-db.d.ts +32 -7
  434. package/dist/pipeline/handler-context-db.js +26 -17
  435. package/dist/pipeline/handler-context-dispatch.d.ts +13 -7
  436. package/dist/pipeline/handler-context-dispatch.js +9 -8
  437. package/dist/pipeline/handler-context-events.d.ts +22 -36
  438. package/dist/pipeline/handler-context-events.js +36 -31
  439. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  440. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  441. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  442. package/dist/pipeline/handler-context-notify.js +1 -1
  443. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  444. package/dist/pipeline/handler-context-observability.js +7 -5
  445. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  446. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  447. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  448. package/dist/pipeline/handler-context-scope.js +18 -20
  449. package/dist/pipeline/index.d.ts +9 -21
  450. package/dist/pipeline/index.js +5 -7
  451. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  452. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  453. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  454. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  455. package/dist/pipeline/member-read-only-transaction.js +11 -3
  456. package/dist/pipeline/member-reader.d.ts +1 -1
  457. package/dist/pipeline/member-reader.js +2 -2
  458. package/dist/pipeline/msp-rebuild.js +5 -3
  459. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  460. package/dist/pipeline/notify-scope.d.ts +2 -1
  461. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  462. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  463. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  464. package/dist/pipeline/projection-rebuild.js +12 -5
  465. package/dist/pipeline/projection-state.d.ts +0 -6
  466. package/dist/pipeline/projection-state.js +0 -5
  467. package/dist/pipeline/projections-runner.d.ts +2 -1
  468. package/dist/pipeline/projections-runner.js +10 -6
  469. package/dist/pipeline/system-hooks.d.ts +3 -1
  470. package/dist/pipeline/system-hooks.js +6 -4
  471. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  472. package/dist/pipeline/system-identity-switch.js +51 -36
  473. package/dist/pipeline/typed-append-event.d.ts +2 -0
  474. package/dist/pipeline/typed-append-event.js +4 -0
  475. package/dist/pipeline/write-origin.js +2 -2
  476. package/dist/pipeline/write-result-masking.d.ts +1 -1
  477. package/dist/random/index.d.ts +1 -2
  478. package/dist/random/index.js +1 -2
  479. package/dist/rate-limit/bucket.d.ts +2 -1
  480. package/dist/rate-limit/middleware.js +2 -1
  481. package/dist/redis/index.d.ts +3 -4
  482. package/dist/redis/index.js +2 -2
  483. package/dist/schema-cli/apply-command.js +5 -2
  484. package/dist/schema-cli/baseline-command.js +7 -2
  485. package/dist/schema-cli/generate-command.js +7 -9
  486. package/dist/schema-cli/shared.d.ts +4 -0
  487. package/dist/schema-cli/shared.js +21 -2
  488. package/dist/schema-cli/status-command.js +8 -2
  489. package/dist/schema-cli/validate-command.js +52 -4
  490. package/dist/schema-cli.d.ts +0 -1
  491. package/dist/search/configure-tenant-index.d.ts +1 -3
  492. package/dist/search/configure-tenant-index.js +0 -4
  493. package/dist/search/index.d.ts +1 -4
  494. package/dist/search/index.js +0 -2
  495. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  496. package/dist/search/meilisearch-adapter-internals.js +9 -0
  497. package/dist/search/meilisearch-adapter.d.ts +1 -8
  498. package/dist/search/meilisearch-adapter.js +6 -7
  499. package/dist/search/meilisearch-peer.d.ts +2 -0
  500. package/dist/search/meilisearch-peer.js +5 -0
  501. package/dist/search/reindex-entity.js +93 -87
  502. package/dist/secrets/index.d.ts +3 -4
  503. package/dist/secrets/index.js +2 -3
  504. package/dist/seeding/index.d.ts +2 -2
  505. package/dist/seeding/index.js +1 -2
  506. package/dist/time/index.d.ts +2 -2
  507. package/dist/time/index.js +1 -1
  508. package/dist/time/tz-context.d.ts +0 -5
  509. package/dist/time/tz-context.js +0 -9
  510. package/dist/ui-types/index.d.ts +8 -11
  511. package/dist/ui-types/index.js +3 -3
  512. package/dist/upgrade-changelog.d.ts +3 -2
  513. package/dist/upgrade-changelog.js +12 -8
  514. package/dist/upgrade-cli-internals.d.ts +8 -0
  515. package/dist/upgrade-cli-internals.js +63 -0
  516. package/dist/upgrade-cli.d.ts +1 -9
  517. package/dist/upgrade-cli.js +10 -64
  518. package/dist/utils/import-optional-peer.d.ts +6 -0
  519. package/dist/utils/import-optional-peer.js +19 -0
  520. package/dist/utils/index.d.ts +1 -4
  521. package/dist/utils/index.js +1 -4
  522. package/package.json +22 -18
  523. package/src/changes.json +206 -0
  524. package/dist/crypto/request-kms-cache.d.ts +0 -8
  525. package/dist/crypto/request-kms-cache.js +0 -21
  526. package/dist/engine/codemod/index.d.ts +0 -2
  527. package/dist/engine/codemod/index.js +0 -1
  528. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  529. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  530. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  531. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  532. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  533. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  534. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  535. package/dist/engine/feature-ast/extractors/events.js +0 -275
  536. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  537. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  538. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  539. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  540. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  541. package/dist/engine/feature-ast/extractors/index.js +0 -13
  542. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  543. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  544. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  545. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  546. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  547. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  548. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -11
  549. package/dist/engine/feature-ast/extractors/round1.js +0 -87
  550. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  551. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  552. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  553. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  554. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  555. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  556. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  557. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  558. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  559. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  560. package/dist/engine/feature-ast/index.d.ts +0 -16
  561. package/dist/engine/feature-ast/index.js +0 -10
  562. package/dist/engine/feature-ast/parse.d.ts +0 -31
  563. package/dist/engine/feature-ast/parse.js +0 -485
  564. package/dist/engine/feature-ast/patch.d.ts +0 -212
  565. package/dist/engine/feature-ast/patch.js +0 -611
  566. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  567. package/dist/engine/feature-ast/patcher.js +0 -281
  568. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1238
  569. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
  570. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  571. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
  572. package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
  573. package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
  574. package/dist/engine/feature-ast/patterns.d.ts +0 -322
  575. package/dist/engine/feature-ast/patterns.js +0 -107
  576. package/dist/engine/feature-ast/render.d.ts +0 -47
  577. package/dist/engine/feature-ast/render.js +0 -666
  578. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  579. package/dist/engine/feature-ast/source-location.js +0 -27
  580. package/dist/engine/pattern-library/index.d.ts +0 -2
  581. package/dist/engine/pattern-library/index.js +0 -3
  582. package/dist/engine/pattern-library/library.d.ts +0 -14
  583. package/dist/engine/pattern-library/library.js +0 -94
  584. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  585. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  586. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  587. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  588. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  589. package/dist/engine/pattern-library/shared-fields.js +0 -88
  590. package/dist/engine/pattern-library/static-schemas.d.ts +0 -21
  591. package/dist/engine/pattern-library/static-schemas.js +0 -487
  592. package/dist/engine/pattern-library/types.d.ts +0 -158
  593. package/dist/engine/pattern-library/types.js +0 -36
  594. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  595. package/dist/engine/resolve-config-or-param.js +0 -76
  596. package/src/scripts/codemod/README.md +0 -187
  597. package/src/scripts/codemod/codemod-support.ts +0 -334
  598. package/src/scripts/codemod/collect-source-files.ts +0 -48
  599. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  600. package/src/scripts/codemod/db-factory.ts +0 -810
  601. package/src/scripts/codemod/feature-factory.ts +0 -429
  602. package/src/scripts/codemod/feature-layout.ts +0 -424
  603. package/src/scripts/codemod/import-extensions.ts +0 -118
  604. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  605. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  606. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  607. package/src/scripts/codemod/object-form.ts +0 -746
  608. package/src/scripts/codemod/package-merge.ts +0 -299
  609. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  610. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  611. package/src/scripts/codemod/s3-imports.ts +0 -236
  612. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  613. package/src/scripts/codemod/testing-injection.ts +0 -215
  614. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  615. package/src/scripts/codemod/testing-move.ts +0 -542
  616. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -1,1072 +0,0 @@
1
- // Runtime validator for the `unknown → PatternChange[]` boundary. An AI
2
- // tool (or any external caller) hands us JSON; before it ever reaches
3
- // `applyChanges` it must pass through here. Every rejection carries an
4
- // exact dotted/bracketed path so the caller (frequently an LLM) can
5
- // self-correct without a human in the loop.
6
- //
7
- // **Zod v4 constraint driving this file's shape:** every discriminated-
8
- // union member below stays a plain `z.object(...)` (or `.superRefine`
9
- // wrapper around one) — never `.transform()` at the object level. A
10
- // whole-object transform would erase the "which member matched" signal
11
- // `discriminatedUnion` needs to attribute a nested field error to the
12
- // right member, and it would blur per-member `.strict()` unrecognized-key
13
- // detection. Transforms only ever touch a single field (`sourceBody`,
14
- // below) — never the object they live on.
15
- //
16
- // **Deep definitions stay opaque.** EntityDefinition, ScreenDefinition,
17
- // NavDefinition, WorkspaceDefinition, JobDefinition-options, MetricOptions,
18
- // etc. are NOT hand-modeled here — that would fork a second, driftable
19
- // catalogue of their shape. They're accepted via `z.custom` (plain object,
20
- // or a RawRefSentinel/AiStepOpaqueArgs — the extractor's own "couldn't
21
- // resolve this statically" markers) and, for EntityDefinition only,
22
- // additionally checked for field-type membership via the shared
23
- // `findUnknownEntityFieldTypes` helper (kept in sync with `extractEntity`).
24
- import { ESCAPE_HATCH_GRANTS } from "@cosmicdrift/kumiko-types/handlers";
25
- import * as z from "zod";
26
- import { LifecycleHookTypes } from "../constants.js";
27
- import { describeUnknownFieldType, findUnknownEntityFieldTypes } from "./entity-field-types.js";
28
- import { AGENT_RISK_VALUES } from "./extractors/handlers.js";
29
- import { isPlainObject, isRawRefSentinel } from "./extractors/shared.js";
30
- import { SYNTHETIC_LOC } from "./patcher.js";
31
- import { patternIdSchema } from "./pattern-id-schema.js";
32
- // Derives an exhaustive literal-value array from a `Record<T, true>` flag
33
- // map: an added/removed union member fails to compile here instead of
34
- // silently producing a schema narrower than the runtime type — same
35
- // rationale as kumiko-types's `NO_WIDGET_FIELD_TYPES`/`FIELD_TYPE_NAMES`.
36
- function keysOf(flags) {
37
- return Object.keys(flags);
38
- }
39
- // =============================================================================
40
- // Shared primitives
41
- // =============================================================================
42
- function isPlainObjectOrSentinel(value) {
43
- return isRawRefSentinel(value) || isPlainObject(value);
44
- }
45
- const sourcePositionSchema = z
46
- .object({ line: z.number(), column: z.number() })
47
- .strict();
48
- const fullSourceLocationSchema = z
49
- .object({
50
- file: z.string(),
51
- start: sourcePositionSchema,
52
- end: sourcePositionSchema,
53
- raw: z.string(),
54
- })
55
- .strict();
56
- // Partial object form — only `raw` is meaningful, `file`/`start`/`end` (if
57
- // present) are accepted but discarded: a wire producer sending a
58
- // half-populated location is telling us "this came from generated code, not
59
- // a real file span" and `rawLoc` is exactly that contract.
60
- const partialSourceLocationSchema = z
61
- .object({
62
- raw: z.string(),
63
- file: z.string().optional(),
64
- start: sourcePositionSchema.optional(),
65
- end: sourcePositionSchema.optional(),
66
- })
67
- .strict()
68
- .transform((value) => ({ ...SYNTHETIC_LOC, raw: value.raw }));
69
- const stringSourceLocationSchema = z
70
- .string()
71
- .transform((raw) => ({ ...SYNTHETIC_LOC, raw }));
72
- // `sourceBody`: string | {raw, file?, start?, end?} | full SourceLocation.
73
- // Order matters — a fully-populated object must match `fullSourceLocationSchema`
74
- // first so it round-trips unchanged; only a partial object falls through to
75
- // the raw-collapsing variant.
76
- const sourceBodySchema = z.union([
77
- fullSourceLocationSchema,
78
- partialSourceLocationSchema,
79
- stringSourceLocationSchema,
80
- ]);
81
- const nonEmptySourceBodySchema = sourceBodySchema.refine((loc) => loc.raw.trim().length > 0, {
82
- message: "source.raw must be non-empty",
83
- });
84
- // The pattern-level `source` field: optional on the wire, defaults to the
85
- // patcher's own synthetic placeholder (mirrors createFeaturePatcher's
86
- // add{Kind} methods, which never have a real file span either).
87
- const sourceFieldSchema = sourceBodySchema
88
- .optional()
89
- .default(SYNTHETIC_LOC);
90
- // `readVarargsOrArrayProp` (extractors/shared.ts) already types a mixed
91
- // string/sentinel array as `readonly string[]` at its own extraction
92
- // boundary (requires.featureNames, readsConfig.qualifiedKeys); mirror that
93
- // same typed lie here instead of re-deriving a wider array type only to
94
- // cast it back down.
95
- const stringOrRawRefListSchema = z.custom((value) => Array.isArray(value) && value.every((el) => typeof el === "string" || isRawRefSentinel(el)), { message: "must be an array of strings or unresolved references" });
96
- // Runtime source of truth for the lifecycle-hook-type literals: the
97
- // engine's own `LifecycleHookTypes` const object (engine/constants.ts) —
98
- // `hook`'s `hookType` is that union plus the AST-only "validation" pseudo-
99
- // type (r.hook(type: "validation", ...) has no runtime LifecycleHookType
100
- // counterpart, it maps to a different registrar call).
101
- const LIFECYCLE_HOOK_TYPE_VALUES = Object.values(LifecycleHookTypes);
102
- const hookTypeSchema = z.enum([...LIFECYCLE_HOOK_TYPE_VALUES, "validation"]);
103
- const hookPhaseSchema = z.enum(keysOf({ inTransaction: true, afterCommit: true }));
104
- const httpRouteMethodSchema = z.enum(keysOf({
105
- GET: true,
106
- POST: true,
107
- PUT: true,
108
- PATCH: true,
109
- DELETE: true,
110
- HEAD: true,
111
- OPTIONS: true,
112
- }));
113
- const runInSchema = z.enum(keysOf({ api: true, worker: true, both: true }));
114
- const claimKeyTypeSchema = z.enum(keysOf({
115
- string: true,
116
- number: true,
117
- boolean: true,
118
- "string[]": true,
119
- object: true,
120
- }));
121
- const agentRiskSchema = z.enum(AGENT_RISK_VALUES);
122
- const rateLimitPerSchema = z.enum(keysOf({
123
- user: true,
124
- tenant: true,
125
- ip: true,
126
- "user+handler": true,
127
- "tenant+handler": true,
128
- "ip+handler": true,
129
- }));
130
- const mspDeliverySchema = z.enum(keysOf({ shared: true, "per-instance": true }));
131
- const escapeHatchSchema = z
132
- .object({
133
- reason: z.string().refine((s) => s.trim().length > 0, {
134
- message: "reason must be non-empty",
135
- }),
136
- grants: z.array(z.enum(ESCAPE_HATCH_GRANTS)).min(1).optional(),
137
- })
138
- .strict();
139
- const rawRefSentinelSchema = z.object({ __raw: z.string() }).strict();
140
- // Adds the raw-ref-sentinel branch a handler header field accepts when the
141
- // extractor couldn't resolve it to a literal (see extractors/hooks.ts).
142
- function orRawRef(schema) {
143
- return z.union([schema, rawRefSentinelSchema]);
144
- }
145
- const rateLimitDisabledSchema = z
146
- .object({
147
- disabled: z.literal(true),
148
- reason: z.string().refine((s) => s.trim().length > 0, {
149
- message: "reason must be non-empty",
150
- }),
151
- })
152
- .strict();
153
- const rateLimitOptionSchema = z
154
- .object({
155
- per: rateLimitPerSchema,
156
- limit: z.number(),
157
- windowSeconds: z.number(),
158
- cost: z.number().optional(),
159
- })
160
- .strict();
161
- const rateLimitOptionListSchema = z.tuple([rateLimitOptionSchema], rateLimitOptionSchema);
162
- const additionalRateLimitsSchema = z.array(z
163
- .object({
164
- per: z.object({ payloadField: z.string() }).strict(),
165
- limit: z.number(),
166
- windowSeconds: z.number(),
167
- cost: z.number().optional(),
168
- normalize: z.literal("email").optional(),
169
- })
170
- .strict());
171
- const agentHandlerHintsSchema = z
172
- .object({
173
- expose: z.boolean().optional(),
174
- risk: agentRiskSchema.optional(),
175
- })
176
- .strict();
177
- // AccessRule — DEFAULT-DENY per its doc in types/handlers.ts; a malformed
178
- // shape must be rejected, not silently narrowed to "no access" (that would
179
- // hide the author's mistake instead of reporting it at the boundary).
180
- const roleAccessRuleSchema = z
181
- .object({
182
- roles: z.array(z.string()),
183
- personalData: z.literal("public-intake").optional(),
184
- })
185
- .strict();
186
- const openToAllAccessRuleSchema = z
187
- .object({
188
- openToAll: z
189
- .object({
190
- reason: z.string().refine((s) => s.trim().length > 0, {
191
- message: "openToAll.reason must be non-empty",
192
- }),
193
- personalData: z.literal("tenant-members").optional(),
194
- })
195
- .strict(),
196
- })
197
- .strict();
198
- const accessRuleSchema = z.union([roleAccessRuleSchema, openToAllAccessRuleSchema]);
199
- // Header keys per handler kind — drift pin against patch.ts's *HeaderKey
200
- // types (via `satisfies`), and the source the schemas below derive from.
201
- const WRITE_HANDLER_HEADER_SHAPE = {
202
- access: accessRuleSchema,
203
- description: z.string(),
204
- agent: agentHandlerHintsSchema,
205
- rateLimit: rateLimitOptionSchema,
206
- additionalRateLimits: additionalRateLimitsSchema,
207
- unsafeSkipTransitionGuard: z.boolean(),
208
- escapeHatch: escapeHatchSchema,
209
- };
210
- const QUERY_HANDLER_HEADER_SHAPE = {
211
- access: accessRuleSchema,
212
- description: z.string(),
213
- agent: agentHandlerHintsSchema,
214
- rateLimit: rateLimitOptionSchema,
215
- escapeHatch: escapeHatchSchema,
216
- };
217
- const STREAM_HANDLER_HEADER_SHAPE = {
218
- access: accessRuleSchema,
219
- rateLimit: rateLimitOptionSchema,
220
- escapeHatch: escapeHatchSchema,
221
- };
222
- const WRITE_HANDLER_HEADER_KEYS = z.object(WRITE_HANDLER_HEADER_SHAPE).keyof().options;
223
- const QUERY_HANDLER_HEADER_KEYS = z.object(QUERY_HANDLER_HEADER_SHAPE).keyof().options;
224
- const STREAM_HANDLER_HEADER_KEYS = z.object(STREAM_HANDLER_HEADER_SHAPE).keyof().options;
225
- // `update`'s set-schema stays exactly as strict as the extractor's own
226
- // output: Designer/AI-authored values must be structured, never a raw
227
- // reference or a partially-literal shape — those only ever come from
228
- // statically parsed source, not from a `set` payload.
229
- const WRITE_HANDLER_UPDATE_SET_SCHEMA = z.object(WRITE_HANDLER_HEADER_SHAPE).partial().strict();
230
- const QUERY_HANDLER_UPDATE_SET_SCHEMA = z.object(QUERY_HANDLER_HEADER_SHAPE).partial().strict();
231
- const STREAM_HANDLER_UPDATE_SET_SCHEMA = z.object(STREAM_HANDLER_HEADER_SHAPE).partial().strict();
232
- // `unset` may name any header field except `access` (always required).
233
- const WRITE_HANDLER_UPDATE_UNSET_ENUM = z
234
- .object(WRITE_HANDLER_HEADER_SHAPE)
235
- .omit({ access: true })
236
- .keyof();
237
- const QUERY_HANDLER_UPDATE_UNSET_ENUM = z
238
- .object(QUERY_HANDLER_HEADER_SHAPE)
239
- .omit({ access: true })
240
- .keyof();
241
- const STREAM_HANDLER_UPDATE_UNSET_ENUM = z
242
- .object(STREAM_HANDLER_HEADER_SHAPE)
243
- .omit({ access: true })
244
- .keyof();
245
- // Full patterns (add/replace) carry whatever the extractor parsed, which
246
- // may be a RawRefSentinel or a disabled-rate-limit shape it can't resolve
247
- // to a literal; widen only here, not on UPDATE_SET_SCHEMA above.
248
- const WRITE_HANDLER_PATTERN_HEADER_SHAPE = {
249
- ...WRITE_HANDLER_HEADER_SHAPE,
250
- access: orRawRef(accessRuleSchema),
251
- agent: orRawRef(agentHandlerHintsSchema),
252
- rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitOptionListSchema, rateLimitDisabledSchema])),
253
- additionalRateLimits: orRawRef(additionalRateLimitsSchema),
254
- escapeHatch: orRawRef(escapeHatchSchema),
255
- };
256
- const QUERY_HANDLER_PATTERN_HEADER_SHAPE = {
257
- ...QUERY_HANDLER_HEADER_SHAPE,
258
- access: orRawRef(accessRuleSchema),
259
- agent: orRawRef(agentHandlerHintsSchema),
260
- rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitOptionListSchema, rateLimitDisabledSchema])),
261
- escapeHatch: orRawRef(escapeHatchSchema),
262
- };
263
- const STREAM_HANDLER_PATTERN_HEADER_SHAPE = {
264
- ...STREAM_HANDLER_HEADER_SHAPE,
265
- access: orRawRef(accessRuleSchema),
266
- rateLimit: orRawRef(z.union([rateLimitOptionSchema, rateLimitOptionListSchema, rateLimitDisabledSchema])),
267
- escapeHatch: orRawRef(escapeHatchSchema),
268
- };
269
- function requireHandlerBody(val, ctx, headerKeys) {
270
- const hasAny = val.handlerName !== undefined ||
271
- val.schemaSource !== undefined ||
272
- val.handlerBody !== undefined;
273
- if (!hasAny) {
274
- if (val.source.raw.trim().length === 0) {
275
- ctx.addIssue({
276
- code: "custom",
277
- path: ["source"],
278
- message: "an opaque handler reference (no handlerName/schemaSource/handlerBody) requires a non-empty source.raw",
279
- });
280
- }
281
- for (const key of headerKeys) {
282
- if (val[key] !== undefined) {
283
- ctx.addIssue({
284
- code: "custom",
285
- path: [key],
286
- message: "not rendered for an opaque handler reference; provide handlerName, schemaSource and handlerBody",
287
- });
288
- }
289
- }
290
- // skip: opaque handler reference carries no name/schema/body to require
291
- return;
292
- }
293
- if (val.handlerName === undefined || val.handlerName.trim().length === 0) {
294
- ctx.addIssue({
295
- code: "custom",
296
- path: ["handlerName"],
297
- message: "handlerName is required and must be non-empty",
298
- });
299
- }
300
- if (val.schemaSource === undefined) {
301
- ctx.addIssue({ code: "custom", path: ["schemaSource"], message: "schemaSource is required" });
302
- }
303
- if (val.handlerBody === undefined) {
304
- ctx.addIssue({ code: "custom", path: ["handlerBody"], message: "handlerBody is required" });
305
- }
306
- }
307
- // =============================================================================
308
- // Static patterns
309
- // =============================================================================
310
- // Deep-definition passthrough: accepts a plain object OR the extractor's
311
- // own "couldn't resolve this statically" sentinel (RawRefSentinel), typed
312
- // as `T` at the boundary — the same "typed lie" the extractors already
313
- // make (e.g. round2.ts's `definition as EntityDefinition`), because a
314
- // sentinel-bearing value is never actually shaped like `T` at runtime, but
315
- // round-trips through `applyChanges`/the renderer unexamined either way.
316
- function passthroughSchema() {
317
- return z.custom(isPlainObjectOrSentinel, {
318
- message: "must be a plain object or unresolved reference",
319
- });
320
- }
321
- const entityDefinitionSchema = passthroughSchema().superRefine((value, ctx) => {
322
- for (const entry of findUnknownEntityFieldTypes(value)) {
323
- ctx.addIssue({
324
- code: "custom",
325
- path: ["fields", entry.fieldName, "type"],
326
- message: describeUnknownFieldType(entry),
327
- });
328
- }
329
- });
330
- const entitySchema = z
331
- .object({
332
- kind: z.literal("entity"),
333
- source: sourceFieldSchema,
334
- entityName: z.string(),
335
- definition: entityDefinitionSchema,
336
- backingTable: passthroughSchema().optional(),
337
- })
338
- .strict();
339
- const relationSchema = z
340
- .object({
341
- kind: z.literal("relation"),
342
- source: sourceFieldSchema,
343
- entityName: z.string(),
344
- relationName: z.string(),
345
- definition: passthroughSchema(),
346
- })
347
- .strict();
348
- const navSchema = z
349
- .object({
350
- kind: z.literal("nav"),
351
- source: sourceFieldSchema,
352
- definition: passthroughSchema(),
353
- })
354
- .strict();
355
- const workspaceSchema = z
356
- .object({
357
- kind: z.literal("workspace"),
358
- source: sourceFieldSchema,
359
- definition: passthroughSchema(),
360
- })
361
- .strict();
362
- const configSchema = z
363
- .object({
364
- kind: z.literal("config"),
365
- source: sourceFieldSchema,
366
- keys: passthroughSchema(),
367
- })
368
- .strict();
369
- const translationsSchema = z
370
- .object({
371
- kind: z.literal("translations"),
372
- source: sourceFieldSchema,
373
- keys: passthroughSchema(),
374
- })
375
- .strict();
376
- const requiresSchema = z
377
- .object({
378
- kind: z.literal("requires"),
379
- source: sourceFieldSchema,
380
- featureNames: stringOrRawRefListSchema,
381
- })
382
- .strict();
383
- const optionalRequiresSchema = z
384
- .object({
385
- kind: z.literal("optionalRequires"),
386
- source: sourceFieldSchema,
387
- featureNames: stringOrRawRefListSchema,
388
- })
389
- .strict();
390
- const systemScopeSchema = z
391
- .object({
392
- kind: z.literal("systemScope"),
393
- source: sourceFieldSchema,
394
- })
395
- .strict();
396
- const toggleableSchema = z
397
- .object({
398
- kind: z.literal("toggleable"),
399
- source: sourceFieldSchema,
400
- default: z.boolean(),
401
- })
402
- .strict();
403
- const describeSchema = z
404
- .object({
405
- kind: z.literal("describe"),
406
- source: sourceFieldSchema,
407
- text: z.string().refine((s) => s.trim().length > 0, { message: "text must be non-empty" }),
408
- })
409
- .strict();
410
- const adoptsBundledListsSchema = z
411
- .object({
412
- kind: z.literal("adoptsBundledLists"),
413
- source: sourceFieldSchema,
414
- })
415
- .strict();
416
- const uiHintsSchema = z
417
- .object({
418
- kind: z.literal("uiHints"),
419
- source: nonEmptySourceBodySchema,
420
- })
421
- .strict();
422
- const metricSchema = z
423
- .object({
424
- kind: z.literal("metric"),
425
- source: sourceFieldSchema,
426
- shortName: z.string(),
427
- options: passthroughSchema(),
428
- })
429
- .strict();
430
- const secretSchema = z
431
- .object({
432
- kind: z.literal("secret"),
433
- source: sourceFieldSchema,
434
- shortName: z.string(),
435
- options: passthroughSchema(),
436
- })
437
- .strict();
438
- const secretNamespaceSchema = z
439
- .object({
440
- kind: z.literal("secretNamespace"),
441
- source: sourceFieldSchema,
442
- shortName: z.string(),
443
- options: passthroughSchema(),
444
- })
445
- .strict();
446
- const claimKeySchema = z
447
- .object({
448
- kind: z.literal("claimKey"),
449
- source: sourceFieldSchema,
450
- shortName: z.string(),
451
- claimType: claimKeyTypeSchema,
452
- })
453
- .strict();
454
- const referenceDataSchema = z
455
- .object({
456
- kind: z.literal("referenceData"),
457
- source: sourceFieldSchema,
458
- entityName: z.string(),
459
- data: z.custom((value) => Array.isArray(value) || isRawRefSentinel(value), { message: "data must be an array or unresolved reference" }),
460
- upsertKey: z.string().optional(),
461
- })
462
- .strict();
463
- const readsConfigSchema = z
464
- .object({
465
- kind: z.literal("readsConfig"),
466
- source: sourceFieldSchema,
467
- qualifiedKeys: stringOrRawRefListSchema,
468
- })
469
- .strict();
470
- const useExtensionSchema = z
471
- .object({
472
- kind: z.literal("useExtension"),
473
- source: sourceFieldSchema,
474
- extensionName: z.string(),
475
- extensionNameRaw: z.string().optional(),
476
- entityName: z.string(),
477
- options: passthroughSchema().optional(),
478
- })
479
- .strict();
480
- const usesApiSchema = z
481
- .object({
482
- kind: z.literal("usesApi"),
483
- source: sourceFieldSchema,
484
- apiName: z.string(),
485
- })
486
- .strict();
487
- const exposesApiSchema = z
488
- .object({
489
- kind: z.literal("exposesApi"),
490
- source: sourceFieldSchema,
491
- apiName: z.string(),
492
- })
493
- .strict();
494
- const treeActionsSchema = z
495
- .object({
496
- kind: z.literal("treeActions"),
497
- source: sourceFieldSchema,
498
- definitions: passthroughSchema(),
499
- })
500
- .strict();
501
- // =============================================================================
502
- // Mixed patterns
503
- // =============================================================================
504
- const screenSchema = z
505
- .object({
506
- kind: z.literal("screen"),
507
- source: sourceFieldSchema,
508
- definition: passthroughSchema(),
509
- opaqueProps: z.record(z.string(), sourceBodySchema).optional().default({}),
510
- })
511
- .strict();
512
- const writeHandlerSchema = z
513
- .object({
514
- kind: z.literal("writeHandler"),
515
- source: sourceFieldSchema,
516
- handlerName: z.string().optional(),
517
- schemaSource: sourceBodySchema.optional(),
518
- handlerBody: sourceBodySchema.optional(),
519
- ...z.object(WRITE_HANDLER_PATTERN_HEADER_SHAPE).partial().shape,
520
- })
521
- .strict()
522
- .superRefine((val, ctx) => requireHandlerBody(val, ctx, WRITE_HANDLER_HEADER_KEYS));
523
- const queryHandlerSchema = z
524
- .object({
525
- kind: z.literal("queryHandler"),
526
- source: sourceFieldSchema,
527
- handlerName: z.string().optional(),
528
- schemaSource: sourceBodySchema.optional(),
529
- handlerBody: sourceBodySchema.optional(),
530
- ...z.object(QUERY_HANDLER_PATTERN_HEADER_SHAPE).partial().shape,
531
- })
532
- .strict()
533
- .superRefine((val, ctx) => requireHandlerBody(val, ctx, QUERY_HANDLER_HEADER_KEYS));
534
- const streamHandlerSchema = z
535
- .object({
536
- kind: z.literal("streamHandler"),
537
- source: sourceFieldSchema,
538
- handlerName: z.string().optional(),
539
- schemaSource: sourceBodySchema.optional(),
540
- handlerBody: sourceBodySchema.optional(),
541
- ...z.object(STREAM_HANDLER_PATTERN_HEADER_SHAPE).partial().shape,
542
- })
543
- .strict()
544
- .superRefine((val, ctx) => requireHandlerBody(val, ctx, STREAM_HANDLER_HEADER_KEYS));
545
- const hookTargetSchema = z.union([
546
- z.string(),
547
- z.array(z.string()),
548
- z.object({ allOf: z.string() }).strict(),
549
- ]);
550
- const hookSchema = z
551
- .object({
552
- kind: z.literal("hook"),
553
- source: sourceFieldSchema,
554
- hookType: hookTypeSchema,
555
- target: hookTargetSchema,
556
- fnBody: sourceBodySchema,
557
- phase: hookPhaseSchema.optional(),
558
- escapeHatch: orRawRef(escapeHatchSchema).optional(),
559
- })
560
- .strict();
561
- const jobSchema = z
562
- .object({
563
- kind: z.literal("job"),
564
- source: sourceFieldSchema,
565
- jobName: z.string(),
566
- options: passthroughSchema(),
567
- handlerBody: sourceBodySchema,
568
- })
569
- .strict();
570
- const notificationSchema = z
571
- .object({
572
- kind: z.literal("notification"),
573
- source: sourceFieldSchema,
574
- notificationName: z.string(),
575
- trigger: z.object({ on: z.string() }).strict().optional(),
576
- recipientBody: sourceBodySchema.optional(),
577
- dataBody: sourceBodySchema.optional(),
578
- templates: z.record(z.string(), sourceBodySchema).optional(),
579
- })
580
- .strict();
581
- const authClaimsSchema = z
582
- .object({
583
- kind: z.literal("authClaims"),
584
- source: sourceFieldSchema,
585
- fnBody: sourceBodySchema,
586
- })
587
- .strict();
588
- const httpRouteSchema = z
589
- .object({
590
- kind: z.literal("httpRoute"),
591
- source: sourceFieldSchema,
592
- method: httpRouteMethodSchema,
593
- path: z.string(),
594
- anonymous: z.boolean(),
595
- handlerBody: sourceBodySchema,
596
- })
597
- .strict();
598
- const projectionSchema = z
599
- .object({
600
- kind: z.literal("projection"),
601
- source: sourceFieldSchema,
602
- name: z.string(),
603
- sourceEntity: z.union([z.string(), z.array(z.string())]),
604
- applyBodies: z.record(z.string(), sourceBodySchema),
605
- })
606
- .strict();
607
- const mspErrorPolicySchema = z.object({ skipApplyErrors: z.boolean().optional() }).strict();
608
- const mspErrorModeSchema = z
609
- .object({
610
- continuous: mspErrorPolicySchema.optional(),
611
- rebuild: mspErrorPolicySchema.optional(),
612
- })
613
- .strict();
614
- const multiStreamProjectionSchema = z
615
- .object({
616
- kind: z.literal("multiStreamProjection"),
617
- source: sourceFieldSchema,
618
- name: z.string(),
619
- applyBodies: z.record(z.string(), sourceBodySchema),
620
- errorMode: mspErrorModeSchema.optional(),
621
- runIn: runInSchema.optional(),
622
- delivery: mspDeliverySchema.optional(),
623
- })
624
- .strict();
625
- const defineEventSchema = z
626
- .object({
627
- kind: z.literal("defineEvent"),
628
- source: sourceFieldSchema,
629
- eventName: z.string(),
630
- eventNameRaw: z.string().optional(),
631
- schemaSource: sourceBodySchema,
632
- version: z.number().optional(),
633
- piiFields: sourceBodySchema,
634
- migrations: z.record(z.string(), sourceBodySchema).optional(),
635
- })
636
- .strict();
637
- const extendsRegistrarSchema = z
638
- .object({
639
- kind: z.literal("extendsRegistrar"),
640
- source: sourceFieldSchema,
641
- extensionName: z.string(),
642
- extensionNameRaw: z.string().optional(),
643
- defBody: sourceBodySchema,
644
- })
645
- .strict();
646
- const envSchemaSchema = z
647
- .object({
648
- kind: z.literal("envSchema"),
649
- source: sourceFieldSchema,
650
- schemaBody: sourceBodySchema,
651
- })
652
- .strict();
653
- const aiStepOpaqueArgsSchema = z.custom(isRawRefSentinel, {
654
- message: "must be an unresolved reference ({ __raw })",
655
- });
656
- const aiStepPolicySchema = z
657
- .object({
658
- enabled: z.boolean(),
659
- providerId: z.string().optional(),
660
- model: z.string().optional(),
661
- params: z.custom(isPlainObject, {
662
- message: "params must be a plain object",
663
- }),
664
- })
665
- .strict();
666
- const stringOrAiOpaqueSchema = z.union([z.string(), aiStepOpaqueArgsSchema]);
667
- const aiStepPolicyOrOpaqueSchema = z.union([aiStepPolicySchema, aiStepOpaqueArgsSchema]);
668
- const aiGenerateSchema = z
669
- .object({
670
- kind: z.literal("ai.generate"),
671
- source: sourceFieldSchema,
672
- argsSource: aiStepOpaqueArgsSchema.optional(),
673
- stepKey: stringOrAiOpaqueSchema.optional(),
674
- promptKey: stringOrAiOpaqueSchema.optional(),
675
- promptFallback: stringOrAiOpaqueSchema.optional(),
676
- defaults: aiStepPolicyOrOpaqueSchema.optional(),
677
- paramsSchemaSource: sourceBodySchema.optional(),
678
- inputBody: sourceBodySchema.optional(),
679
- })
680
- .strict();
681
- const aiExtractSchema = z
682
- .object({
683
- kind: z.literal("ai.extract"),
684
- source: sourceFieldSchema,
685
- argsSource: aiStepOpaqueArgsSchema.optional(),
686
- stepKey: stringOrAiOpaqueSchema.optional(),
687
- promptKey: stringOrAiOpaqueSchema.optional(),
688
- promptFallback: stringOrAiOpaqueSchema.optional(),
689
- defaults: aiStepPolicyOrOpaqueSchema.optional(),
690
- paramsSchemaSource: sourceBodySchema.optional(),
691
- outputSchemaSource: sourceBodySchema.optional(),
692
- instructionsBody: sourceBodySchema.optional(),
693
- documentBody: sourceBodySchema.optional(),
694
- })
695
- .strict();
696
- const aiClassifySchema = z
697
- .object({
698
- kind: z.literal("ai.classify"),
699
- source: sourceFieldSchema,
700
- argsSource: aiStepOpaqueArgsSchema.optional(),
701
- stepKey: stringOrAiOpaqueSchema.optional(),
702
- promptKey: stringOrAiOpaqueSchema.optional(),
703
- promptFallback: stringOrAiOpaqueSchema.optional(),
704
- defaults: aiStepPolicyOrOpaqueSchema.optional(),
705
- paramsSchemaSource: sourceBodySchema.optional(),
706
- actions: z.array(z.object({ type: z.string(), description: z.string() }).strict()).optional(),
707
- inputBody: sourceBodySchema.optional(),
708
- })
709
- .strict();
710
- // =============================================================================
711
- // Catch-all
712
- // =============================================================================
713
- const unknownPatternSchema = z
714
- .object({
715
- kind: z.literal("unknown"),
716
- source: nonEmptySourceBodySchema,
717
- methodName: z.string(),
718
- })
719
- .strict();
720
- // =============================================================================
721
- // Pattern union — Record keyed by kind doubles as the exhaustiveness pin
722
- // consumed by the compile-time typtest (a missing/renamed kind fails to
723
- // compile here, same contract as patterns.ts's own switch statements).
724
- // =============================================================================
725
- export const PATTERN_SCHEMAS_BY_KIND = {
726
- entity: entitySchema,
727
- relation: relationSchema,
728
- nav: navSchema,
729
- workspace: workspaceSchema,
730
- config: configSchema,
731
- translations: translationsSchema,
732
- requires: requiresSchema,
733
- optionalRequires: optionalRequiresSchema,
734
- systemScope: systemScopeSchema,
735
- toggleable: toggleableSchema,
736
- describe: describeSchema,
737
- uiHints: uiHintsSchema,
738
- adoptsBundledLists: adoptsBundledListsSchema,
739
- metric: metricSchema,
740
- secret: secretSchema,
741
- secretNamespace: secretNamespaceSchema,
742
- claimKey: claimKeySchema,
743
- referenceData: referenceDataSchema,
744
- readsConfig: readsConfigSchema,
745
- useExtension: useExtensionSchema,
746
- usesApi: usesApiSchema,
747
- exposesApi: exposesApiSchema,
748
- treeActions: treeActionsSchema,
749
- screen: screenSchema,
750
- writeHandler: writeHandlerSchema,
751
- queryHandler: queryHandlerSchema,
752
- streamHandler: streamHandlerSchema,
753
- hook: hookSchema,
754
- job: jobSchema,
755
- notification: notificationSchema,
756
- authClaims: authClaimsSchema,
757
- httpRoute: httpRouteSchema,
758
- projection: projectionSchema,
759
- multiStreamProjection: multiStreamProjectionSchema,
760
- defineEvent: defineEventSchema,
761
- extendsRegistrar: extendsRegistrarSchema,
762
- envSchema: envSchemaSchema,
763
- "ai.generate": aiGenerateSchema,
764
- "ai.extract": aiExtractSchema,
765
- "ai.classify": aiClassifySchema,
766
- unknown: unknownPatternSchema,
767
- };
768
- export const patternSchema = z.discriminatedUnion("kind", [
769
- entitySchema,
770
- relationSchema,
771
- navSchema,
772
- workspaceSchema,
773
- configSchema,
774
- translationsSchema,
775
- requiresSchema,
776
- optionalRequiresSchema,
777
- systemScopeSchema,
778
- toggleableSchema,
779
- describeSchema,
780
- uiHintsSchema,
781
- adoptsBundledListsSchema,
782
- metricSchema,
783
- secretSchema,
784
- secretNamespaceSchema,
785
- claimKeySchema,
786
- referenceDataSchema,
787
- readsConfigSchema,
788
- useExtensionSchema,
789
- usesApiSchema,
790
- exposesApiSchema,
791
- treeActionsSchema,
792
- screenSchema,
793
- writeHandlerSchema,
794
- queryHandlerSchema,
795
- streamHandlerSchema,
796
- hookSchema,
797
- jobSchema,
798
- notificationSchema,
799
- authClaimsSchema,
800
- httpRouteSchema,
801
- projectionSchema,
802
- multiStreamProjectionSchema,
803
- defineEventSchema,
804
- extendsRegistrarSchema,
805
- envSchemaSchema,
806
- aiGenerateSchema,
807
- aiExtractSchema,
808
- aiClassifySchema,
809
- unknownPatternSchema,
810
- ]);
811
- // =============================================================================
812
- // Change union — `rationale` is accepted (optional, on every member) and
813
- // dropped when the final PatternChange is assembled below (plain field
814
- // selection, not a schema-level transform — see file-header rationale).
815
- // =============================================================================
816
- const addChangeSchema = z
817
- .object({
818
- op: z.literal("add"),
819
- pattern: patternSchema,
820
- rationale: z.string().optional(),
821
- })
822
- .strict();
823
- const replaceChangeSchema = z
824
- .object({
825
- op: z.literal("replace"),
826
- id: patternIdSchema,
827
- pattern: patternSchema,
828
- rationale: z.string().optional(),
829
- })
830
- .strict();
831
- const removeChangeSchema = z
832
- .object({
833
- op: z.literal("remove"),
834
- id: patternIdSchema,
835
- rationale: z.string().optional(),
836
- })
837
- .strict();
838
- // `set`/`unset` are validated loosely here; the real per-kind check happens
839
- // in a second pass once `id.kind` is known (see parseUpdateChange).
840
- const updateChangeSchema = z
841
- .object({
842
- op: z.literal("update"),
843
- id: patternIdSchema,
844
- set: z.record(z.string(), z.unknown()).optional(),
845
- unset: z.array(z.string()).optional(),
846
- rationale: z.string().optional(),
847
- })
848
- .strict();
849
- const changeSchema = z.discriminatedUnion("op", [
850
- addChangeSchema,
851
- replaceChangeSchema,
852
- removeChangeSchema,
853
- updateChangeSchema,
854
- ]);
855
- function prefixIssuePath(issues, prefix) {
856
- return issues.map((issue) => ({ ...issue, path: [prefix, ...issue.path] }));
857
- }
858
- // Shared per-`unset[j]` checks ("access" is fixed-required, overlap with
859
- // `set`) ahead of the kind-specific enum parse in parseHeaderSetAndUnset.
860
- function unsetElementIssue(key, j, index, setKeys) {
861
- if (key === "access") {
862
- return {
863
- path: `changes[${index}].unset[${j}]`,
864
- message: "access is required and cannot be unset",
865
- };
866
- }
867
- if (setKeys.has(key)) {
868
- return { path: `changes[${index}].unset[${j}]`, message: "key is also in set" };
869
- }
870
- return undefined;
871
- }
872
- // Shared set/unset validation for one handler kind's Set-schema/Unset-enum —
873
- // the only thing that differs per kind (see the switch below).
874
- function parseHeaderSetAndUnset(setSchema, unsetEnum, kindLabel, value, index, rawItem) {
875
- const issues = [];
876
- const setResult = setSchema.safeParse(value.set ?? {});
877
- if (!setResult.success) {
878
- issues.push(...formatZodIssues(prefixIssuePath(setResult.error.issues, "set"), index, rawItem));
879
- }
880
- const setKeys = new Set(Object.keys(value.set ?? {}));
881
- const unsetInput = value.unset ?? [];
882
- const validatedUnset = [];
883
- unsetInput.forEach((key, j) => {
884
- const preIssue = unsetElementIssue(key, j, index, setKeys);
885
- if (preIssue) {
886
- issues.push(preIssue);
887
- // skip: already reported, no further checks apply to this element
888
- return;
889
- }
890
- const parsed = unsetEnum.safeParse(key);
891
- if (!parsed.success) {
892
- issues.push({
893
- path: `changes[${index}].unset[${j}]`,
894
- message: `"${key}" is not a header field of ${kindLabel}`,
895
- });
896
- // skip: already reported, no further checks apply to this element
897
- return;
898
- }
899
- validatedUnset.push(parsed.data);
900
- });
901
- const hasSet = value.set !== undefined && Object.keys(value.set).length > 0;
902
- if (!hasSet && unsetInput.length === 0) {
903
- issues.push({
904
- path: `changes[${index}].set`,
905
- message: "update needs at least one key in set or unset",
906
- });
907
- }
908
- if (!setResult.success || issues.length > 0)
909
- return { ok: false, issues };
910
- return { ok: true, set: setResult.data, unset: validatedUnset };
911
- }
912
- // Per-kind switch so `value.id` narrows and `change` needs no cast.
913
- function parseUpdateChange(value, index, rawItem) {
914
- switch (value.id.kind) {
915
- case "writeHandler": {
916
- const result = parseHeaderSetAndUnset(WRITE_HANDLER_UPDATE_SET_SCHEMA, WRITE_HANDLER_UPDATE_UNSET_ENUM, "writeHandler", value, index, rawItem);
917
- if (!result.ok)
918
- return { issues: result.issues };
919
- const change = {
920
- op: "update",
921
- id: value.id,
922
- set: result.set,
923
- ...(result.unset.length > 0 ? { unset: result.unset } : {}),
924
- };
925
- return { change, issues: [] };
926
- }
927
- case "queryHandler": {
928
- const result = parseHeaderSetAndUnset(QUERY_HANDLER_UPDATE_SET_SCHEMA, QUERY_HANDLER_UPDATE_UNSET_ENUM, "queryHandler", value, index, rawItem);
929
- if (!result.ok)
930
- return { issues: result.issues };
931
- const change = {
932
- op: "update",
933
- id: value.id,
934
- set: result.set,
935
- ...(result.unset.length > 0 ? { unset: result.unset } : {}),
936
- };
937
- return { change, issues: [] };
938
- }
939
- case "streamHandler": {
940
- const result = parseHeaderSetAndUnset(STREAM_HANDLER_UPDATE_SET_SCHEMA, STREAM_HANDLER_UPDATE_UNSET_ENUM, "streamHandler", value, index, rawItem);
941
- if (!result.ok)
942
- return { issues: result.issues };
943
- const change = {
944
- op: "update",
945
- id: value.id,
946
- set: result.set,
947
- ...(result.unset.length > 0 ? { unset: result.unset } : {}),
948
- };
949
- return { change, issues: [] };
950
- }
951
- default:
952
- return {
953
- issues: [
954
- {
955
- path: `changes[${index}].id.kind`,
956
- message: `update is not supported for kind "${value.id.kind}"; use replace`,
957
- },
958
- ],
959
- };
960
- }
961
- }
962
- // =============================================================================
963
- // Issue formatting
964
- // =============================================================================
965
- function formatPath(index, path) {
966
- let out = `changes[${index}]`;
967
- for (const segment of path) {
968
- out += typeof segment === "number" ? `[${segment}]` : `.${String(segment)}`;
969
- }
970
- return out;
971
- }
972
- function getAtPath(root, path) {
973
- let current = root;
974
- for (const segment of path) {
975
- if (isPlainObject(current)) {
976
- current = current[String(segment)];
977
- }
978
- else if (Array.isArray(current) && typeof segment === "number") {
979
- current = current[segment];
980
- }
981
- else {
982
- return undefined;
983
- }
984
- }
985
- return current;
986
- }
987
- // zod v4 reports `.strict()` violations as a single `unrecognized_keys`
988
- // issue per offending object, carrying all extra key names at once. We
989
- // split it into one PatternChangeIssue per key so each unexpected key gets
990
- // its own actionable path — except `definition` on a handler-kind pattern
991
- // nesting an `access` sub-key, which gets the more specific message the
992
- // spec calls for (a caller who nests `access` under a stray `definition`
993
- // key is making one specific, common mistake, not an arbitrary unknown key).
994
- // Only these kinds render a top-level `access`; on any other kind the hint
995
- // would send the caller into a second rejection.
996
- function isKindWithTopLevelAccess(kind) {
997
- return kind === "writeHandler" || kind === "queryHandler" || kind === "streamHandler";
998
- }
999
- function formatZodIssues(issues, index, rawItem) {
1000
- const out = [];
1001
- for (const issue of issues) {
1002
- if (issue.code === "unrecognized_keys") {
1003
- const parentValue = getAtPath(rawItem, issue.path);
1004
- for (const key of issue.keys) {
1005
- const keyValue = isPlainObject(parentValue) ? parentValue[key] : undefined;
1006
- if (key === "definition" &&
1007
- isPlainObject(parentValue) &&
1008
- isKindWithTopLevelAccess(parentValue["kind"]) &&
1009
- isPlainObject(keyValue) &&
1010
- "access" in keyValue) {
1011
- out.push({
1012
- path: `${formatPath(index, issue.path)}.definition.access`,
1013
- message: "unexpected key; access belongs at top level of the pattern",
1014
- });
1015
- continue;
1016
- }
1017
- out.push({
1018
- path: `${formatPath(index, issue.path)}.${key}`,
1019
- message: "unexpected key",
1020
- });
1021
- }
1022
- continue;
1023
- }
1024
- out.push({ path: formatPath(index, issue.path), message: issue.message });
1025
- }
1026
- return out;
1027
- }
1028
- // =============================================================================
1029
- // Public API
1030
- // =============================================================================
1031
- export function parsePatternChanges(input) {
1032
- if (!Array.isArray(input)) {
1033
- return { ok: false, issues: [{ path: "changes", message: "must be an array" }] };
1034
- }
1035
- const issues = [];
1036
- const changes = [];
1037
- input.forEach((item, index) => {
1038
- const result = changeSchema.safeParse(item);
1039
- if (!result.success) {
1040
- issues.push(...formatZodIssues(result.error.issues, index, item));
1041
- // skip: schema violations already reported as issues
1042
- return;
1043
- }
1044
- const value = result.data;
1045
- if (value.op === "replace" && value.id.kind !== value.pattern.kind) {
1046
- issues.push({
1047
- path: `changes[${index}].pattern.kind`,
1048
- message: `pattern.kind "${value.pattern.kind}" does not match id.kind "${value.id.kind}"`,
1049
- });
1050
- // skip: id/pattern kind mismatch already reported as an issue
1051
- return;
1052
- }
1053
- if (value.op === "add") {
1054
- changes.push({ op: "add", pattern: value.pattern });
1055
- }
1056
- else if (value.op === "replace") {
1057
- changes.push({ op: "replace", id: value.id, pattern: value.pattern });
1058
- }
1059
- else if (value.op === "remove") {
1060
- changes.push({ op: "remove", id: value.id });
1061
- }
1062
- else {
1063
- const outcome = parseUpdateChange(value, index, item);
1064
- issues.push(...outcome.issues);
1065
- if (outcome.change)
1066
- changes.push(outcome.change);
1067
- }
1068
- });
1069
- if (issues.length > 0)
1070
- return { ok: false, issues };
1071
- return { ok: true, changes };
1072
- }