@cosmicdrift/kumiko-framework 0.1.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 (388) hide show
  1. package/README.md +159 -0
  2. package/package.json +91 -0
  3. package/src/__tests__/anonymous-access.integration.ts +325 -0
  4. package/src/__tests__/error-contract.integration.ts +435 -0
  5. package/src/__tests__/field-access.integration.ts +269 -0
  6. package/src/__tests__/full-stack.integration.ts +914 -0
  7. package/src/__tests__/ownership.integration.ts +449 -0
  8. package/src/__tests__/reference-data.integration.ts +198 -0
  9. package/src/__tests__/transition-guard.integration.ts +340 -0
  10. package/src/api/__tests__/api.test.ts +337 -0
  11. package/src/api/__tests__/auth-middleware-transport.test.ts +80 -0
  12. package/src/api/__tests__/auth-routes-cookie.test.ts +179 -0
  13. package/src/api/__tests__/batch.integration.ts +404 -0
  14. package/src/api/__tests__/body-limit.test.ts +88 -0
  15. package/src/api/__tests__/csrf-middleware.test.ts +97 -0
  16. package/src/api/__tests__/dispatcher-live.integration.ts +216 -0
  17. package/src/api/__tests__/metrics-endpoint.test.ts +126 -0
  18. package/src/api/__tests__/nested-write.integration.ts +213 -0
  19. package/src/api/__tests__/readiness.test.ts +76 -0
  20. package/src/api/__tests__/request-id-middleware.test.ts +72 -0
  21. package/src/api/__tests__/sse-broker.test.ts +58 -0
  22. package/src/api/__tests__/sse-route.test.ts +112 -0
  23. package/src/api/anonymous-cookie.ts +60 -0
  24. package/src/api/api-constants.ts +64 -0
  25. package/src/api/auth-middleware.ts +418 -0
  26. package/src/api/auth-routes.ts +982 -0
  27. package/src/api/csrf-middleware.ts +77 -0
  28. package/src/api/index.ts +31 -0
  29. package/src/api/jwt.ts +66 -0
  30. package/src/api/observability-middleware.ts +89 -0
  31. package/src/api/readiness.ts +132 -0
  32. package/src/api/request-context.ts +49 -0
  33. package/src/api/request-id-middleware.ts +50 -0
  34. package/src/api/route-registrars.ts +195 -0
  35. package/src/api/routes.ts +135 -0
  36. package/src/api/server.ts +640 -0
  37. package/src/api/sse-broker.ts +71 -0
  38. package/src/api/sse-route.ts +62 -0
  39. package/src/api/tokens.ts +16 -0
  40. package/src/db/__tests__/apply-entity-event-tenant.integration.ts +159 -0
  41. package/src/db/__tests__/compound-types.test.ts +114 -0
  42. package/src/db/__tests__/connection-options.test.ts +68 -0
  43. package/src/db/__tests__/cursor.test.ts +41 -0
  44. package/src/db/__tests__/db-helpers.test.ts +369 -0
  45. package/src/db/__tests__/dialect-instant.test.ts +50 -0
  46. package/src/db/__tests__/drizzle-helpers.integration.ts +186 -0
  47. package/src/db/__tests__/drizzle-table-types.test.ts +162 -0
  48. package/src/db/__tests__/encryption.test.ts +39 -0
  49. package/src/db/__tests__/event-store-executor-list.integration.ts +313 -0
  50. package/src/db/__tests__/event-store-executor.integration.ts +235 -0
  51. package/src/db/__tests__/implicit-projection-equivalence.integration.ts +304 -0
  52. package/src/db/__tests__/located-timestamp.test.ts +184 -0
  53. package/src/db/__tests__/money.test.ts +199 -0
  54. package/src/db/__tests__/multi-row-insert.integration.ts +76 -0
  55. package/src/db/__tests__/parse-auto-verb.test.ts +70 -0
  56. package/src/db/__tests__/required-not-null-migration-safety.integration.ts +105 -0
  57. package/src/db/__tests__/row-helpers.test.ts +59 -0
  58. package/src/db/__tests__/schema-migration.integration.ts +273 -0
  59. package/src/db/__tests__/table-builder-indexes.test.ts +153 -0
  60. package/src/db/__tests__/table-builder-required.test.ts +216 -0
  61. package/src/db/__tests__/tenant-db.integration.ts +606 -0
  62. package/src/db/__tests__/unique-violation-mapping.integration.ts +166 -0
  63. package/src/db/apply-entity-event.ts +188 -0
  64. package/src/db/assert-exists-in.ts +59 -0
  65. package/src/db/compound-types.ts +47 -0
  66. package/src/db/connection.ts +104 -0
  67. package/src/db/cursor.ts +83 -0
  68. package/src/db/dialect.ts +109 -0
  69. package/src/db/eagerload.ts +174 -0
  70. package/src/db/encryption.ts +39 -0
  71. package/src/db/event-store-executor.ts +906 -0
  72. package/src/db/index.ts +55 -0
  73. package/src/db/located-timestamp.ts +114 -0
  74. package/src/db/money.ts +120 -0
  75. package/src/db/pg-error.ts +46 -0
  76. package/src/db/reference-data.ts +77 -0
  77. package/src/db/row-helpers.ts +53 -0
  78. package/src/db/schema-inspection.ts +25 -0
  79. package/src/db/table-builder.ts +475 -0
  80. package/src/db/tenant-db.ts +434 -0
  81. package/src/engine/__tests__/auth-claims-registrar.test.ts +74 -0
  82. package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +108 -0
  83. package/src/engine/__tests__/boot-validator.test.ts +1865 -0
  84. package/src/engine/__tests__/build-app-schema.test.ts +154 -0
  85. package/src/engine/__tests__/claim-keys.test.ts +274 -0
  86. package/src/engine/__tests__/config-helpers.test.ts +236 -0
  87. package/src/engine/__tests__/effective-features.test.ts +86 -0
  88. package/src/engine/__tests__/engine.test.ts +1461 -0
  89. package/src/engine/__tests__/entity-handlers.test.ts +274 -0
  90. package/src/engine/__tests__/event-helpers.test.ts +68 -0
  91. package/src/engine/__tests__/extends-registrar.test.ts +159 -0
  92. package/src/engine/__tests__/factories-long-text.test.ts +84 -0
  93. package/src/engine/__tests__/factories-time.test.ts +158 -0
  94. package/src/engine/__tests__/field-predicates.test.ts +48 -0
  95. package/src/engine/__tests__/hook-phases.test.ts +132 -0
  96. package/src/engine/__tests__/identifiers.test.ts +35 -0
  97. package/src/engine/__tests__/lifecycle-hooks.test.ts +237 -0
  98. package/src/engine/__tests__/nav.test.ts +267 -0
  99. package/src/engine/__tests__/ownership.test.ts +421 -0
  100. package/src/engine/__tests__/parse-ref-target.test.ts +43 -0
  101. package/src/engine/__tests__/projection-helpers.test.ts +62 -0
  102. package/src/engine/__tests__/projection.test.ts +191 -0
  103. package/src/engine/__tests__/qualified-name.test.ts +264 -0
  104. package/src/engine/__tests__/resolve-config-or-param.test.ts +315 -0
  105. package/src/engine/__tests__/run-in.test.ts +38 -0
  106. package/src/engine/__tests__/schema-builder.test.ts +380 -0
  107. package/src/engine/__tests__/screen.test.ts +408 -0
  108. package/src/engine/__tests__/state-machine.test.ts +148 -0
  109. package/src/engine/__tests__/system-user.test.ts +57 -0
  110. package/src/engine/__tests__/validation-hooks.test.ts +71 -0
  111. package/src/engine/access.ts +23 -0
  112. package/src/engine/boot-validator.ts +1528 -0
  113. package/src/engine/build-app-schema.ts +125 -0
  114. package/src/engine/config-helpers.ts +115 -0
  115. package/src/engine/constants.ts +85 -0
  116. package/src/engine/create-app.ts +98 -0
  117. package/src/engine/define-feature.ts +702 -0
  118. package/src/engine/define-handler.ts +78 -0
  119. package/src/engine/define-roles.ts +19 -0
  120. package/src/engine/effective-features.ts +87 -0
  121. package/src/engine/entity-handlers.ts +364 -0
  122. package/src/engine/event-helpers.ts +73 -0
  123. package/src/engine/factories.ts +328 -0
  124. package/src/engine/feature-ast/__tests__/canonical-form.test.ts +416 -0
  125. package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +197 -0
  126. package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +128 -0
  127. package/src/engine/feature-ast/__tests__/parse.test.ts +888 -0
  128. package/src/engine/feature-ast/__tests__/patch.test.ts +360 -0
  129. package/src/engine/feature-ast/__tests__/patcher.test.ts +469 -0
  130. package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +287 -0
  131. package/src/engine/feature-ast/extractors.ts +2562 -0
  132. package/src/engine/feature-ast/index.ts +105 -0
  133. package/src/engine/feature-ast/parse.ts +369 -0
  134. package/src/engine/feature-ast/patch.ts +525 -0
  135. package/src/engine/feature-ast/patcher.ts +518 -0
  136. package/src/engine/feature-ast/patterns.ts +434 -0
  137. package/src/engine/feature-ast/render.ts +602 -0
  138. package/src/engine/feature-ast/source-location.ts +45 -0
  139. package/src/engine/field-access.ts +120 -0
  140. package/src/engine/index.ts +254 -0
  141. package/src/engine/ownership.ts +337 -0
  142. package/src/engine/parse-ref-target.ts +22 -0
  143. package/src/engine/pattern-library/__tests__/library.test.ts +351 -0
  144. package/src/engine/pattern-library/index.ts +24 -0
  145. package/src/engine/pattern-library/library.ts +1117 -0
  146. package/src/engine/pattern-library/types.ts +255 -0
  147. package/src/engine/projection-helpers.ts +85 -0
  148. package/src/engine/qualified-name.ts +122 -0
  149. package/src/engine/read-claim.ts +31 -0
  150. package/src/engine/registry.ts +1325 -0
  151. package/src/engine/resolve-config-or-param.ts +153 -0
  152. package/src/engine/run-in.ts +29 -0
  153. package/src/engine/schema-builder.ts +175 -0
  154. package/src/engine/screen-filter-ops.ts +51 -0
  155. package/src/engine/state-machine.ts +70 -0
  156. package/src/engine/system-user.ts +32 -0
  157. package/src/engine/types/config.ts +306 -0
  158. package/src/engine/types/event-type-map.ts +37 -0
  159. package/src/engine/types/feature.ts +574 -0
  160. package/src/engine/types/fields.ts +422 -0
  161. package/src/engine/types/handlers.ts +742 -0
  162. package/src/engine/types/hooks.ts +142 -0
  163. package/src/engine/types/http-route.ts +54 -0
  164. package/src/engine/types/identifiers.ts +47 -0
  165. package/src/engine/types/index.ts +208 -0
  166. package/src/engine/types/nav.ts +46 -0
  167. package/src/engine/types/projection.ts +132 -0
  168. package/src/engine/types/relations.ts +51 -0
  169. package/src/engine/types/screen.ts +452 -0
  170. package/src/engine/types/workspace.ts +42 -0
  171. package/src/engine/validation.ts +33 -0
  172. package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.ts +173 -0
  173. package/src/entrypoint/__tests__/split-deploy.integration.ts +297 -0
  174. package/src/entrypoint/index.ts +442 -0
  175. package/src/errors/__tests__/classes.test.ts +371 -0
  176. package/src/errors/__tests__/write-failures.test.ts +109 -0
  177. package/src/errors/classes.ts +249 -0
  178. package/src/errors/i18n/de.yaml +83 -0
  179. package/src/errors/i18n/en.yaml +80 -0
  180. package/src/errors/index.ts +41 -0
  181. package/src/errors/kumiko-error.ts +67 -0
  182. package/src/errors/reasons.ts +36 -0
  183. package/src/errors/serialize.ts +136 -0
  184. package/src/errors/transition-details.ts +30 -0
  185. package/src/errors/write-error-info.ts +123 -0
  186. package/src/errors/zod-bridge.ts +49 -0
  187. package/src/event-store/__tests__/admin-api.integration.ts +361 -0
  188. package/src/event-store/__tests__/event-store.integration.ts +584 -0
  189. package/src/event-store/__tests__/get-stream-version-perf.integration.ts +83 -0
  190. package/src/event-store/__tests__/perf.integration.ts +255 -0
  191. package/src/event-store/__tests__/snapshot.integration.ts +267 -0
  192. package/src/event-store/__tests__/upcaster-dead-letter.integration.ts +204 -0
  193. package/src/event-store/__tests__/upcaster.integration.ts +460 -0
  194. package/src/event-store/admin-api.ts +257 -0
  195. package/src/event-store/archive.ts +106 -0
  196. package/src/event-store/errors.ts +35 -0
  197. package/src/event-store/event-store.ts +405 -0
  198. package/src/event-store/events-schema.ts +90 -0
  199. package/src/event-store/index.ts +50 -0
  200. package/src/event-store/snapshot.ts +210 -0
  201. package/src/event-store/upcaster-dead-letter.ts +119 -0
  202. package/src/event-store/upcaster.ts +147 -0
  203. package/src/files/__tests__/content-disposition.test.ts +123 -0
  204. package/src/files/__tests__/file-field-column.integration.ts +103 -0
  205. package/src/files/__tests__/file-field-pipeline.integration.ts +211 -0
  206. package/src/files/__tests__/file-handle.test.ts +122 -0
  207. package/src/files/__tests__/files.integration.ts +830 -0
  208. package/src/files/__tests__/storage-tracking.integration.ts +153 -0
  209. package/src/files/content-disposition.ts +55 -0
  210. package/src/files/file-handle.ts +63 -0
  211. package/src/files/file-ref-table.ts +22 -0
  212. package/src/files/file-routes.ts +353 -0
  213. package/src/files/in-memory-provider.ts +62 -0
  214. package/src/files/index.ts +29 -0
  215. package/src/files/local-provider.ts +35 -0
  216. package/src/files/storage-tracking.ts +60 -0
  217. package/src/files/types.ts +118 -0
  218. package/src/i18n/__tests__/i18n.test.ts +72 -0
  219. package/src/i18n/index.ts +29 -0
  220. package/src/jobs/__tests__/job-event-trigger.integration.ts +172 -0
  221. package/src/jobs/__tests__/job-multi-trigger.integration.ts +144 -0
  222. package/src/jobs/__tests__/jobs.integration.ts +566 -0
  223. package/src/jobs/index.ts +2 -0
  224. package/src/jobs/job-runner.ts +574 -0
  225. package/src/lifecycle/__tests__/create-test-lifecycle.ts +19 -0
  226. package/src/lifecycle/__tests__/lifecycle-server.integration.ts +108 -0
  227. package/src/lifecycle/__tests__/lifecycle.test.ts +212 -0
  228. package/src/lifecycle/__tests__/signal-handlers.test.ts +106 -0
  229. package/src/lifecycle/index.ts +13 -0
  230. package/src/lifecycle/lifecycle.ts +160 -0
  231. package/src/lifecycle/signal-handlers.ts +62 -0
  232. package/src/logging/__tests__/pino-trace-bridge.test.ts +50 -0
  233. package/src/logging/index.ts +3 -0
  234. package/src/logging/pino-logger.ts +64 -0
  235. package/src/logging/types.ts +7 -0
  236. package/src/migrations/__tests__/compare-snapshots.test.ts +150 -0
  237. package/src/migrations/__tests__/detect-drift.integration.ts +320 -0
  238. package/src/migrations/__tests__/detect-projections-to-rebuild.integration.ts +134 -0
  239. package/src/migrations/__tests__/rebuild-marker.test.ts +79 -0
  240. package/src/migrations/index.ts +28 -0
  241. package/src/migrations/projection-detection.ts +149 -0
  242. package/src/migrations/rebuild-marker.ts +64 -0
  243. package/src/migrations/schema-drift.ts +395 -0
  244. package/src/observability/__tests__/console-provider.test.ts +67 -0
  245. package/src/observability/__tests__/metric-validator.test.ts +87 -0
  246. package/src/observability/__tests__/noop-provider.test.ts +82 -0
  247. package/src/observability/__tests__/observability.integration.ts +559 -0
  248. package/src/observability/__tests__/prometheus-meter.test.ts +144 -0
  249. package/src/observability/__tests__/recording-meter.test.ts +101 -0
  250. package/src/observability/__tests__/recording-tracer.test.ts +110 -0
  251. package/src/observability/__tests__/sensitive-filter.test.ts +98 -0
  252. package/src/observability/console-provider.ts +130 -0
  253. package/src/observability/context.ts +26 -0
  254. package/src/observability/fallback.ts +34 -0
  255. package/src/observability/ids.ts +25 -0
  256. package/src/observability/index.ts +79 -0
  257. package/src/observability/metric-validator.ts +86 -0
  258. package/src/observability/metrics-handle.ts +56 -0
  259. package/src/observability/noop-provider.ts +146 -0
  260. package/src/observability/prometheus-meter.ts +284 -0
  261. package/src/observability/recording-meter.ts +156 -0
  262. package/src/observability/recording-tracer.ts +198 -0
  263. package/src/observability/redis-wrapper.ts +132 -0
  264. package/src/observability/sensitive-filter.ts +108 -0
  265. package/src/observability/standard-metrics.ts +213 -0
  266. package/src/observability/types/index.ts +29 -0
  267. package/src/observability/types/metric.ts +56 -0
  268. package/src/observability/types/provider.ts +32 -0
  269. package/src/observability/types/span.ts +64 -0
  270. package/src/pipeline/__tests__/archive-stream.integration.ts +220 -0
  271. package/src/pipeline/__tests__/auth-claims-resolver.test.ts +279 -0
  272. package/src/pipeline/__tests__/cascade-handler.integration.ts +419 -0
  273. package/src/pipeline/__tests__/cascade-handler.test.ts +52 -0
  274. package/src/pipeline/__tests__/causation-chain.integration.ts +206 -0
  275. package/src/pipeline/__tests__/ctx-bridge.integration.ts +234 -0
  276. package/src/pipeline/__tests__/dispatcher.test.ts +379 -0
  277. package/src/pipeline/__tests__/distributed-lock.integration.ts +67 -0
  278. package/src/pipeline/__tests__/domain-events-projections.integration.ts +323 -0
  279. package/src/pipeline/__tests__/event-dedup.integration.ts +153 -0
  280. package/src/pipeline/__tests__/event-define-event-strict.integration.ts +202 -0
  281. package/src/pipeline/__tests__/event-dispatcher-lifecycle.integration.ts +220 -0
  282. package/src/pipeline/__tests__/event-dispatcher-multi-instance.integration.ts +423 -0
  283. package/src/pipeline/__tests__/event-dispatcher-pg-listen.integration.ts +123 -0
  284. package/src/pipeline/__tests__/event-dispatcher-recovery.integration.ts +202 -0
  285. package/src/pipeline/__tests__/event-dispatcher-second-audit.integration.ts +290 -0
  286. package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +65 -0
  287. package/src/pipeline/__tests__/event-dispatcher.integration.ts +287 -0
  288. package/src/pipeline/__tests__/event-retention.integration.ts +239 -0
  289. package/src/pipeline/__tests__/fetch-for-writing.integration.ts +281 -0
  290. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +430 -0
  291. package/src/pipeline/__tests__/load-aggregate-query.integration.ts +266 -0
  292. package/src/pipeline/__tests__/msp-error-mode.integration.ts +149 -0
  293. package/src/pipeline/__tests__/msp-multi-hop.integration.ts +228 -0
  294. package/src/pipeline/__tests__/msp-rebuild.integration.ts +368 -0
  295. package/src/pipeline/__tests__/multi-stream-projection.integration.ts +341 -0
  296. package/src/pipeline/__tests__/perf-rebuild.integration.ts +147 -0
  297. package/src/pipeline/__tests__/projection-rebuild.integration.ts +551 -0
  298. package/src/pipeline/__tests__/query-projection.integration.ts +201 -0
  299. package/src/pipeline/__tests__/redis-pipeline.integration.ts +306 -0
  300. package/src/pipeline/append-event-core.ts +117 -0
  301. package/src/pipeline/auth-claims-resolver.ts +103 -0
  302. package/src/pipeline/cascade-handler.ts +113 -0
  303. package/src/pipeline/dispatcher.ts +1585 -0
  304. package/src/pipeline/distributed-lock.ts +37 -0
  305. package/src/pipeline/entity-cache.ts +113 -0
  306. package/src/pipeline/event-consumer-state.ts +108 -0
  307. package/src/pipeline/event-dedup.ts +23 -0
  308. package/src/pipeline/event-dispatcher.ts +1016 -0
  309. package/src/pipeline/event-retention.ts +154 -0
  310. package/src/pipeline/idempotency.ts +76 -0
  311. package/src/pipeline/index.ts +66 -0
  312. package/src/pipeline/lifecycle-pipeline.ts +409 -0
  313. package/src/pipeline/msp-rebuild.ts +242 -0
  314. package/src/pipeline/multi-stream-apply-context.ts +115 -0
  315. package/src/pipeline/projection-rebuild.ts +334 -0
  316. package/src/pipeline/projection-state.ts +72 -0
  317. package/src/pipeline/projections-runner.ts +56 -0
  318. package/src/pipeline/redis-keys.ts +11 -0
  319. package/src/pipeline/system-hooks.ts +190 -0
  320. package/src/random/__tests__/generate.test.ts +149 -0
  321. package/src/random/generate.ts +141 -0
  322. package/src/random/index.ts +8 -0
  323. package/src/random/words.ts +392 -0
  324. package/src/rate-limit/__tests__/dispatcher-l3.integration.ts +111 -0
  325. package/src/rate-limit/__tests__/middleware.integration.ts +189 -0
  326. package/src/rate-limit/__tests__/resolver.integration.ts +189 -0
  327. package/src/rate-limit/bucket.ts +36 -0
  328. package/src/rate-limit/index.ts +14 -0
  329. package/src/rate-limit/middleware.ts +152 -0
  330. package/src/rate-limit/resolver.ts +267 -0
  331. package/src/redis/__tests__/redis-options.test.ts +54 -0
  332. package/src/redis/index.ts +74 -0
  333. package/src/search/__tests__/meilisearch-adapter.integration.ts +236 -0
  334. package/src/search/__tests__/search-adapter.test.ts +256 -0
  335. package/src/search/in-memory-adapter.ts +123 -0
  336. package/src/search/index.ts +12 -0
  337. package/src/search/meilisearch-adapter.ts +106 -0
  338. package/src/search/types.ts +39 -0
  339. package/src/secrets/__tests__/dek-cache.test.ts +213 -0
  340. package/src/secrets/__tests__/env-master-key-provider.test.ts +119 -0
  341. package/src/secrets/__tests__/envelope.test.ts +74 -0
  342. package/src/secrets/__tests__/leak-guard.test.ts +92 -0
  343. package/src/secrets/__tests__/rotation.test.ts +149 -0
  344. package/src/secrets/dek-cache.ts +116 -0
  345. package/src/secrets/env-master-key-provider.ts +162 -0
  346. package/src/secrets/envelope.ts +55 -0
  347. package/src/secrets/index.ts +19 -0
  348. package/src/secrets/leak-guard.ts +87 -0
  349. package/src/secrets/rotation.ts +34 -0
  350. package/src/secrets/types.ts +107 -0
  351. package/src/stack/db.ts +104 -0
  352. package/src/stack/event-collector.ts +23 -0
  353. package/src/stack/index.ts +32 -0
  354. package/src/stack/redis.ts +44 -0
  355. package/src/stack/request-helper.ts +168 -0
  356. package/src/stack/table-helpers.ts +104 -0
  357. package/src/stack/test-stack.ts +357 -0
  358. package/src/stack/test-users.ts +37 -0
  359. package/src/testing/__tests__/e2e-generator.test.ts +230 -0
  360. package/src/testing/__tests__/ensure-entity-table.integration.ts +54 -0
  361. package/src/testing/access-assertions.ts +15 -0
  362. package/src/testing/assertions.ts +35 -0
  363. package/src/testing/e2e-generator.ts +465 -0
  364. package/src/testing/expect-error.ts +25 -0
  365. package/src/testing/handler-context.ts +125 -0
  366. package/src/testing/http-cookies.ts +52 -0
  367. package/src/testing/index.ts +41 -0
  368. package/src/testing/late-bound.ts +39 -0
  369. package/src/testing/mutable-master-key-provider.ts +31 -0
  370. package/src/testing/observability-recorder.ts +54 -0
  371. package/src/testing/shared-entities.ts +49 -0
  372. package/src/testing/utils.ts +1 -0
  373. package/src/testing/wait-for.ts +31 -0
  374. package/src/time/__tests__/polyfill.test.ts +73 -0
  375. package/src/time/__tests__/tz-context.test.ts +121 -0
  376. package/src/time/index.ts +21 -0
  377. package/src/time/polyfill.ts +70 -0
  378. package/src/time/tz-context.ts +107 -0
  379. package/src/ui-types/app-schema.ts +57 -0
  380. package/src/ui-types/index.ts +65 -0
  381. package/src/utils/__tests__/assert.test.ts +17 -0
  382. package/src/utils/__tests__/env-parse.test.ts +54 -0
  383. package/src/utils/assert.ts +18 -0
  384. package/src/utils/env-parse.ts +16 -0
  385. package/src/utils/ids.ts +16 -0
  386. package/src/utils/index.ts +5 -0
  387. package/src/utils/safe-json.ts +30 -0
  388. package/src/utils/serialization.ts +7 -0
