@cosmicdrift/kumiko-framework 1.0.0 → 2.0.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 (424) hide show
  1. package/README.md +9 -38
  2. package/package.json +21 -2
  3. package/src/__tests__/anonymous-access.integration.test.ts +185 -0
  4. package/src/__tests__/consumer-cli.integration.test.ts +172 -0
  5. package/src/__tests__/entity-permalink-open.integration.test.ts +94 -0
  6. package/src/__tests__/full-stack.integration.test.ts +1 -1
  7. package/src/__tests__/schema-cli-temporal-polyfill.test.ts +48 -0
  8. package/src/__tests__/schema-cli.integration.test.ts +50 -0
  9. package/src/__tests__/store-table.integration.test.ts +93 -0
  10. package/src/api/__tests__/api.test.ts +373 -0
  11. package/src/api/__tests__/auth-middleware-anonymous-access-boot.test.ts +40 -0
  12. package/src/api/__tests__/auth-routes-cookie.test.ts +17 -1
  13. package/src/api/__tests__/auth-routes-invalid-body-invite.test.ts +253 -0
  14. package/src/api/__tests__/auth-routes-mfa-preauth-confirm.test.ts +222 -0
  15. package/src/api/__tests__/auth-routes-mfa-preauth-enable-start.test.ts +249 -0
  16. package/src/api/__tests__/auth-routes-mfa-verify.test.ts +202 -0
  17. package/src/api/__tests__/auth-routes-trusted-proxy.test.ts +135 -0
  18. package/src/api/__tests__/batch.integration.test.ts +101 -11
  19. package/src/api/__tests__/csrf-constants-sync.test.ts +20 -0
  20. package/src/api/__tests__/dispatcher-live.integration.test.ts +74 -0
  21. package/src/api/__tests__/jwt.test.ts +200 -1
  22. package/src/api/__tests__/login-rate-limiter-sweep.test.ts +50 -0
  23. package/src/api/__tests__/pat-scope.test.ts +36 -0
  24. package/src/api/__tests__/pii-leak-guard.integration.test.ts +103 -0
  25. package/src/api/__tests__/redis-login-rate-limiter.integration.test.ts +138 -0
  26. package/src/api/__tests__/request-id-middleware.test.ts +51 -0
  27. package/src/api/__tests__/server-boot-guards.test.ts +71 -0
  28. package/src/api/__tests__/server-jwt-ttl.test.ts +58 -0
  29. package/src/api/__tests__/sse-broker.test.ts +57 -0
  30. package/src/api/__tests__/sse-route.test.ts +4 -0
  31. package/src/api/api-constants.ts +11 -0
  32. package/src/api/auth-middleware.ts +248 -40
  33. package/src/api/auth-routes.ts +576 -95
  34. package/src/api/index.ts +13 -4
  35. package/src/api/jwt.ts +170 -11
  36. package/src/api/pat-scope.ts +14 -0
  37. package/src/api/pii-leak-guard.ts +47 -0
  38. package/src/api/request-context.ts +3 -0
  39. package/src/api/request-id-middleware.ts +2 -0
  40. package/src/api/routes.ts +169 -2
  41. package/src/api/server.ts +112 -16
  42. package/src/api/sse-broker.ts +39 -0
  43. package/src/bun-db/__tests__/PATTERN.md +0 -1
  44. package/src/bun-db/__tests__/coerce-row-temporal.test.ts +41 -0
  45. package/src/bun-db/__tests__/select-many-retry.test.ts +79 -0
  46. package/src/bun-db/__tests__/write-brand.test.ts +21 -0
  47. package/src/bun-db/connection.ts +3 -3
  48. package/src/bun-db/index.ts +2 -0
  49. package/src/bun-db/query.ts +105 -32
  50. package/src/consumer-cli.ts +134 -0
  51. package/src/crypto/__tests__/blind-index.test.ts +130 -0
  52. package/src/crypto/__tests__/event-pii.test.ts +161 -0
  53. package/src/crypto/__tests__/kek-rotation.integration.test.ts +180 -0
  54. package/src/crypto/__tests__/kms-adapter-contract.ts +134 -0
  55. package/src/crypto/__tests__/kms-adapter.contract.test.ts +4 -0
  56. package/src/crypto/__tests__/pg-kms-adapter.integration.test.ts +117 -0
  57. package/src/crypto/__tests__/pii-field-encryption.test.ts +376 -0
  58. package/src/crypto/__tests__/request-kms-cache.test.ts +74 -0
  59. package/src/crypto/__tests__/subject-resolver.test.ts +108 -0
  60. package/src/crypto/blind-index.ts +118 -0
  61. package/src/crypto/event-pii.ts +70 -0
  62. package/src/crypto/in-memory-kms-adapter.ts +50 -0
  63. package/src/crypto/index.ts +67 -0
  64. package/src/crypto/kms-adapter.ts +2 -0
  65. package/src/crypto/pg-kms-adapter.ts +295 -0
  66. package/src/crypto/pii-field-encryption.ts +248 -0
  67. package/src/crypto/request-kms-cache.ts +38 -0
  68. package/src/crypto/subject-resolver.ts +91 -0
  69. package/src/db/__tests__/assert-no-unreachable-live-rows.integration.test.ts +191 -0
  70. package/src/db/__tests__/blind-index.integration.test.ts +248 -0
  71. package/src/db/__tests__/build-filter-where.test.ts +34 -0
  72. package/src/db/__tests__/collect-table-metas.test.ts +10 -10
  73. package/src/db/__tests__/config-seed.integration.test.ts +13 -5
  74. package/src/db/__tests__/dialect-instant.test.ts +1 -4
  75. package/src/db/__tests__/entity-field-encryption.test.ts +7 -7
  76. package/src/db/__tests__/entity-table-meta-source.test.ts +50 -0
  77. package/src/db/__tests__/event-store-executor-context.pii-roundtrip.test.ts +67 -0
  78. package/src/db/__tests__/event-store-executor-write-verbs.integration.test.ts +402 -0
  79. package/src/db/__tests__/event-store-executor.integration.test.ts +299 -29
  80. package/src/db/__tests__/feature-table-sources.test.ts +34 -0
  81. package/src/db/__tests__/implicit-projection-equivalence.integration.test.ts +118 -39
  82. package/src/db/__tests__/instant-to-driver-temporal.test.ts +21 -0
  83. package/src/db/__tests__/located-timestamp.test.ts +19 -0
  84. package/src/db/__tests__/migrate-generator.test.ts +21 -0
  85. package/src/db/__tests__/migrate-runner.test.ts +61 -0
  86. package/src/db/__tests__/number-field-fractional.integration.test.ts +58 -0
  87. package/src/db/__tests__/rebuild-marker.test.ts +13 -3
  88. package/src/db/__tests__/replay-migration-sql.test.ts +384 -0
  89. package/src/db/__tests__/schema-inspection.test.ts +7 -0
  90. package/src/db/__tests__/schema-migration.integration.test.ts +1 -1
  91. package/src/db/__tests__/table-builder-meta-lockstep.test.ts +39 -0
  92. package/src/db/__tests__/tenant-db-where-merge.test.ts +49 -3
  93. package/src/db/__tests__/tenant-db.integration.test.ts +6 -2
  94. package/src/db/api.ts +2 -2
  95. package/src/db/apply-entity-event.ts +18 -14
  96. package/src/db/blind-index-cleanup.ts +55 -0
  97. package/src/db/bun-provider.ts +2 -2
  98. package/src/db/collect-table-metas.ts +6 -7
  99. package/src/db/config-seed.ts +9 -9
  100. package/src/db/connection.ts +7 -12
  101. package/src/db/cursor.ts +1 -18
  102. package/src/db/dialect.ts +20 -26
  103. package/src/db/entity-field-encryption.ts +81 -24
  104. package/src/db/entity-table-meta-types.ts +2 -0
  105. package/src/db/entity-table-meta.ts +63 -90
  106. package/src/db/event-store-executor-context.ts +404 -0
  107. package/src/db/event-store-executor-read.ts +275 -0
  108. package/src/db/event-store-executor-write.ts +644 -0
  109. package/src/db/event-store-executor.ts +28 -1155
  110. package/src/db/feature-table-sources.ts +6 -5
  111. package/src/db/index.ts +20 -3
  112. package/src/db/located-timestamp.ts +4 -0
  113. package/src/db/migrate-generator.ts +39 -6
  114. package/src/db/migrate-runner.ts +107 -11
  115. package/src/db/pg-error.ts +9 -1
  116. package/src/db/postgres-provider.ts +2 -2
  117. package/src/db/queries/__tests__/event-store-idempotency-index.integration.test.ts +80 -0
  118. package/src/db/queries/backfill-pii.ts +277 -0
  119. package/src/db/queries/ddl.ts +45 -0
  120. package/src/db/queries/event-consumer.ts +35 -2
  121. package/src/db/queries/event-store.ts +126 -19
  122. package/src/db/queries/projection-rebuild.ts +22 -8
  123. package/src/db/queries/shadow-swap.ts +183 -0
  124. package/src/db/queries/test-stack.ts +4 -30
  125. package/src/db/query-api.ts +1 -0
  126. package/src/db/query.ts +1 -0
  127. package/src/db/rebuild-marker.ts +18 -2
  128. package/src/db/reference-data.ts +2 -3
  129. package/src/db/replay-migration-sql.ts +257 -0
  130. package/src/db/schema-inspection.ts +1 -1
  131. package/src/db/table-builder.ts +102 -71
  132. package/src/db/tenant-db.ts +15 -53
  133. package/src/engine/__tests__/boot-validator-action-wiring.test.ts +242 -0
  134. package/src/engine/__tests__/boot-validator-boot-check.test.ts +99 -0
  135. package/src/engine/__tests__/boot-validator-dashboard.test.ts +237 -0
  136. package/src/engine/__tests__/boot-validator-entity-list.test.ts +104 -0
  137. package/src/engine/__tests__/boot-validator-gdpr-storage.test.ts +7 -69
  138. package/src/engine/__tests__/boot-validator-i18n-keys.test.ts +26 -5
  139. package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +3 -19
  140. package/src/engine/__tests__/boot-validator-pii-retention.test.ts +246 -4
  141. package/src/engine/__tests__/boot-validator.test.ts +219 -15
  142. package/src/engine/__tests__/build-app-schema.test.ts +82 -0
  143. package/src/engine/__tests__/build-config-feature-schema.test.ts +125 -0
  144. package/src/engine/__tests__/build-target.test.ts +3 -11
  145. package/src/engine/__tests__/codemod-pipeline.test.ts +152 -21
  146. package/src/engine/__tests__/config-helpers.test.ts +16 -0
  147. package/src/engine/__tests__/define-feature-entity-mapping.test.ts +6 -0
  148. package/src/engine/__tests__/define-roles.test.ts +21 -0
  149. package/src/engine/__tests__/engine.test.ts +163 -1
  150. package/src/engine/__tests__/entity-handlers.test.ts +80 -0
  151. package/src/engine/__tests__/event-migration-declarative.test.ts +65 -0
  152. package/src/engine/__tests__/event-type-map-augmentation.test.ts +24 -0
  153. package/src/engine/__tests__/extend-entity-projection.test.ts +123 -0
  154. package/src/engine/__tests__/factories-time.test.ts +2 -66
  155. package/src/engine/__tests__/feature-crud-shorthand.test.ts +28 -0
  156. package/src/engine/__tests__/feature-manifest.test.ts +31 -1
  157. package/src/engine/__tests__/field-access.test.ts +23 -1
  158. package/src/engine/__tests__/hook-phases.test.ts +5 -5
  159. package/src/engine/__tests__/membership-roles.test.ts +4 -10
  160. package/src/engine/__tests__/nav.test.ts +86 -1
  161. package/src/engine/__tests__/pipeline-engine.test.ts +9 -9
  162. package/src/engine/__tests__/pipeline-handler.integration.test.ts +18 -18
  163. package/src/engine/__tests__/pipeline-observability.integration.test.ts +2 -2
  164. package/src/engine/__tests__/pipeline-performance.integration.test.ts +3 -3
  165. package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +9 -9
  166. package/src/engine/__tests__/post-query-hook.test.ts +7 -7
  167. package/src/engine/__tests__/registrar-object-form.test.ts +141 -0
  168. package/src/engine/__tests__/registry.test.ts +144 -0
  169. package/src/engine/__tests__/schema-builder.test.ts +18 -0
  170. package/src/engine/__tests__/screen.test.ts +147 -1
  171. package/src/engine/__tests__/soft-delete-cleanup.test.ts +3 -0
  172. package/src/engine/__tests__/store-table.test.ts +229 -0
  173. package/src/engine/__tests__/tier-resolver-extension.test.ts +19 -1
  174. package/src/engine/__tests__/{visual-tree-patterns.test.ts → tree-actions-patterns.test.ts} +7 -95
  175. package/src/engine/__tests__/validate-projection-allowlist.test.ts +15 -15
  176. package/src/engine/boot-validator/__tests__/config-deps.test.ts +92 -0
  177. package/src/engine/boot-validator/action-wiring.ts +149 -0
  178. package/src/engine/boot-validator/boot-check.ts +21 -0
  179. package/src/engine/boot-validator/config-deps.ts +40 -4
  180. package/src/engine/boot-validator/entity-handler.ts +20 -21
  181. package/src/engine/boot-validator/entity-list-screens.ts +88 -0
  182. package/src/engine/boot-validator/gdpr-storage.ts +0 -20
  183. package/src/engine/boot-validator/i18n-keys.ts +58 -4
  184. package/src/engine/boot-validator/index.ts +33 -12
  185. package/src/engine/boot-validator/nav.ts +125 -0
  186. package/src/engine/boot-validator/pii-retention.ts +95 -10
  187. package/src/engine/boot-validator/{screens-nav.ts → screens.ts} +214 -191
  188. package/src/engine/boot-validator/workspaces.ts +68 -0
  189. package/src/engine/build-app-schema.ts +16 -0
  190. package/src/engine/build-config-feature-schema.ts +44 -7
  191. package/src/engine/codemod/pipeline-codemod.ts +5 -5
  192. package/src/engine/config-helpers.ts +15 -0
  193. package/src/engine/constants.ts +32 -6
  194. package/src/engine/create-app.ts +11 -0
  195. package/src/engine/define-feature.ts +95 -947
  196. package/src/engine/define-handler.ts +28 -94
  197. package/src/engine/define-workflow.ts +1 -1
  198. package/src/engine/effective-features.ts +12 -2
  199. package/src/engine/entity-handlers.ts +76 -11
  200. package/src/engine/extensions/tenant-data.ts +19 -0
  201. package/src/engine/extensions/user-data.ts +29 -2
  202. package/src/engine/factories.ts +8 -49
  203. package/src/engine/feature-ast/__tests__/canonical-form.test.ts +26 -29
  204. package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/feature.ts +9 -0
  205. package/src/engine/feature-ast/__tests__/fixtures/cross-file-registrar/screens.ts +4 -0
  206. package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +1 -2
  207. package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +18 -8
  208. package/src/engine/feature-ast/__tests__/parse.test.ts +1640 -160
  209. package/src/engine/feature-ast/__tests__/patch.test.ts +206 -12
  210. package/src/engine/feature-ast/__tests__/patcher.test.ts +20 -23
  211. package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +380 -5
  212. package/src/engine/feature-ast/extractors/events.ts +322 -0
  213. package/src/engine/feature-ast/extractors/handlers.ts +234 -0
  214. package/src/engine/feature-ast/extractors/hooks.ts +243 -0
  215. package/src/engine/feature-ast/extractors/index.ts +34 -31
  216. package/src/engine/feature-ast/extractors/jobs-routes.ts +221 -0
  217. package/src/engine/feature-ast/extractors/projections-screens.ts +269 -0
  218. package/src/engine/feature-ast/extractors/round1.ts +3 -3
  219. package/src/engine/feature-ast/extractors/round5.ts +3 -3
  220. package/src/engine/feature-ast/extractors/round6.ts +2 -36
  221. package/src/engine/feature-ast/extractors/shared.ts +64 -6
  222. package/src/engine/feature-ast/index.ts +2 -4
  223. package/src/engine/feature-ast/parse.ts +130 -23
  224. package/src/engine/feature-ast/patch.ts +39 -50
  225. package/src/engine/feature-ast/patcher.ts +37 -38
  226. package/src/engine/feature-ast/patterns.ts +50 -62
  227. package/src/engine/feature-ast/render.ts +67 -44
  228. package/src/engine/feature-builder-state.ts +168 -0
  229. package/src/engine/feature-config-events-jobs.ts +403 -0
  230. package/src/engine/feature-entity-handlers.ts +208 -0
  231. package/src/engine/feature-manifest.ts +2 -1
  232. package/src/engine/feature-ui-extensions.ts +500 -0
  233. package/src/engine/field-access.ts +13 -2
  234. package/src/engine/field-helpers.ts +31 -0
  235. package/src/engine/handler-helpers.ts +26 -0
  236. package/src/engine/hook-helpers.ts +16 -0
  237. package/src/engine/index.ts +23 -7
  238. package/src/engine/membership-roles.ts +13 -0
  239. package/src/engine/object-form.ts +27 -0
  240. package/src/engine/ownership.ts +26 -79
  241. package/src/engine/pattern-library/__tests__/library.test.ts +7 -20
  242. package/src/engine/pattern-library/library.ts +44 -1152
  243. package/src/engine/pattern-library/mixed-schemas.ts +450 -0
  244. package/src/engine/pattern-library/opaque-schemas.ts +124 -0
  245. package/src/engine/pattern-library/shared-fields.ts +75 -0
  246. package/src/engine/pattern-library/static-schemas.ts +456 -0
  247. package/src/engine/pipeline.ts +6 -11
  248. package/src/engine/registry-facade.ts +362 -0
  249. package/src/engine/registry-ingest.ts +478 -0
  250. package/src/engine/registry-state.ts +388 -0
  251. package/src/engine/registry-validate.ts +642 -0
  252. package/src/engine/registry.ts +78 -1658
  253. package/src/engine/run-pipeline.ts +1 -1
  254. package/src/engine/schema-builder.ts +1 -0
  255. package/src/engine/screen-helpers.ts +54 -0
  256. package/src/engine/soft-delete-cleanup.ts +6 -2
  257. package/src/engine/steps/__tests__/duration-utils.test.ts +20 -0
  258. package/src/engine/steps/_duration-utils.ts +2 -0
  259. package/src/engine/steps/unsafe-projection-upsert.ts +1 -4
  260. package/src/engine/tier-resolver-extension.ts +3 -2
  261. package/src/engine/types/config.ts +2 -482
  262. package/src/engine/types/define-handler.ts +2 -0
  263. package/src/engine/types/entity-handlers.ts +2 -0
  264. package/src/engine/types/event-type-map.ts +1 -37
  265. package/src/engine/types/feature.ts +2 -972
  266. package/src/engine/types/fields.ts +2 -675
  267. package/src/engine/types/handlers.ts +2 -774
  268. package/src/engine/types/hooks.ts +2 -184
  269. package/src/engine/types/http-route.ts +1 -54
  270. package/src/engine/types/identifiers.ts +1 -47
  271. package/src/engine/types/index.ts +86 -40
  272. package/src/engine/types/nav.ts +2 -63
  273. package/src/engine/types/ownership.ts +2 -0
  274. package/src/engine/types/projection.ts +2 -138
  275. package/src/engine/types/relations.ts +1 -51
  276. package/src/engine/types/screen.ts +2 -574
  277. package/src/engine/types/step.ts +2 -334
  278. package/src/engine/types/target-ref.ts +1 -21
  279. package/src/engine/types/tree-node.ts +1 -132
  280. package/src/engine/types/workspace.ts +2 -49
  281. package/src/engine/validate-projection-allowlist.ts +6 -6
  282. package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.test.ts +120 -1
  283. package/src/entrypoint/index.ts +49 -6
  284. package/src/errors/classes.ts +22 -1
  285. package/src/errors/field-issue.ts +0 -3
  286. package/src/errors/index.ts +1 -1
  287. package/src/errors/write-error-info.ts +10 -22
  288. package/src/es-ops/README.md +1 -1
  289. package/src/es-ops/__tests__/runner.integration.test.ts +74 -0
  290. package/src/es-ops/context.ts +4 -2
  291. package/src/es-ops/types.ts +8 -1
  292. package/src/event-store/__tests__/admin-api.integration.test.ts +27 -1
  293. package/src/event-store/__tests__/backfill-pii.integration.test.ts +279 -0
  294. package/src/event-store/__tests__/event-store.integration.test.ts +201 -0
  295. package/src/event-store/__tests__/row-to-stored-event.test.ts +2 -2
  296. package/src/event-store/__tests__/snapshot.integration.test.ts +86 -0
  297. package/src/event-store/__tests__/unscoped-stream-primitives.guard.test.ts +58 -0
  298. package/src/event-store/__tests__/upcaster.integration.test.ts +77 -45
  299. package/src/event-store/admin-api.ts +11 -4
  300. package/src/event-store/errors.ts +2 -35
  301. package/src/event-store/event-store.ts +64 -78
  302. package/src/event-store/events-schema.ts +11 -13
  303. package/src/event-store/index.ts +18 -3
  304. package/src/event-store/rebuild-dead-letter.ts +111 -0
  305. package/src/event-store/snapshot.ts +63 -40
  306. package/src/event-store/types.ts +2 -0
  307. package/src/files/__tests__/build-storage-key.test.ts +28 -0
  308. package/src/files/__tests__/file-ref-entity.test.ts +8 -0
  309. package/src/files/__tests__/files.integration.test.ts +24 -0
  310. package/src/files/__tests__/in-memory-provider.contract.test.ts +4 -0
  311. package/src/files/__tests__/local-provider.test.ts +31 -0
  312. package/src/files/__tests__/provider-resolver.test.ts +70 -0
  313. package/src/files/__tests__/write-stream.test.ts +13 -0
  314. package/src/files/file-handle.ts +2 -19
  315. package/src/files/file-ref-entity.ts +2 -2
  316. package/src/files/file-routes.ts +13 -0
  317. package/src/files/index.ts +1 -1
  318. package/src/files/local-provider.ts +27 -8
  319. package/src/files/provider-resolver.ts +31 -20
  320. package/src/files/types.ts +13 -55
  321. package/src/i18n/__tests__/required-surface-keys.test.ts +17 -0
  322. package/src/i18n/required-surface-keys.ts +120 -1
  323. package/src/jobs/__tests__/job-queue-depth.integration.test.ts +82 -0
  324. package/src/jobs/__tests__/jobs.integration.test.ts +329 -3
  325. package/src/jobs/job-runner.ts +82 -12
  326. package/src/logging/types.ts +1 -7
  327. package/src/migrations/pending-rebuilds.ts +1 -1
  328. package/src/observability/__tests__/observability.integration.test.ts +4 -1
  329. package/src/observability/__tests__/recording-tracer.test.ts +6 -4
  330. package/src/observability/index.ts +2 -0
  331. package/src/observability/noop-provider.ts +0 -9
  332. package/src/observability/recording-tracer.ts +0 -12
  333. package/src/observability/standard-metrics.ts +64 -2
  334. package/src/observability/types/index.ts +1 -29
  335. package/src/observability/types/metric.ts +1 -56
  336. package/src/observability/types/provider.ts +1 -32
  337. package/src/observability/types/span.ts +1 -64
  338. package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +2 -2
  339. package/src/pipeline/__tests__/dispatcher.test.ts +366 -1
  340. package/src/pipeline/__tests__/event-consumer-state.integration.test.ts +31 -0
  341. package/src/pipeline/__tests__/event-dispatcher-delivery-max-attempts.test.ts +126 -0
  342. package/src/pipeline/__tests__/event-dispatcher-rearm.integration.test.ts +263 -0
  343. package/src/pipeline/__tests__/event-dispatcher.integration.test.ts +10 -0
  344. package/src/pipeline/__tests__/job-trigger-consumer.integration.test.ts +106 -0
  345. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +308 -77
  346. package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +16 -8
  347. package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
  348. package/src/pipeline/__tests__/projection-rebuild.integration.test.ts +80 -2
  349. package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +274 -0
  350. package/src/pipeline/__tests__/try-append-event.integration.test.ts +166 -0
  351. package/src/pipeline/dispatch-batch.ts +187 -0
  352. package/src/pipeline/dispatch-query.ts +165 -0
  353. package/src/pipeline/dispatch-shared.ts +826 -0
  354. package/src/pipeline/dispatch-stream.ts +90 -0
  355. package/src/pipeline/dispatch-write.ts +451 -0
  356. package/src/pipeline/dispatcher-utils.ts +1 -1
  357. package/src/pipeline/dispatcher.ts +44 -1372
  358. package/src/pipeline/entity-cache.ts +2 -33
  359. package/src/pipeline/event-consumer-state.ts +30 -2
  360. package/src/pipeline/event-dispatcher-admin.ts +293 -0
  361. package/src/pipeline/event-dispatcher-delivery.ts +305 -0
  362. package/src/pipeline/event-dispatcher.ts +85 -542
  363. package/src/pipeline/index.ts +2 -0
  364. package/src/pipeline/msp-rebuild.ts +42 -3
  365. package/src/pipeline/multi-stream-apply-context.ts +4 -42
  366. package/src/pipeline/projection-rebuild.ts +105 -3
  367. package/src/pipeline/system-hooks.ts +144 -1
  368. package/src/rate-limit/__tests__/resolver.integration.test.ts +18 -0
  369. package/src/rate-limit/resolver.ts +16 -32
  370. package/src/schema-cli.ts +76 -16
  371. package/src/search/__tests__/meilisearch-adapter.integration.test.ts +207 -185
  372. package/src/search/__tests__/meilisearch-ids.test.ts +30 -0
  373. package/src/search/__tests__/reindex-entity.integration.test.ts +144 -0
  374. package/src/search/index.ts +6 -0
  375. package/src/search/meilisearch-adapter.ts +13 -12
  376. package/src/search/reindex-entity.ts +177 -0
  377. package/src/search/types.ts +1 -39
  378. package/src/secrets/__tests__/contains-secret.test.ts +34 -0
  379. package/src/secrets/__tests__/envelope-cipher.test.ts +59 -0
  380. package/src/secrets/__tests__/envelope.test.ts +1 -1
  381. package/src/secrets/dek-cache.ts +26 -5
  382. package/src/secrets/envelope-cipher.ts +53 -0
  383. package/src/secrets/envelope.ts +5 -3
  384. package/src/secrets/index.ts +13 -1
  385. package/src/secrets/stored-envelope.ts +46 -0
  386. package/src/secrets/types.ts +2 -162
  387. package/src/stack/__tests__/event-collector.test.ts +42 -0
  388. package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +125 -0
  389. package/src/stack/db.ts +2 -1
  390. package/src/stack/push-entity-projection-tables.ts +4 -3
  391. package/src/stack/redis.ts +8 -0
  392. package/src/stack/request-helper.ts +38 -2
  393. package/src/stack/table-helpers.ts +6 -4
  394. package/src/stack/test-stack.ts +249 -131
  395. package/src/testing/__tests__/late-bound.test.ts +32 -0
  396. package/src/testing/__tests__/wait-for.test.ts +59 -0
  397. package/src/testing/boot-validator-fixture.ts +121 -0
  398. package/src/testing/e2e-generator.ts +8 -0
  399. package/src/testing/file-provider-contract.ts +104 -0
  400. package/src/testing/handler-context.ts +3 -1
  401. package/src/testing/index.ts +5 -0
  402. package/src/testing/late-bound.ts +5 -3
  403. package/src/testing/mutable-master-key-provider.ts +29 -3
  404. package/src/testing/wait-for.ts +3 -0
  405. package/src/testing/without-ambient-temporal.ts +14 -0
  406. package/src/time/__tests__/tz-dateline.test.ts +8 -10
  407. package/src/time/geo-tz.ts +1 -32
  408. package/src/time/index.ts +1 -0
  409. package/src/time/legacy-date.ts +18 -0
  410. package/src/time/polyfill.ts +21 -38
  411. package/src/time/tz-context.ts +44 -85
  412. package/src/ui-types/app-schema.ts +12 -0
  413. package/src/ui-types/index.ts +20 -7
  414. package/src/utils/__tests__/safe-json-temporal.test.ts +18 -0
  415. package/src/utils/safe-json.ts +13 -1
  416. package/src/__tests__/raw-table.integration.test.ts +0 -116
  417. package/src/bun-db/__tests__/bun-test-stack.ts +0 -6
  418. package/src/db/__tests__/encryption.test.ts +0 -39
  419. package/src/db/encryption.ts +0 -39
  420. package/src/db/row-helpers.ts +0 -4
  421. package/src/engine/__tests__/raw-table.test.ts +0 -150
  422. package/src/engine/__tests__/unmanaged-table.test.ts +0 -127
  423. package/src/engine/feature-ast/__tests__/visual-tree-parse.test.ts +0 -184
  424. package/src/engine/feature-ast/extractors/round4.ts +0 -1366
