@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,306 @@
1
+ import type { ZodType } from "zod";
2
+ import type { DbConnection } from "../../db/connection";
3
+ import type { TenantDb } from "../../db/tenant-db";
4
+ import type { ConcurrencyMode, ConfigScope } from "../constants";
5
+ import type { FieldDefinition } from "./fields";
6
+ import type { AppContext } from "./handlers";
7
+ import type {
8
+ PostDeleteHookFn,
9
+ PostSaveHookFn,
10
+ PreDeleteHookFn,
11
+ PreQueryHookFn,
12
+ PreSaveHookFn,
13
+ } from "./hooks";
14
+ import type { TenantId } from "./identifiers";
15
+
16
+ // --- Config ---
17
+
18
+ export type ConfigKeyAccess = {
19
+ readonly read: readonly string[];
20
+ readonly write: readonly string[];
21
+ };
22
+
23
+ export type ConfigKeyType = "text" | "number" | "boolean" | "select";
24
+
25
+ export type ConfigValue<T extends ConfigKeyType> = T extends "number"
26
+ ? number
27
+ : T extends "boolean"
28
+ ? boolean
29
+ : T extends "text" | "select"
30
+ ? string
31
+ : never;
32
+
33
+ // Bounds for numeric config keys. Enforced as hard-reject (not silent-clamp)
34
+ // in set.write.ts: a tenant-admin setting a value outside [min, max] gets a
35
+ // 400 "out_of_bounds" — silent clamping would be a UX trap ("I entered 9999,
36
+ // it saved as 1000, why?"). Per-Request helpers MAY clamp — that's a
37
+ // different call site where the caller often can't control the exact value.
38
+ // Only meaningful for type="number"; boot-validator rejects on other types.
39
+ export type ConfigBounds = {
40
+ readonly min?: number;
41
+ readonly max?: number;
42
+ };
43
+
44
+ // Ctx a `computed` key-resolver gets. Mirrors what the resolver itself has:
45
+ // tenantId + userId for scope-aware lookups, db for ad-hoc queries (e.g.
46
+ // "read the current subscription plan for this tenant"). Intentionally
47
+ // narrow — giving it the full AppContext would leak deps like `redis`
48
+ // into declaration-level code that shouldn't need them.
49
+ export type ConfigComputedContext = {
50
+ readonly tenantId: TenantId;
51
+ readonly userId: string;
52
+ readonly db: DbConnection | TenantDb;
53
+ };
54
+
55
+ // Computed-value resolver. Called when no scope-row AND no app-boot-override
56
+ // exist for this key — sits one step above keyDef.default.
57
+ //
58
+ // Use-case: plan-based limits ("Pro tenants get maxUploadSizeMB=100"). The
59
+ // feature declares *how* to compute the value, the handler stays neutral:
60
+ // const max = await ctx.config(handle); // resolver calls computed
61
+ //
62
+ // Row wins over computed: a tenant-admin that sets a specific value
63
+ // overrides the plan-default. If you want "plan is a hard policy", reject
64
+ // set on the handler-side — don't try to invert the cascade.
65
+ export type ConfigComputedFn<T extends ConfigKeyType = ConfigKeyType> = (
66
+ ctx: ConfigComputedContext,
67
+ ) => Promise<ConfigValue<T>>;
68
+
69
+ export type ConfigKeyDefinition<T extends ConfigKeyType = ConfigKeyType> = {
70
+ readonly type: T;
71
+ readonly default?: ConfigValue<T>;
72
+ readonly scope: ConfigScope;
73
+ readonly access: ConfigKeyAccess;
74
+ readonly encrypted?: boolean;
75
+ readonly options?: readonly string[];
76
+ readonly bounds?: ConfigBounds;
77
+ readonly computed?: ConfigComputedFn<T>;
78
+ // Per-Request opt-in. Default false — resolveConfigOrParam wirft für
79
+ // Keys ohne diese Marke, auch wenn der Caller paramValue übergibt. Das
80
+ // zwingt Feature-Devs zur expliziten Entscheidung "dieser Key darf pro
81
+ // Request überschrieben werden" — statt versehentlich zu erlauben dass
82
+ // ein Query-Param jede beliebige Tenant-Config umgeht.
83
+ //
84
+ // Nicht kombinierbar mit type="text" (Boot-Reject) — Text-Werte sind
85
+ // immer gesperrt wegen XSS/SQL/Shell-Risiko, selbst mit Opt-in.
86
+ // Nicht kombinierbar mit encrypted (Boot-Reject) — encrypted Keys
87
+ // werden nicht transient aus Query-Strings heraus gelesen.
88
+ readonly allowPerRequest?: boolean;
89
+ };
90
+
91
+ export type ConfigDefinition = {
92
+ readonly keys: Readonly<Record<string, ConfigKeyDefinition>>;
93
+ };
94
+
95
+ export type ConfigKeyHandle<T extends ConfigKeyType = ConfigKeyType> = {
96
+ readonly name: string;
97
+ readonly type: T;
98
+ };
99
+
100
+ export type ConfigAccessor = {
101
+ (qualifiedKey: string): Promise<string | number | boolean | undefined>;
102
+ <T extends ConfigKeyType>(handle: ConfigKeyHandle<T>): Promise<ConfigValue<T> | undefined>;
103
+ };
104
+
105
+ export type ConfigAccessorFactory = (deps: {
106
+ readonly user: { readonly id: string; readonly tenantId: TenantId };
107
+ readonly db: DbConnection | TenantDb;
108
+ }) => ConfigAccessor;
109
+
110
+ // Row shape returned by ConfigResolver.getAll — just enough for the
111
+ // values.query handler to project. Stored as `unknown` value because the
112
+ // resolver hands raw JSON strings; deserialization is the resolver's job.
113
+ //
114
+ // Post-ES the config_values projection PK is a UUID (event-store aggregate
115
+ // id) and tenantId is non-null (system-scope rows carry SYSTEM_TENANT_ID).
116
+ // The shape stays backward-compatible for read callers: they only touch
117
+ // `value` and `key`.
118
+ export type ConfigStoredRow = {
119
+ readonly id: string;
120
+ readonly key: string;
121
+ readonly value: string | null;
122
+ readonly tenantId: string;
123
+ readonly userId: string | null;
124
+ };
125
+
126
+ // Which layer of the cascade actually produced a value. Emitted only by
127
+ // `getWithSource` — regular `get` hides this to keep the hot-path simple.
128
+ // Use-case: Ops-debugging ("warum ist mein Wert 50 und nicht 100?") without
129
+ // poking through six scope-row-lookups by hand.
130
+ export type ConfigValueSource =
131
+ | "user-row" // user-scoped row (only for scope:user keys)
132
+ | "tenant-row" // tenant-scoped row
133
+ | "system-row" // system-scoped row (tenantId = SYSTEM_TENANT_ID, userId = null)
134
+ | "app-override" // from createConfigResolver({ appOverrides })
135
+ | "computed" // computed resolver in the key declaration
136
+ | "default" // keyDef.default
137
+ | "missing"; // no row, no override, no computed, no default
138
+
139
+ export type ConfigValueWithSource = {
140
+ readonly value: string | number | boolean | undefined;
141
+ readonly source: ConfigValueSource;
142
+ };
143
+
144
+ // Minimal contract handlers (set/reset/values.query) call against the
145
+ // resolver. Lives in the framework so SharedContextFields.configResolver
146
+ // can drop the `unknown` cast — the concrete implementation in
147
+ // bundled-features/config/resolver.ts implements this shape.
148
+ // Read-only contract: writes flow through the config feature's
149
+ // write-handlers (set / reset), which append events + let the event-store-
150
+ // executor materialise the projection. The resolver is purely a read
151
+ // cascade (user → tenant → system → app-override → computed → default).
152
+ export type ConfigResolver = {
153
+ get(
154
+ qualifiedKey: string,
155
+ keyDef: ConfigKeyDefinition,
156
+ tenantId: TenantId,
157
+ userId: string,
158
+ db: DbConnection | TenantDb,
159
+ ): Promise<string | number | boolean | undefined>;
160
+
161
+ // Same cascade as get() but also reports which layer produced the value.
162
+ // Intended for Ops/Support tooling — never call this from hot-path
163
+ // handlers (it builds the source tag even when the caller doesn't look
164
+ // at it). Row-lookup count is identical to get(); the extra work is a
165
+ // small branch tag.
166
+ getWithSource(
167
+ qualifiedKey: string,
168
+ keyDef: ConfigKeyDefinition,
169
+ tenantId: TenantId,
170
+ userId: string,
171
+ db: DbConnection | TenantDb,
172
+ ): Promise<ConfigValueWithSource>;
173
+
174
+ getAll(
175
+ tenantId: TenantId,
176
+ userId: string,
177
+ db: DbConnection | TenantDb,
178
+ ): Promise<ReadonlyMap<string, ConfigStoredRow>>;
179
+ };
180
+
181
+ // --- Process-Placement (runIn) ---
182
+
183
+ // Which deploy-shape a consumer / job is allowed to run in. Filtered at
184
+ // entrypoint boot: createApiEntrypoint picks up "api"|"both", createWorker
185
+ // Entrypoint picks up "worker"|"both", createAllInOneEntrypoint takes
186
+ // everything. Default is "worker" for every async consumer/job — that's the
187
+ // sensible prod default (API instances stay request-focused, heavy async
188
+ // work lives on the worker fleet). Opt into "api" only for latency-
189
+ // sensitive or in-memory-stateful consumers (e.g. later: SSE per-instance
190
+ // push in Welle 2.7).
191
+ //
192
+ // Feature-hooks (r.hook preSave/postSave/…) intentionally have no runIn —
193
+ // they run in-TX in whatever process handles the command. Splitting them
194
+ // would break atomicity. If you want async work, use r.job or
195
+ // r.multiStreamProjection.
196
+ export type RunIn = "api" | "worker" | "both";
197
+
198
+ // Jobs are queue-delivered via BullMQ with one dedicated queue per lane
199
+ // ("kumiko-jobs-api" vs "kumiko-jobs-worker") and one dedicated event-
200
+ // enqueuer consumer per lane. "both" would mean "dispatch to both queues",
201
+ // which over-delivers the job; the Marten-style cursor/queue fan-out is not
202
+ // free. Restrict at the type level so the boot-validator never has to
203
+ // report it.
204
+ export type JobRunIn = Exclude<RunIn, "both">;
205
+
206
+ // --- Jobs ---
207
+
208
+ export type JobHandlerFn = (payload: Record<string, unknown>, context: AppContext) => Promise<void>;
209
+
210
+ export type JobTrigger =
211
+ // `on` akzeptiert ein einzelnes Handler-Ref ODER eine Liste. Multi-
212
+ // Trigger-Form ist DRY für Fanout-Patterns: ein Job-Body, mehrere
213
+ // Trigger (z.B. webhook-fanout: incident.open / incident.update /
214
+ // maintenance.start) statt N r.job-Calls mit demselben Handler-Body.
215
+ // Im Handler-payload landet `_triggerName: string` damit der Code
216
+ // weiß, welcher Trigger gefeuert hat.
217
+ | { readonly on: import("./handlers").NameOrRef | readonly import("./handlers").NameOrRef[] }
218
+ | { readonly cron: string }
219
+ | { readonly manual: true };
220
+
221
+ export type JobDefinition = {
222
+ readonly name: string;
223
+ readonly handler: JobHandlerFn;
224
+ readonly trigger: JobTrigger;
225
+ readonly concurrency?: ConcurrencyMode | undefined;
226
+ readonly maxPerTenant?: number | undefined;
227
+ readonly debounceMs?: number | undefined;
228
+ readonly retries?: number | undefined;
229
+ readonly backoff?: "fixed" | "exponential" | undefined;
230
+ readonly timeout?: number | undefined;
231
+ readonly schema?: ZodType | undefined;
232
+ readonly runOnBoot?: boolean | undefined;
233
+ readonly perTenant?: boolean | undefined;
234
+ // Which deploy-lane runs this job. Default "worker". Set "api" only for
235
+ // short CPU-light handlers (token cleanup, in-process cache warmup) that
236
+ // don't justify a separate worker container — long/CPU-heavy jobs on the
237
+ // API lane will starve request handlers.
238
+ readonly runIn?: JobRunIn | undefined;
239
+ };
240
+
241
+ // --- Notifications ---
242
+
243
+ export type NotificationRecipientFn = (
244
+ result: import("./hooks").SaveContext,
245
+ ) => string | readonly string[] | { readonly tenant: string } | null;
246
+
247
+ export type NotificationDataFn = (result: import("./hooks").SaveContext) => Record<string, unknown>;
248
+
249
+ // Per-channel template function: transforms raw notification data into channel-specific format.
250
+ // Example: inApp gets { title, body }, email gets { subject, sections }.
251
+ export type NotificationTemplateFn = (data: Record<string, unknown>) => Record<string, unknown>;
252
+
253
+ export type NotificationDefinition = {
254
+ readonly name: string;
255
+ readonly trigger: { readonly on: string };
256
+ readonly recipient: NotificationRecipientFn;
257
+ readonly data: NotificationDataFn;
258
+ readonly templates: Readonly<Record<string, NotificationTemplateFn>> | undefined;
259
+ };
260
+
261
+ // --- Translations ---
262
+
263
+ export type TranslationEntry = Readonly<Record<string, string>>;
264
+ export type TranslationKeys = Readonly<Record<string, TranslationEntry>>;
265
+
266
+ export type TranslationsDef = {
267
+ readonly keys: TranslationKeys;
268
+ };
269
+
270
+ // --- Registrar Extensions ---
271
+
272
+ export type RegistrarExtensionHooks = {
273
+ readonly preSave?: PreSaveHookFn;
274
+ readonly postSave?: PostSaveHookFn;
275
+ readonly preDelete?: PreDeleteHookFn;
276
+ readonly postDelete?: PostDeleteHookFn;
277
+ readonly preQuery?: PreQueryHookFn;
278
+ };
279
+
280
+ export type UiExtensionDef = {
281
+ readonly editSection?: string;
282
+ readonly listColumns?: string;
283
+ readonly filters?: string;
284
+ };
285
+
286
+ export type RegistrarExtensionDef = {
287
+ readonly onRegister?: (entityName: string, options?: Record<string, unknown>) => void;
288
+ readonly extendSchema?: (entityName: string) => Record<string, FieldDefinition>;
289
+ readonly hooks?: RegistrarExtensionHooks;
290
+ readonly extendSearch?: (entityName: string) => Record<string, unknown>;
291
+ readonly uiExtension?: UiExtensionDef;
292
+ };
293
+
294
+ export type RegistrarExtensionRegistration = {
295
+ readonly extensionName: string;
296
+ readonly entityName: string;
297
+ readonly options?: Record<string, unknown> | undefined;
298
+ };
299
+
300
+ // --- Reference Data ---
301
+
302
+ export type ReferenceDataDef = {
303
+ readonly entityName: string;
304
+ readonly data: readonly Record<string, unknown>[];
305
+ readonly upsertKey?: string | undefined;
306
+ };
@@ -0,0 +1,37 @@
1
+ // Cross-Feature Compile-Time-Type-Map.
2
+ //
3
+ // Zweck: ctx.appendEvent / ctx.queryProjection / dispatcher.write gegen ein
4
+ // statisch bekanntes Schema-Bild prüfen, statt erst zur Boot- oder Runtime
5
+ // (zod-validate) zu scheitern. Designer/AI-Layer profitiert dadurch sofort:
6
+ // Autocomplete kennt alle Event-Typen aller geladenen Features, payload-
7
+ // Shape-Mismatches werden im Editor angezeigt, nicht erst beim Boot.
8
+ //
9
+ // Befüllung erfolgt per Feature über `declare module "@cosmicdrift/kumiko-framework/engine"`
10
+ // — entweder hand-geschrieben (für stabile Frameworks-Internals) oder vom
11
+ // Codegen-Skript erzeugt (für apps/bundled-features). Empty defaults sind
12
+ // kein Bug: ein Feature ohne Augmentation ist runtime-pluggable und nutzt
13
+ // die Fallback-Overload mit `unknown` payload.
14
+ //
15
+ // Pattern für hand-geschriebene Augmentation am File-Top:
16
+ //
17
+ // declare module "@cosmicdrift/kumiko-framework/engine" {
18
+ // interface KumikoEventTypeMap {
19
+ // "users:user.created": z.infer<typeof userCreatedSchema>;
20
+ // }
21
+ // }
22
+
23
+ // MUST be `interface` (not `type`): only interfaces support TS declaration-
24
+ // merging. Apps/features extend these via `declare module "@cosmicdrift/kumiko-framework/engine"`
25
+ // blocks. A `type X = {}` alias would silently break that augmentation channel.
26
+
27
+ // biome-ignore lint/suspicious/noEmptyInterface: declaration-merging marker — augmented per feature
28
+ export interface KumikoEventTypeMap {}
29
+
30
+ // biome-ignore lint/suspicious/noEmptyInterface: declaration-merging marker
31
+ export interface KumikoEntityTypeMap {}
32
+
33
+ // biome-ignore lint/suspicious/noEmptyInterface: declaration-merging marker
34
+ export interface KumikoHandlerPayloadMap {}
35
+
36
+ // biome-ignore lint/suspicious/noEmptyInterface: declaration-merging marker
37
+ export interface KumikoHandlerResultMap {}