@@ -0,0 +1,434 @@
1
+ // FeaturePattern — typed representation of an `r.*` call inside a
2
+ // feature file. The AST visitor (parse.ts) walks the
3
+ // `defineFeature(name, (r) => { ... })` setup callback and yields one
4
+ // FeaturePattern per recognised call.
5
+ //
6
+ // **Design principle:**
7
+ //
8
+ // - Whatever the Designer/AI can edit declaratively → typed static
9
+ // fields, reusing the existing engine/types definitions so the
10
+ // pattern shape never drifts from the runtime contract.
11
+ // - Whatever carries closures/code → SourceLocation pointing at the
12
+ // opaque region. The Designer renders that as a read-only code
13
+ // block; the AI patcher overwrites the span verbatim.
14
+ //
15
+ // **Coverage = 100%.** Calls we don't recognise become UnknownPattern
16
+ // (the Designer shows "custom call", AI leaves them alone). Custom
17
+ // TypeScript code BETWEEN `r.*` calls (helpers, local consts, imports)
18
+ // is not extracted — it stays in the file buffer and survives every
19
+ // patch unchanged.
20
+ //
21
+ // **Extension point.** Adding a new r.* API → new pattern type here +
22
+ // new extractor in parse.ts. The discriminated union forces every
23
+ // consumer (Designer, AI patcher, MCP server) to handle the new kind
24
+ // at compile time.
25
+ //
26
+ // **Naming convention.** Pattern `kind` matches the r.* method name
27
+ // 1:1 (e.g. `r.writeHandler` → `kind: "writeHandler"`). No kebab/camel
28
+ // translation layer.
29
+
30
+ import type { LifecycleHookType } from "../constants";
31
+ import type {
32
+ ConfigKeyDefinition,
33
+ ConfigKeyType,
34
+ JobDefinition,
35
+ ReferenceDataDef,
36
+ RunIn,
37
+ TranslationKeys,
38
+ } from "../types/config";
39
+ import type { MetricOptions, SecretOptions } from "../types/feature";
40
+ import type { EntityDefinition } from "../types/fields";
41
+ import type { AccessRule, ClaimKeyType, RateLimitOption } from "../types/handlers";
42
+ import type { HookPhase } from "../types/hooks";
43
+ import type { HttpRouteMethod } from "../types/http-route";
44
+ import type { NavDefinition } from "../types/nav";
45
+ import type { MspErrorMode } from "../types/projection";
46
+ import type { RelationDefinition } from "../types/relations";
47
+ import type { ScreenDefinition } from "../types/screen";
48
+ import type { WorkspaceDefinition } from "../types/workspace";
49
+ import type { SourceLocation } from "./source-location";
50
+
51
+ // =============================================================================
52
+ // Static patterns — fully declarative. Designer renders forms, AI
53
+ // generates them as pure data. Round-trip without code spans.
54
+ // =============================================================================
55
+
56
+ export type EntityPattern = {
57
+ readonly kind: "entity";
58
+ readonly source: SourceLocation;
59
+ readonly entityName: string;
60
+ readonly definition: EntityDefinition;
61
+ };
62
+
63
+ export type RelationPattern = {
64
+ readonly kind: "relation";
65
+ readonly source: SourceLocation;
66
+ readonly entityName: string;
67
+ readonly relationName: string;
68
+ readonly definition: RelationDefinition;
69
+ };
70
+
71
+ export type NavPattern = {
72
+ readonly kind: "nav";
73
+ readonly source: SourceLocation;
74
+ readonly definition: NavDefinition;
75
+ };
76
+
77
+ export type WorkspacePattern = {
78
+ readonly kind: "workspace";
79
+ readonly source: SourceLocation;
80
+ readonly definition: WorkspaceDefinition;
81
+ };
82
+
83
+ export type ConfigPattern = {
84
+ readonly kind: "config";
85
+ readonly source: SourceLocation;
86
+ readonly keys: Readonly<Record<string, ConfigKeyDefinition<ConfigKeyType>>>;
87
+ };
88
+
89
+ export type TranslationsPattern = {
90
+ readonly kind: "translations";
91
+ readonly source: SourceLocation;
92
+ readonly keys: TranslationKeys;
93
+ };
94
+
95
+ export type RequiresPattern = {
96
+ readonly kind: "requires";
97
+ readonly source: SourceLocation;
98
+ readonly featureNames: readonly string[];
99
+ };
100
+
101
+ export type OptionalRequiresPattern = {
102
+ readonly kind: "optionalRequires";
103
+ readonly source: SourceLocation;
104
+ readonly featureNames: readonly string[];
105
+ };
106
+
107
+ export type SystemScopePattern = {
108
+ readonly kind: "systemScope";
109
+ readonly source: SourceLocation;
110
+ };
111
+
112
+ export type ToggleablePattern = {
113
+ readonly kind: "toggleable";
114
+ readonly source: SourceLocation;
115
+ readonly default: boolean;
116
+ };
117
+
118
+ export type MetricPattern = {
119
+ readonly kind: "metric";
120
+ readonly source: SourceLocation;
121
+ readonly shortName: string;
122
+ readonly options: MetricOptions;
123
+ };
124
+
125
+ export type SecretPattern = {
126
+ readonly kind: "secret";
127
+ readonly source: SourceLocation;
128
+ readonly shortName: string;
129
+ readonly options: SecretOptions;
130
+ };
131
+
132
+ export type ClaimKeyPattern = {
133
+ readonly kind: "claimKey";
134
+ readonly source: SourceLocation;
135
+ readonly shortName: string;
136
+ readonly claimType: ClaimKeyType;
137
+ };
138
+
139
+ export type ReferenceDataPattern = {
140
+ readonly kind: "referenceData";
141
+ readonly source: SourceLocation;
142
+ readonly entityName: string;
143
+ readonly data: ReferenceDataDef["data"];
144
+ readonly upsertKey?: string;
145
+ };
146
+
147
+ export type ReadsConfigPattern = {
148
+ readonly kind: "readsConfig";
149
+ readonly source: SourceLocation;
150
+ readonly qualifiedKeys: readonly string[];
151
+ };
152
+
153
+ export type UseExtensionPattern = {
154
+ readonly kind: "useExtension";
155
+ readonly source: SourceLocation;
156
+ readonly extensionName: string;
157
+ readonly entityName: string;
158
+ readonly options?: Readonly<Record<string, unknown>>;
159
+ };
160
+
161
+ // =============================================================================
162
+ // Mixed patterns — header (name/access/etc.) is declarative, body
163
+ // (handler/hook/apply/transform fn) is opaque. Designer renders the
164
+ // header as a form + the body as a code block. AI patcher generates
165
+ // the header as data + the body as TypeScript source.
166
+ // =============================================================================
167
+
168
+ // Path-keyed map of source locations for opaque sub-properties of an
169
+ // otherwise declarative definition (e.g. screen.rowActions[0].visible
170
+ // is a closure that lives only in monolith bundles). Keys use JSON-path
171
+ // notation so the Designer can show "this prop is custom code" at the
172
+ // exact form-field that maps to the path.
173
+ export type OpaquePropMap = Readonly<Record<string, SourceLocation>>;
174
+
175
+ // Marker emitted in `ScreenPattern.definition` wherever a closure or
176
+ // unresolvable identifier sat in the source. Designer renderers compare
177
+ // against this constant to decide "form vs read-only span" — the actual
178
+ // SourceLocation lives at the matching path in `opaqueProps`.
179
+ export const SCREEN_OPAQUE_MARKER = "$opaque" as const;
180
+ export type ScreenOpaqueMarker = typeof SCREEN_OPAQUE_MARKER;
181
+
182
+ export type ScreenPattern = {
183
+ readonly kind: "screen";
184
+ readonly source: SourceLocation;
185
+ readonly definition: ScreenDefinition;
186
+ // Closure-typed sub-properties (FieldCondition, RowAction.payload,
187
+ // FieldRenderer function form). Keyed by JSON path inside the
188
+ // definition (e.g. "rowActions.0.visible", "fields.email.renderer").
189
+ readonly opaqueProps: OpaquePropMap;
190
+ };
191
+
192
+ export type WriteHandlerPattern = {
193
+ readonly kind: "writeHandler";
194
+ readonly source: SourceLocation;
195
+ readonly handlerName: string;
196
+ // schemaSource: the Zod call as source text (e.g. "z.object({...})").
197
+ // We keep it as an opaque block instead of decoding it back to JSON
198
+ // schema — Zod's full surface is too rich for a faithful round-trip.
199
+ readonly schemaSource: SourceLocation;
200
+ // handlerBody: the closure body as source text. Always opaque — AI
201
+ // generates raw TypeScript, no DSL interpretation.
202
+ readonly handlerBody: SourceLocation;
203
+ readonly access?: AccessRule;
204
+ readonly rateLimit?: RateLimitOption;
205
+ readonly skipTransitionGuard?: boolean;
206
+ };
207
+
208
+ export type QueryHandlerPattern = {
209
+ readonly kind: "queryHandler";
210
+ readonly source: SourceLocation;
211
+ readonly handlerName: string;
212
+ readonly schemaSource: SourceLocation;
213
+ readonly handlerBody: SourceLocation;
214
+ readonly access?: AccessRule;
215
+ readonly rateLimit?: RateLimitOption;
216
+ };
217
+
218
+ export type HookPattern = {
219
+ readonly kind: "hook";
220
+ readonly source: SourceLocation;
221
+ readonly hookType: LifecycleHookType | "validation";
222
+ // r.hook accepts a single target or a list; we keep both shapes so
223
+ // the Designer can render the original author intent.
224
+ readonly target: string | readonly string[];
225
+ readonly fnBody: SourceLocation;
226
+ readonly phase?: HookPhase;
227
+ };
228
+
229
+ export type EntityHookPattern = {
230
+ readonly kind: "entityHook";
231
+ readonly source: SourceLocation;
232
+ readonly hookType: "postSave" | "preDelete" | "postDelete";
233
+ readonly entityName: string;
234
+ readonly fnBody: SourceLocation;
235
+ readonly phase?: HookPhase;
236
+ };
237
+
238
+ export type JobPattern = {
239
+ readonly kind: "job";
240
+ readonly source: SourceLocation;
241
+ readonly jobName: string;
242
+ // JobDefinition without `name` (already on jobName) and without
243
+ // `handler` (kept separately as handlerBody for opacity).
244
+ readonly options: Omit<JobDefinition, "name" | "handler">;
245
+ readonly handlerBody: SourceLocation;
246
+ };
247
+
248
+ export type NotificationPattern = {
249
+ readonly kind: "notification";
250
+ readonly source: SourceLocation;
251
+ readonly notificationName: string;
252
+ readonly trigger: { readonly on: string };
253
+ readonly recipientBody: SourceLocation;
254
+ readonly dataBody: SourceLocation;
255
+ // Each template (e.g. "email", "push") carries its own closure source.
256
+ readonly templates?: Readonly<Record<string, SourceLocation>>;
257
+ };
258
+
259
+ export type AuthClaimsPattern = {
260
+ readonly kind: "authClaims";
261
+ readonly source: SourceLocation;
262
+ readonly fnBody: SourceLocation;
263
+ };
264
+
265
+ export type HttpRoutePattern = {
266
+ readonly kind: "httpRoute";
267
+ readonly source: SourceLocation;
268
+ readonly method: HttpRouteMethod;
269
+ readonly path: string;
270
+ readonly anonymous?: boolean;
271
+ readonly handlerBody: SourceLocation;
272
+ };
273
+
274
+ export type ProjectionPattern = {
275
+ readonly kind: "projection";
276
+ readonly source: SourceLocation;
277
+ readonly name: string;
278
+ // Entity name(s) whose events feed this projection. Disambiguated
279
+ // from `source: SourceLocation` by the explicit `Entity` suffix.
280
+ readonly sourceEntity: string | readonly string[];
281
+ // Map event-type → SourceLocation of the apply closure.
282
+ readonly applyBodies: Readonly<Record<string, SourceLocation>>;
283
+ };
284
+
285
+ export type MultiStreamProjectionPattern = {
286
+ readonly kind: "multiStreamProjection";
287
+ readonly source: SourceLocation;
288
+ readonly name: string;
289
+ readonly applyBodies: Readonly<Record<string, SourceLocation>>;
290
+ readonly errorMode?: MspErrorMode;
291
+ readonly runIn?: RunIn;
292
+ readonly delivery?: "shared" | "per-instance";
293
+ };
294
+
295
+ export type DefineEventPattern = {
296
+ readonly kind: "defineEvent";
297
+ readonly source: SourceLocation;
298
+ readonly eventName: string;
299
+ readonly schemaSource: SourceLocation;
300
+ readonly version?: number;
301
+ };
302
+
303
+ export type EventMigrationPattern = {
304
+ readonly kind: "eventMigration";
305
+ readonly source: SourceLocation;
306
+ readonly eventName: string;
307
+ readonly fromVersion: number;
308
+ readonly toVersion: number;
309
+ readonly transformBody: SourceLocation;
310
+ };
311
+
312
+ export type ExtendsRegistrarPattern = {
313
+ readonly kind: "extendsRegistrar";
314
+ readonly source: SourceLocation;
315
+ readonly extensionName: string;
316
+ // Meta-programming surface — kept fully opaque in the MVP. The
317
+ // Designer shows "Custom Registrar Extension"; AI leaves it alone.
318
+ readonly defBody: SourceLocation;
319
+ };
320
+
321
+ // =============================================================================
322
+ // Catch-all — r.* calls the visitor doesn't recognise. Designer renders
323
+ // "unknown call (cannot edit)", AI patcher leaves them unchanged. When
324
+ // an UnknownPattern shows up in the wild it's a signal that a new r.*
325
+ // API exists and needs its own pattern type here.
326
+ // =============================================================================
327
+
328
+ export type UnknownPattern = {
329
+ readonly kind: "unknown";
330
+ readonly source: SourceLocation;
331
+ readonly methodName: string;
332
+ };
333
+
334
+ // =============================================================================
335
+ // Discriminated union — visitors return FeaturePattern[]; consumers
336
+ // switch on `kind`.
337
+ // =============================================================================
338
+
339
+ export type FeaturePattern =
340
+ // Static
341
+ | EntityPattern
342
+ | RelationPattern
343
+ | NavPattern
344
+ | WorkspacePattern
345
+ | ConfigPattern
346
+ | TranslationsPattern
347
+ | RequiresPattern
348
+ | OptionalRequiresPattern
349
+ | SystemScopePattern
350
+ | ToggleablePattern
351
+ | MetricPattern
352
+ | SecretPattern
353
+ | ClaimKeyPattern
354
+ | ReferenceDataPattern
355
+ | ReadsConfigPattern
356
+ | UseExtensionPattern
357
+ // Mixed
358
+ | ScreenPattern
359
+ | WriteHandlerPattern
360
+ | QueryHandlerPattern
361
+ | HookPattern
362
+ | EntityHookPattern
363
+ | JobPattern
364
+ | NotificationPattern
365
+ | AuthClaimsPattern
366
+ | HttpRoutePattern
367
+ | ProjectionPattern
368
+ | MultiStreamProjectionPattern
369
+ | DefineEventPattern
370
+ | EventMigrationPattern
371
+ | ExtendsRegistrarPattern
372
+ // Catch-all
373
+ | UnknownPattern;
374
+
375
+ // Convenience: the literal union of all kinds, useful for Designer
376
+ // switches that exhaustively cover every pattern.
377
+ export type FeaturePatternKind = FeaturePattern["kind"];
378
+
379
+ // =============================================================================
380
+ // Editability classification — Designer UI uses this to decide whether
381
+ // to render a pattern as a form (editable) or a read-only code block
382
+ // (opaque). The AI patcher uses the same signal to decide JSON-patch
383
+ // vs TS-source-replace.
384
+ // =============================================================================
385
+
386
+ export type Editability =
387
+ | "static" // Fully declarative — forms only, no code slot.
388
+ | "mixed" // Header declarative + body as TS source block.
389
+ | "opaque"; // Whole pattern is TS code, no form surface.
390
+
391
+ export function getEditability(pattern: FeaturePattern): Editability {
392
+ switch (pattern.kind) {
393
+ case "entity":
394
+ case "relation":
395
+ case "nav":
396
+ case "workspace":
397
+ case "config":
398
+ case "translations":
399
+ case "requires":
400
+ case "optionalRequires":
401
+ case "systemScope":
402
+ case "toggleable":
403
+ case "metric":
404
+ case "secret":
405
+ case "claimKey":
406
+ case "referenceData":
407
+ case "readsConfig":
408
+ case "useExtension":
409
+ return "static";
410
+ case "screen":
411
+ case "writeHandler":
412
+ case "queryHandler":
413
+ case "hook":
414
+ case "entityHook":
415
+ case "job":
416
+ case "notification":
417
+ case "httpRoute":
418
+ case "projection":
419
+ case "multiStreamProjection":
420
+ case "defineEvent":
421
+ case "eventMigration":
422
+ return "mixed";
423
+ case "authClaims":
424
+ case "extendsRegistrar":
425
+ case "unknown":
426
+ return "opaque";
427
+ default: {
428
+ // Exhaustiveness guard — adding a new pattern kind without
429
+ // updating this switch produces a compile error here.
430
+ const _exhaustive: never = pattern;
431
+ return _exhaustive;
432
+ }
433
+ }
434
+ }