@@ -23,7 +23,7 @@ export const STANDARD_METRIC_DEFS: readonly MetricDefinition[] = [
23
23
  name: "kumiko_dispatcher_handler_duration_seconds",
24
24
  type: "histogram",
25
25
  description: "Dispatcher handler latency in seconds.",
26
- labels: ["handler", "success"],
26
+ labels: ["handler", "success", "outcome"],
27
27
  buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5],
28
28
  },
29
29
  {
@@ -83,6 +83,20 @@ export const STANDARD_METRIC_DEFS: readonly MetricDefinition[] = [
83
83
  "Event deliveries that threw. Repeated failures on the same event lead to dead-letter.",
84
84
  labels: ["consumer", "instance_id"],
85
85
  },
86
+ // Fires once per (consumer, instance) transition into "stuck dead" —
87
+ // the rearm-cooldown/rearm-budget in event-dispatcher-delivery.ts gave up
88
+ // and the consumer now needs an operator (restartConsumer()) to recover.
89
+ // Without this, "dead + auto-rearm exhausted" is only visible via a
90
+ // getConsumerState poll — ops has no push signal that a consumer crossed
91
+ // from "will self-heal" to "needs a human". Deliberately a counter, not a
92
+ // gauge: emitted once per transition (event-dispatcher.ts tracks which
93
+ // consumers already fired this), not once per still-dead poll pass.
94
+ {
95
+ name: "kumiko_event_consumer_rearm_exhausted_total",
96
+ type: "counter",
97
+ description: "Consumer transitioned to dead with its auto-rearm budget exhausted.",
98
+ labels: ["consumer", "instance_id"],
99
+ },
86
100
  // LISTEN-subscription health. 1 = active, 0 = dropped. Drops to 0 while
87
101
  // the dispatcher is running signal that delivery latency has regressed
88
102
  // from sub-millisecond (LISTEN) to pollIntervalMs (timer fallback); ops
@@ -94,6 +108,21 @@ export const STANDARD_METRIC_DEFS: readonly MetricDefinition[] = [
94
108
  "1 if the event-dispatcher holds an active PG LISTEN subscription on the events channel, 0 otherwise.",
95
109
  labels: [],
96
110
  },
111
+ // BullMQ backlog per lane + state (waiting/active/delayed/failed/…). Only
112
+ // the process that owns a lane's consumerLane polls it (job-runner.ts
113
+ // start()) — the count is a global Redis-backed value, no per-instance
114
+ // label needed. A growing "waiting" count means the lane's worker can't
115
+ // keep up with dispatch; "failed" trending up means jobs are erroring
116
+ // silently. Motivated by apps that run every job on the "api" lane
117
+ // (no dedicated worker consumer) — fanout/reconcile jobs then share
118
+ // Redis-queue capacity with request-handling, and contention is
119
+ // otherwise invisible until requests slow down.
120
+ {
121
+ name: "kumiko_job_queue_depth",
122
+ type: "gauge",
123
+ description: "BullMQ job counts per lane and state.",
124
+ labels: ["lane", "state"],
125
+ },
97
126
  ] as const;
98
127
 
99
128
  export function registerStandardMetrics(meter: Meter): void {
@@ -126,12 +155,18 @@ export function emitHttpRequest(
126
155
 
127
156
  export function emitDispatcherHandler(
128
157
  meter: Meter,
129
- labels: { readonly handler: string; readonly success: boolean },
158
+ labels: {
159
+ readonly handler: string;
160
+ readonly success: boolean;
161
+ /** completed = drained normally; aborted = consumer walked away (SSE). */
162
+ readonly outcome?: "completed" | "aborted";
163
+ },
130
164
  durationSeconds: number,
131
165
  ): void {
132
166
  meter.histogram("kumiko_dispatcher_handler_duration_seconds").observe(durationSeconds, {
133
167
  handler: labels.handler,
134
168
  success: String(labels.success),
169
+ outcome: labels.outcome ?? "completed",
135
170
  });
136
171
  }
137
172
 
@@ -188,6 +223,19 @@ export function emitEventConsumerLag(
188
223
  });
189
224
  }
190
225
 
226
+ // Caller (event-dispatcher.ts) is responsible for calling this exactly
227
+ // once per (consumer, instanceId) transition into exhausted-dead — not
228
+ // once per poll pass while it stays dead.
229
+ export function emitEventConsumerRearmExhausted(
230
+ meter: Meter,
231
+ labels: { readonly consumer: string; readonly instanceId: string },
232
+ ): void {
233
+ meter.counter("kumiko_event_consumer_rearm_exhausted_total").inc(1, {
234
+ consumer: labels.consumer,
235
+ instance_id: labels.instanceId,
236
+ });
237
+ }
238
+
191
239
  export function emitEventDispatcherListenConnected(meter: Meter, connected: boolean): void {
192
240
  meter.gauge("kumiko_event_dispatcher_listen_connected").set(connected ? 1 : 0);
193
241
  }
@@ -211,3 +259,17 @@ export function emitEventConsumerPassOutcome(
211
259
  });
212
260
  }
213
261
  }
262
+
263
+ // counts: BullMQ's Queue.getJobCounts() result, filtered by the caller to
264
+ // backlog-relevant states (waiting/active/delayed/failed/paused) — "completed"
265
+ // grows unboundedly without removeOnComplete and would make the gauge series
266
+ // monotonically increasing, useless as a backlog signal.
267
+ export function emitJobQueueDepth(
268
+ meter: Meter,
269
+ lane: string,
270
+ counts: Readonly<Record<string, number>>,
271
+ ): void {
272
+ for (const [state, count] of Object.entries(counts)) {
273
+ meter.gauge("kumiko_job_queue_depth").set(count, { lane, state });
274
+ }
275
+ }
@@ -1,29 +1 @@
1
- // Barrel for observability types. Split into span/metric/provider files so
2
- // each module stays focused; consumers still import from "./types".
3
-
4
- export type {
5
- Counter,
6
- Gauge,
7
- Histogram,
8
- Meter,
9
- MetricDefinition,
10
- MetricLabels,
11
- MetricsHandle,
12
- MetricType,
13
- } from "./metric";
14
- export type {
15
- ObservabilityOptions,
16
- ObservabilityProvider,
17
- SamplingConfig,
18
- SensitiveFilterConfig,
19
- } from "./provider";
20
- export type {
21
- SerializedTraceContext,
22
- Span,
23
- SpanAttributes,
24
- SpanAttributeValue,
25
- SpanKind,
26
- SpanStatus,
27
- StartSpanOptions,
28
- Tracer,
29
- } from "./span";
1
+ export type * from "@cosmicdrift/kumiko-types/observability";
@@ -1,56 +1 @@
1
- // Metric + Meter contract. Feature code interacts through ctx.metrics
2
- // (MetricsHandle); the framework wires Counter/Histogram/Gauge behind that.
3
-
4
- export type MetricLabels = Record<string, string | number | boolean>;
5
-
6
- export type MetricType = "counter" | "histogram" | "gauge";
7
-
8
- export type MetricDefinition = {
9
- // Fully-qualified name (with kumiko_<feature>_ prefix already applied).
10
- readonly name: string;
11
- readonly type: MetricType;
12
- readonly description?: string;
13
- // Declared label keys. Inc/observe calls with unknown label keys throw.
14
- readonly labels?: readonly string[];
15
- // Buckets only for histogram. If omitted, provider-default is used.
16
- readonly buckets?: readonly number[];
17
- readonly unit?: string;
18
- // If true, the framework auto-injects tenant_id from the active ctx.
19
- // Default false — adding tenant_id multiplies cardinality by tenant count.
20
- readonly tenantLabel?: boolean;
21
- };
22
-
23
- export interface Counter {
24
- inc(value?: number, labels?: MetricLabels): void;
25
- }
26
-
27
- export interface Histogram {
28
- observe(value: number, labels?: MetricLabels): void;
29
- }
30
-
31
- export interface Gauge {
32
- set(value: number, labels?: MetricLabels): void;
33
- inc(value?: number, labels?: MetricLabels): void;
34
- dec(value?: number, labels?: MetricLabels): void;
35
- }
36
-
37
- export interface Meter {
38
- // Called once per metric during boot. Duplicate names throw.
39
- registerMetric(def: MetricDefinition): void;
40
- // Lookup by fully-qualified name. Unknown names throw — typed access only.
41
- counter(name: string): Counter;
42
- histogram(name: string): Histogram;
43
- gauge(name: string): Gauge;
44
- // List of registered definitions — used by ctx.metrics to validate labels.
45
- definitions(): ReadonlyMap<string, MetricDefinition>;
46
- }
47
-
48
- // Public handle for feature code — ctx.metrics.
49
- // Name resolution uses the fully-qualified name (kumiko_<feature>_<short>).
50
- // The registrar resolves the short name from the calling feature context
51
- // at boot time; at handler time the map is ready.
52
- export interface MetricsHandle {
53
- inc(name: string, labels?: MetricLabels, value?: number): void;
54
- observe(name: string, value: number, labels?: MetricLabels): void;
55
- set(name: string, value: number, labels?: MetricLabels): void;
56
- }
1
+ export type * from "@cosmicdrift/kumiko-types/observability/metric";
@@ -1,32 +1 @@
1
- // Observability provider contract — the "plug" that implementations (noop,
2
- // console, otlp, prometheus) fulfil. Configuration types that consumers
3
- // (buildServer, setupTestStack) hand in also live here.
4
-
5
- import type { Meter } from "./metric";
6
- import type { Tracer } from "./span";
7
-
8
- export type SamplingConfig = {
9
- // Base sampling rate 0..1. Default 1 in v1 (sample everything).
10
- readonly tracing?: number;
11
- readonly alwaysOnError?: boolean;
12
- readonly alwaysOnSlow?: { readonly thresholdMs: number };
13
- };
14
-
15
- export type SensitiveFilterConfig = {
16
- readonly redactedHeaders: readonly string[];
17
- readonly redactedQueryParams: readonly string[];
18
- readonly redactedAttributeKeyPatterns: readonly RegExp[];
19
- };
20
-
21
- export type ObservabilityOptions = {
22
- readonly sampling?: SamplingConfig;
23
- readonly sensitiveFilter?: Partial<SensitiveFilterConfig>;
24
- };
25
-
26
- export interface ObservabilityProvider {
27
- readonly name: string;
28
- readonly tracer: Tracer;
29
- readonly meter: Meter;
30
- // Graceful flush. Called from framework lifecycle shutdown.
31
- shutdown(): Promise<void>;
32
- }
1
+ export type * from "@cosmicdrift/kumiko-types/observability/provider";
@@ -1,64 +1 @@
1
- // Span + Tracer contract. Provider implementations (noop, recording → console/otlp)
2
- // all speak this — everything else (middleware, dispatcher, db, redis, jobs)
3
- // is provider-agnostic.
4
-
5
- export type SpanAttributeValue = string | number | boolean;
6
- export type SpanAttributes = Record<string, SpanAttributeValue>;
7
-
8
- export type SpanStatus = "unset" | "ok" | "error";
9
-
10
- export type SpanKind = "internal" | "server" | "client" | "producer" | "consumer";
11
-
12
- // Serialized form of a trace context — what we pass across process boundaries
13
- // (outbox row, BullMQ job payload). Matches W3C trace-context spec loosely,
14
- // but staying minimal — a full W3C parser is v2.
15
- export type SerializedTraceContext = {
16
- readonly traceId: string;
17
- readonly spanId: string;
18
- readonly baggage?: Readonly<Record<string, string>>;
19
- };
20
-
21
- export type StartSpanOptions = {
22
- // Either a live Span (normal in-process parent) or a serialized trace
23
- // context (cross-process — outbox row, job payload). Both carry traceId
24
- // and spanId, so the tracer reads them uniformly. Omitted → fall back to
25
- // the AsyncLocalStorage active span.
26
- readonly parent?: Span | SerializedTraceContext;
27
- readonly attributes?: SpanAttributes;
28
- readonly kind?: SpanKind;
29
- readonly startTime?: number;
30
- };
31
-
32
- export interface Span {
33
- readonly traceId: string;
34
- readonly spanId: string;
35
- readonly parentSpanId: string | undefined;
36
- readonly name: string;
37
- setAttribute(key: string, value: SpanAttributeValue): void;
38
- setAttributes(attrs: SpanAttributes): void;
39
- setStatus(status: SpanStatus, message?: string): void;
40
- recordException(error: Error): void;
41
- end(endTime?: number): void;
42
- // Whether end() has been called. Idempotency guard for auto-wrappers.
43
- readonly ended: boolean;
44
- }
45
-
46
- export interface Tracer {
47
- startSpan(name: string, options?: StartSpanOptions): Span;
48
- // Runs fn inside the span context (AsyncLocalStorage), ends the span
49
- // automatically — including on thrown errors, where the error is recorded
50
- // and status set to "error" before re-throwing.
51
- withSpan<T>(
52
- name: string,
53
- optionsOrFn: StartSpanOptions | ((span: Span) => Promise<T>),
54
- fn?: (span: Span) => Promise<T>,
55
- ): Promise<T>;
56
- // Current active span from AsyncLocalStorage, or undefined.
57
- getActiveSpan(): Span | undefined;
58
- // @deprecated Prefer `startSpan(name, { parent: context })`.
59
- startSpanFromContext(
60
- name: string,
61
- context: SerializedTraceContext,
62
- options?: StartSpanOptions,
63
- ): Span;
64
- }
1
+ export type * from "@cosmicdrift/kumiko-types/observability/span";
@@ -131,14 +131,14 @@ const bridgeFeature = defineFeature("ctxbridge", (r) => {
131
131
  );
132
132
 
133
133
  // afterCommit hook on bag — fires once per outer commit.
134
- r.entityHook("postSave", bag, async (result) => {
134
+ r.hook("postSave", { allOf: bag }, async (result) => {
135
135
  afterCommitLog.push(`bag:${result.data["label"]}`);
136
136
  });
137
137
 
138
138
  // afterCommit hook on secret — the entity targeted by the nested writeAs.
139
139
  // Proves: (a) hook fires exactly once per successful writeAs, (b) hook
140
140
  // does NOT fire when the outer transaction rolls back.
141
- r.entityHook("postSave", secret, async (result) => {
141
+ r.hook("postSave", { allOf: secret }, async (result) => {
142
142
  afterCommitLog.push(`secret:${result.data["owner"]}`);
143
143
  });
144
144
  });