@cosmicdrift/kumiko-framework 0.307.0 → 0.309.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 (174) hide show
  1. package/package.json +5 -5
  2. package/src/__tests__/anonymous-access.integration.test.ts +1 -1
  3. package/src/__tests__/error-contract.integration.test.ts +1 -1
  4. package/src/__tests__/field-access.integration.test.ts +1 -1
  5. package/src/__tests__/fixtures/migrate-open-to-all/manual-only.expected.ts +1 -1
  6. package/src/__tests__/fixtures/migrate-open-to-all/manual-only.input.ts +1 -1
  7. package/src/__tests__/fixtures/migrate-open-to-all/test-simple.expected.ts +1 -1
  8. package/src/__tests__/fixtures/migrate-open-to-all/test-simple.input.ts +1 -1
  9. package/src/__tests__/full-stack.integration.test.ts +1 -1
  10. package/src/__tests__/transition-guard.integration.test.ts +1 -1
  11. package/src/api/__tests__/api.test.ts +1 -1
  12. package/src/api/__tests__/batch.integration.test.ts +1 -1
  13. package/src/api/__tests__/body-limit.test.ts +1 -1
  14. package/src/api/__tests__/dispatcher-live.integration.test.ts +1 -1
  15. package/src/api/__tests__/extra-routes.integration.test.ts +1 -1
  16. package/src/api/__tests__/http-route-rate-limit.integration.test.ts +1 -1
  17. package/src/api/__tests__/nested-write-ownership.integration.test.ts +1 -1
  18. package/src/api/__tests__/nested-write.integration.test.ts +1 -1
  19. package/src/api/__tests__/pii-leak-guard.integration.test.ts +1 -1
  20. package/src/api/__tests__/redis-sse-broker.integration.test.ts +73 -6
  21. package/src/api/__tests__/request-locale.integration.test.ts +1 -1
  22. package/src/api/__tests__/server-boot-guards.test.ts +1 -1
  23. package/src/api/__tests__/server-error-logging.test.ts +1 -1
  24. package/src/api/__tests__/sse-broker.test.ts +107 -13
  25. package/src/api/__tests__/stream-escape-hatch.integration.test.ts +1 -1
  26. package/src/api/auth-routes.ts +1 -1
  27. package/src/api/redis-sse-broker.ts +51 -11
  28. package/src/api/server.ts +11 -0
  29. package/src/api/sse-broker.ts +61 -22
  30. package/src/bun-db/__tests__/postgres-closed-socket-write.integration.test.ts +87 -0
  31. package/src/bun-db/connection.ts +2 -0
  32. package/src/changes.json +61 -0
  33. package/src/compliance/override-schema.ts +1 -1
  34. package/src/crypto/__tests__/event-pii.test.ts +1 -1
  35. package/src/crypto/kms-adapter.ts +1 -1
  36. package/src/db/__tests__/feature-table-sources.test.ts +2 -2
  37. package/src/db/__tests__/tenant-db-where-merge.integration.test.ts +1 -1
  38. package/src/db/collect-table-metas.ts +3 -6
  39. package/src/db/feature-table-sources.ts +3 -4
  40. package/src/db/queries/event-consumer.ts +98 -6
  41. package/src/derivatives/__tests__/derivatives-context.integration.test.ts +1 -1
  42. package/src/derivatives/delete-stored-file.ts +86 -0
  43. package/src/derivatives/index.ts +2 -0
  44. package/src/engine/__tests__/boot-validator-action-wiring.test.ts +1 -1
  45. package/src/engine/__tests__/boot-validator-dashboard.test.ts +1 -1
  46. package/src/engine/__tests__/boot-validator-nav-area.test.ts +1 -1
  47. package/src/engine/__tests__/boot-validator-pii-retention.test.ts +1 -1
  48. package/src/engine/__tests__/boot-validator-projection-list.test.ts +1 -1
  49. package/src/engine/__tests__/boot-validator-query-output-schema.test.ts +1 -1
  50. package/src/engine/__tests__/boot-validator-query-refs.test.ts +1 -1
  51. package/src/engine/__tests__/boot-validator-ref-entity.test.ts +1 -1
  52. package/src/engine/__tests__/boot-validator-s0-integration.test.ts +1 -1
  53. package/src/engine/__tests__/boot-validator.test.ts +35 -1
  54. package/src/engine/__tests__/build-app-schema.test.ts +1 -1
  55. package/src/engine/__tests__/build-config-feature-schema-secrets.test.ts +1 -1
  56. package/src/engine/__tests__/define-feature-entity-mapping.test.ts +1 -1
  57. package/src/engine/__tests__/engine.test.ts +1 -1
  58. package/src/engine/__tests__/event-helpers.test.ts +1 -1
  59. package/src/engine/__tests__/event-migration-declarative.test.ts +1 -1
  60. package/src/engine/__tests__/extend-entity-projection.test.ts +1 -1
  61. package/src/engine/__tests__/extends-registrar.test.ts +1 -1
  62. package/src/engine/__tests__/hook-phases.test.ts +1 -1
  63. package/src/engine/__tests__/lifecycle-hooks.test.ts +1 -1
  64. package/src/engine/__tests__/pipeline-engine.test.ts +1 -1
  65. package/src/engine/__tests__/pipeline-handler.integration.test.ts +1 -1
  66. package/src/engine/__tests__/pipeline-observability.integration.test.ts +1 -1
  67. package/src/engine/__tests__/pipeline-performance.integration.test.ts +1 -1
  68. package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +1 -1
  69. package/src/engine/__tests__/post-query-hook.test.ts +1 -1
  70. package/src/engine/__tests__/projection-detail-actions.test.ts +1 -1
  71. package/src/engine/__tests__/projection-detail-singleton.test.ts +1 -1
  72. package/src/engine/__tests__/projection-detail-tabs.test.ts +1 -1
  73. package/src/engine/__tests__/read-steps-tenant-filter.integration.test.ts +1 -1
  74. package/src/engine/__tests__/registry.test.ts +1 -1
  75. package/src/engine/__tests__/screen.test.ts +1 -1
  76. package/src/engine/__tests__/validate-projection-allowlist.test.ts +1 -1
  77. package/src/engine/boot-validator/__tests__/access-declarations.test.ts +1 -1
  78. package/src/engine/boot-validator/__tests__/action-icon.test.ts +81 -0
  79. package/src/engine/boot-validator/__tests__/anonymous-rate-limit-required.test.ts +1 -1
  80. package/src/engine/boot-validator/__tests__/no-all-role-in-handler-access.test.ts +1 -1
  81. package/src/engine/boot-validator/__tests__/parent-ref.test.ts +1 -1
  82. package/src/engine/boot-validator/__tests__/rate-limit-disabled-reason.test.ts +1 -1
  83. package/src/engine/boot-validator/screens.ts +83 -0
  84. package/src/engine/define-handler.ts +2 -1
  85. package/src/engine/entity-handlers.ts +2 -1
  86. package/src/engine/feature-ast/__tests__/pattern-change-schema.test.ts +1 -1
  87. package/src/engine/feature-ast/pattern-change-schema.ts +1 -1
  88. package/src/engine/feature-builder-state.ts +2 -1
  89. package/src/engine/feature-config-events-jobs.ts +2 -1
  90. package/src/engine/feature-entity-handlers.ts +2 -1
  91. package/src/engine/schema-builder.ts +1 -1
  92. package/src/entrypoint/__tests__/entrypoint-attach-dispatcher.integration.test.ts +1 -1
  93. package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.test.ts +1 -1
  94. package/src/entrypoint/__tests__/split-deploy.integration.test.ts +1 -1
  95. package/src/env/__tests__/compose-env-schema.test.ts +1 -1
  96. package/src/env/__tests__/dry-run.test.ts +1 -1
  97. package/src/env/__tests__/parse-env-dry-run.test.ts +1 -1
  98. package/src/env/_zod-introspect.ts +1 -1
  99. package/src/env/dry-run.ts +1 -1
  100. package/src/env/index.ts +1 -1
  101. package/src/errors/__tests__/classes.test.ts +1 -1
  102. package/src/es-ops/__tests__/runner.integration.test.ts +1 -1
  103. package/src/event-store/__tests__/backfill-pii.integration.test.ts +1 -1
  104. package/src/event-store/__tests__/event-attribution.integration.test.ts +1 -1
  105. package/src/event-store/__tests__/upcaster.integration.test.ts +1 -1
  106. package/src/jobs/__tests__/job-backoff.integration.test.ts +1 -1
  107. package/src/jobs/__tests__/job-event-trigger.integration.test.ts +1 -1
  108. package/src/jobs/__tests__/job-multi-trigger.integration.test.ts +1 -1
  109. package/src/jobs/__tests__/job-public-intake-origin.integration.test.ts +1 -1
  110. package/src/jobs/__tests__/job-retention.integration.test.ts +1 -1
  111. package/src/jobs/__tests__/job-write-as.integration.test.ts +1 -1
  112. package/src/jobs/__tests__/jobs.integration.test.ts +1 -1
  113. package/src/observability/__tests__/metrics-wiring.test.ts +1 -1
  114. package/src/observability/__tests__/observability.integration.test.ts +1 -1
  115. package/src/observability/metrics-wiring.ts +1 -1
  116. package/src/pipeline/__tests__/archive-stream.integration.test.ts +1 -1
  117. package/src/pipeline/__tests__/causation-chain.integration.test.ts +1 -1
  118. package/src/pipeline/__tests__/ctx-bridge.integration.test.ts +1 -1
  119. package/src/pipeline/__tests__/ctx-systemdb.integration.test.ts +1 -1
  120. package/src/pipeline/__tests__/dispatcher.test.ts +1 -1
  121. package/src/pipeline/__tests__/domain-events-projections.integration.test.ts +1 -1
  122. package/src/pipeline/__tests__/escape-hatch-audit.integration.test.ts +1 -1
  123. package/src/pipeline/__tests__/escape-hatch.integration.test.ts +1 -1
  124. package/src/pipeline/__tests__/event-dedup.integration.test.ts +1 -1
  125. package/src/pipeline/__tests__/event-define-event-strict.integration.test.ts +1 -1
  126. package/src/pipeline/__tests__/event-dispatcher-batch-delivery.test.ts +178 -0
  127. package/src/pipeline/__tests__/event-dispatcher-batch-handler.integration.test.ts +143 -0
  128. package/src/pipeline/__tests__/event-dispatcher-db-outage.integration.test.ts +192 -0
  129. package/src/pipeline/__tests__/event-dispatcher-idle.integration.test.ts +94 -0
  130. package/src/pipeline/__tests__/event-dispatcher-start-from.integration.test.ts +103 -3
  131. package/src/pipeline/__tests__/fetch-for-writing.integration.test.ts +1 -1
  132. package/src/pipeline/__tests__/idempotency-transient-failure.integration.test.ts +1 -1
  133. package/src/pipeline/__tests__/job-trigger-consumer.integration.test.ts +1 -1
  134. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +1 -1
  135. package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +1 -1
  136. package/src/pipeline/__tests__/msp-multi-hop.integration.test.ts +1 -1
  137. package/src/pipeline/__tests__/msp-rebuild.integration.test.ts +116 -1
  138. package/src/pipeline/__tests__/multi-stream-projection.integration.test.ts +1 -1
  139. package/src/pipeline/__tests__/pending-gap-ranges.test.ts +94 -0
  140. package/src/pipeline/__tests__/post-query-hook.integration.test.ts +1 -1
  141. package/src/pipeline/__tests__/public-intake-runtime-gate.integration.test.ts +1 -1
  142. package/src/pipeline/__tests__/query-projection.integration.test.ts +1 -1
  143. package/src/pipeline/__tests__/rate-limit-default.integration.test.ts +1 -1
  144. package/src/pipeline/__tests__/rebuild-poison-quarantine.integration.test.ts +1 -1
  145. package/src/pipeline/__tests__/search-consumer-named-events.integration.test.ts +1 -1
  146. package/src/pipeline/__tests__/system-identity-switch.integration.test.ts +1 -1
  147. package/src/pipeline/__tests__/try-append-event.integration.test.ts +1 -1
  148. package/src/pipeline/__tests__/unsafe-raw-escape-hatch.integration.test.ts +1 -1
  149. package/src/pipeline/dispatch-stream.ts +6 -1
  150. package/src/pipeline/event-dispatcher-delivery.ts +132 -37
  151. package/src/pipeline/event-dispatcher.ts +121 -17
  152. package/src/pipeline/index.ts +1 -0
  153. package/src/pipeline/msp-rebuild.ts +39 -1
  154. package/src/pipeline/pending-gap-ranges.ts +48 -0
  155. package/src/pipeline/system-hooks.ts +223 -68
  156. package/src/pipeline/write-origin.ts +1 -1
  157. package/src/rate-limit/__tests__/dispatcher-l3.integration.test.ts +1 -1
  158. package/src/search/__tests__/derive-search-adapter-config.test.ts +65 -0
  159. package/src/search/__tests__/meilisearch-adapter.integration.test.ts +91 -0
  160. package/src/search/__tests__/search-consumer-batch.integration.test.ts +306 -0
  161. package/src/search/derive-search-adapter-config.ts +27 -0
  162. package/src/search/index.ts +1 -0
  163. package/src/search/meilisearch-adapter.ts +96 -14
  164. package/src/secrets/__tests__/contains-secret.test.ts +1 -1
  165. package/src/stack/__tests__/request-helper.integration.test.ts +1 -1
  166. package/src/stack/__tests__/setup-test-stack-entity-tables.integration.test.ts +65 -0
  167. package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +1 -1
  168. package/src/stack/__tests__/setup-test-stack-metrics.integration.test.ts +1 -1
  169. package/src/stack/test-stack.ts +61 -54
  170. package/src/testing/__tests__/e2e-generator.test.ts +1 -1
  171. package/src/testing/__tests__/real-providers.test.ts +9 -1
  172. package/src/testing/e2e-generator.ts +1 -1
  173. package/src/testing/index.ts +1 -1
  174. package/src/testing/real-providers.ts +12 -4
@@ -1,5 +1,6 @@
1
1
  import { normalizeEventPiiSubject } from "@cosmicdrift/kumiko-types/handlers";
2
- import { ZodObject, type ZodType, type z } from "zod";
2
+ import type * as z from "zod";
3
+ import { ZodObject, type ZodType } from "zod";
3
4
  import type { FeatureBuilderState } from "./feature-builder-state";
4
5
  import { resolveName } from "./handler-helpers";
5
6
  import { splitNamedDefinition, unwrapArrayForm } from "./object-form";
@@ -1,5 +1,6 @@
1
1
  import { ENTITY_CONVENTION_QUERY_BRAND } from "@cosmicdrift/kumiko-types/handlers";
2
- import type { ZodType, z } from "zod";
2
+ import type * as z from "zod";
3
+ import type { ZodType } from "zod";
3
4
  import { toTableName } from "../db/table-builder";
4
5
  import {
5
6
  isEntityConventionQueryHandler,
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import * as z from "zod";
2
2
  import { moneyPayloadToMinorUnits } from "../db/money";
3
3
  import { isValidIanaTimeZone } from "../time";
4
4
  import { assertUnreachable } from "../utils";
@@ -10,7 +10,7 @@
10
10
  // throws the #2043 stub).
11
11
 
12
12
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
13
- import { z } from "zod";
13
+ import * as z from "zod";
14
14
  import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
15
15
  import { asRawClient } from "../../db/query";
16
16
  import { createRegistry, defineFeature } from "../../engine";
@@ -13,7 +13,7 @@
13
13
  // regressing to the Welle-2.5 state.
14
14
 
15
15
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
16
- import { z } from "zod";
16
+ import * as z from "zod";
17
17
  import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
18
18
  import { createRegistry, defineFeature } from "../../engine";
19
19
  import { createArchivedStreamsTable } from "../../event-store";
@@ -13,7 +13,7 @@
13
13
  // fires with systemConsumers explicitly disabled).
14
14
 
15
15
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
16
- import { z } from "zod";
16
+ import * as z from "zod";
17
17
  import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
18
18
  import { asRawClient } from "../../db/query";
19
19
  import { createRegistry, defineFeature } from "../../engine";
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { defineFeature } from "../../engine/define-feature";
4
4
  import {
5
5
  camelCase,
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { defineFeature } from "../../engine/define-feature";
4
4
  import { prometheusMetricsEnvSchema } from "../../observability/metrics-wiring";
5
5
  import { renderDryRun } from "../dry-run";
@@ -2,7 +2,7 @@
2
2
  // undefined. parseEnvDryRun liefert stattdessen ein ehrliches Partial.
3
3
 
4
4
  import { describe, expect, test } from "bun:test";
5
- import { z } from "zod";
5
+ import * as z from "zod";
6
6
  import { parseEnvDryRun } from "../index";
7
7
 
8
8
  const schema = z.object({
@@ -6,7 +6,7 @@
6
6
  // All helpers accept the *runtime* Zod instance — TypeScript wrapper
7
7
  // (`z.ZodType`) and core (`$ZodType`) are the same object at runtime.
8
8
 
9
- import type { z } from "zod";
9
+ import type * as z from "zod";
10
10
 
11
11
  export type ZodDef = {
12
12
  readonly innerType?: z.ZodType;
@@ -8,7 +8,7 @@
8
8
  // The same schema introspection (`classifyField`, `readKumikoMeta`) used
9
9
  // by parseEnv drives the output here — single source of truth.
10
10
 
11
- import type { z } from "zod";
11
+ import type * as z from "zod";
12
12
  import { zodShape } from "./_zod-introspect";
13
13
  import {
14
14
  type ComposedEnvSchema,
package/src/env/index.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  // Without meta, defaults: `camelCase(envVarName)` for the Pulumi key,
15
15
  // `<set-me>` placeholder for the value, no `--secret` flag.
16
16
 
17
- import { z } from "zod";
17
+ import * as z from "zod";
18
18
  import type { FeatureDefinition } from "../engine/types/feature";
19
19
  import { zodDef, zodDescription, zodMeta, zodShape, zodShapeField } from "./_zod-introspect";
20
20
 
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import {
4
4
  AccessDeniedError,
5
5
  buildErrorLog,
@@ -17,7 +17,7 @@ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:tes
17
17
  import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
18
18
  import { tmpdir } from "node:os";
19
19
  import { join } from "node:path";
20
- import { z } from "zod";
20
+ import * as z from "zod";
21
21
  import { createEventStoreExecutor } from "../../db/event-store-executor";
22
22
  import { asRawClient, insertOne, selectMany } from "../../db/query";
23
23
  import { buildEntityTable } from "../../db/table-builder";
@@ -12,7 +12,7 @@ import {
12
12
  resetBlindIndexKeyForTests,
13
13
  resetPiiSubjectKmsForTests,
14
14
  } from "@cosmicdrift/kumiko-framework/testing";
15
- import { z } from "zod";
15
+ import * as z from "zod";
16
16
  import {
17
17
  configureBlindIndexKey,
18
18
  configurePiiSubjectKms,
@@ -15,7 +15,7 @@
15
15
 
16
16
  import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
17
17
  import { UNATTRIBUTED_ORIGIN, type WriteOrigin } from "@cosmicdrift/kumiko-types/event-store-types";
18
- import { z } from "zod";
18
+ import * as z from "zod";
19
19
  import { createEventStoreExecutor } from "../../db/event-store-executor";
20
20
  import { selectMany } from "../../db/query";
21
21
  import { buildEntityTable } from "../../db/table-builder";
@@ -9,7 +9,7 @@
9
9
  // can never silently hand half-migrated data to consumers.
10
10
 
11
11
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
12
- import { z } from "zod";
12
+ import * as z from "zod";
13
13
  import { integer as pgInteger, table as pgTable, text as pgText } from "../../db/dialect";
14
14
  import { createEventStoreExecutor } from "../../db/event-store-executor";
15
15
  import { asRawClient, insertOne, selectMany } from "../../db/query";
@@ -10,7 +10,7 @@
10
10
  // so a >= assertion is flake-free without inflating waitFor's budget.
11
11
 
12
12
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
13
- import { z } from "zod";
13
+ import * as z from "zod";
14
14
  import { defineFeature } from "../../engine";
15
15
  import { setupTestStack, type TestStack, TestUsers } from "../../stack";
16
16
  import { waitFor } from "../../testing";
@@ -1,6 +1,6 @@
1
1
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
2
  import type { Hono } from "hono";
3
- import { z } from "zod";
3
+ import * as z from "zod";
4
4
  import { buildServer, type JwtHelper } from "../../api";
5
5
  import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
6
6
  import { createRegistry, defineFeature, type SessionUser } from "../../engine";
@@ -8,7 +8,7 @@
8
8
 
9
9
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
10
10
  import type { Hono } from "hono";
11
- import { z } from "zod";
11
+ import * as z from "zod";
12
12
  import { buildServer, type JwtHelper } from "../../api";
13
13
  import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
14
14
  import { createRegistry, defineFeature, type SessionUser } from "../../engine";
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
4
4
  import { Queue } from "bullmq";
5
- import { z } from "zod";
5
+ import * as z from "zod";
6
6
  import type { SchemaTable } from "../../db";
7
7
  import { createEventStoreExecutor } from "../../db/event-store-executor";
8
8
  import { asRawClient, selectMany } from "../../db/query";
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
9
9
  import { Queue } from "bullmq";
10
- import { z } from "zod";
10
+ import * as z from "zod";
11
11
  import { createRegistry, defineFeature } from "../../engine";
12
12
  import type { AppContext, TenantId } from "../../engine/types";
13
13
  import { createTestRedis, type TestRedis } from "../../stack";
@@ -9,7 +9,7 @@
9
9
  // to the actor rather than to SYSTEM.
10
10
 
11
11
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
12
- import { z } from "zod";
12
+ import * as z from "zod";
13
13
  import { ROLES } from "../../auth/roles";
14
14
  import { type BunTestDb, createTestDb } from "../../bun-db/__tests__/bun-test-db";
15
15
  import { asRawClient } from "../../db/query";
@@ -1,6 +1,6 @@
1
1
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
2
  import { Queue } from "bullmq";
3
- import { z } from "zod";
3
+ import * as z from "zod";
4
4
  import { requestContext } from "../../api/request-context";
5
5
  import { tenantDbRunner } from "../../db/tenant-db-runner";
6
6
  import { createRegistry, defineFeature } from "../../engine";
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { composeEnvSchema, readKumikoMeta } from "../../env";
4
4
  import { prometheusMetricsEnvSchema, resolveObservabilityWiring } from "../metrics-wiring";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import type { TableColumns } from "../../db/dialect";
4
4
  import { buildEntityTable } from "../../db/table-builder";
5
5
  import { createRegistry, defineFeature } from "../../engine";
@@ -1,4 +1,4 @@
1
- import { z } from "zod";
1
+ import * as z from "zod";
2
2
  import { createNoopProvider } from "./noop-provider";
3
3
  import { createPrometheusMeter, type PrometheusMeter } from "./prometheus-meter";
4
4
  import type { ObservabilityProvider } from "./types";
@@ -6,7 +6,7 @@
6
6
  // streams never pay for extra metadata writes.
7
7
 
8
8
  import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
9
- import { z } from "zod";
9
+ import * as z from "zod";
10
10
  import { createEventStoreExecutor } from "../../db/event-store-executor";
11
11
  import { buildEntityTable } from "../../db/table-builder";
12
12
  import { createEntity, createTextField, defineFeature } from "../../engine";
@@ -16,7 +16,7 @@
16
16
  // msp-multi-hop.integration.ts.
17
17
 
18
18
  import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
19
- import { z } from "zod";
19
+ import * as z from "zod";
20
20
  import { requestContext } from "../../api/request-context";
21
21
  import { createEventStoreExecutor } from "../../db/event-store-executor";
22
22
  import { selectMany } from "../../db/query";
@@ -1,5 +1,5 @@
1
1
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { createEventStoreExecutor } from "../../db/event-store-executor";
4
4
  import { asRawClient, selectMany } from "../../db/query";
5
5
  import { buildEntityTable } from "../../db/table-builder";
@@ -1,5 +1,5 @@
1
1
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { defineFeature } from "../../engine";
4
4
  import { setupTestStack, type TestStack, TestUsers } from "../../stack";
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import type { SseBroker } from "../../api/sse-broker";
4
4
  import { createEntity, createRegistry, createTextField, defineFeature } from "../../engine";
5
5
  import type { TenantId } from "../../engine/types/identifiers";
@@ -10,7 +10,7 @@
10
10
  // projections-runner fires on appendEvent, dispatcher routes appendEvent to
11
11
  // the aggregate stream), any of the assertions below go red.
12
12
  import { afterAll, afterEach, beforeAll, describe, expect, test } from "bun:test";
13
- import { z } from "zod";
13
+ import * as z from "zod";
14
14
  import {
15
15
  integer as pgInteger,
16
16
  table as pgTable,
@@ -4,7 +4,7 @@
4
4
  // system-identity-switch.integration.test.ts.
5
5
 
6
6
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
7
- import { z } from "zod";
7
+ import * as z from "zod";
8
8
  import { defineUnmanagedTable } from "../../db/entity-table-meta";
9
9
  import { executeRawQuery } from "../../db/queries/raw-sql";
10
10
  import { createSystemUser, defineFeature } from "../../engine";
@@ -3,7 +3,7 @@
3
3
  // Real HTTP calls + setupTestStack — never createTestDispatcher.
4
4
 
5
5
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
6
- import { z } from "zod";
6
+ import * as z from "zod";
7
7
  import { defineUnmanagedTable } from "../../db/entity-table-meta";
8
8
  import { defineFeature } from "../../engine";
9
9
  import { createTestUser, setupTestStack, type TestStack } from "../../stack";
@@ -1,5 +1,5 @@
1
1
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
2
- import { z } from "zod";
2
+ import * as z from "zod";
3
3
  import { createEventStoreExecutor } from "../../db/event-store-executor";
4
4
  import { defineFeature, type SaveContext } from "../../engine";
5
5
  import {
@@ -11,7 +11,7 @@
11
11
  // 3. r.defineEvent returns `{ name: qualifiedName, schema }` — callers
12
12
  // pass `def.name` to ctx.appendEvent without building the qn manually.
13
13
  import { afterEach, beforeAll, describe, expect, test } from "bun:test";
14
- import { z } from "zod";
14
+ import * as z from "zod";
15
15
  import { selectMany } from "../../db/query";
16
16
  import { defineFeature } from "../../engine";
17
17
  import { eventsTable } from "../../event-store";
@@ -0,0 +1,178 @@
1
+ // #3227 — deliverEvents' batchHandler fast-path: batch success must land
2
+ // the exact outcome the per-event loop would produce, a batch throw falls
3
+ // back to per-event delivery without bumping attempts for the failed
4
+ // batch attempt itself, and pending-gap resolution still splits pending
5
+ // vs new ids the same way it does for the per-event path.
6
+
7
+ import { beforeAll, describe, expect, test } from "bun:test";
8
+ import type { AppContext } from "../../engine/types";
9
+ import { ensureTemporalPolyfill } from "../../time/polyfill";
10
+ import type { EventConsumer } from "../event-dispatcher";
11
+ import {
12
+ type ConsumerStateRow,
13
+ deliverEvents,
14
+ type StoredEventRow,
15
+ } from "../event-dispatcher-delivery";
16
+
17
+ beforeAll(async () => {
18
+ await ensureTemporalPolyfill();
19
+ });
20
+
21
+ function stubContext(): AppContext {
22
+ return {
23
+ db: {} as unknown as AppContext["db"],
24
+ redis: {} as unknown as AppContext["redis"],
25
+ registry: {} as unknown as AppContext["registry"],
26
+ } as AppContext;
27
+ }
28
+
29
+ function stubEvent(id: bigint): StoredEventRow {
30
+ return {
31
+ id,
32
+ aggregateId: "agg-1",
33
+ aggregateType: "widget",
34
+ tenantId: "tenant-1",
35
+ version: 1,
36
+ type: "widget.created",
37
+ eventVersion: 1,
38
+ payload: {},
39
+ metadata: { userId: "system" },
40
+ createdAt: Temporal.Now.instant(),
41
+ createdBy: "system",
42
+ };
43
+ }
44
+
45
+ function stubState(overrides: Partial<ConsumerStateRow> = {}): ConsumerStateRow {
46
+ return {
47
+ name: "consumer",
48
+ instanceId: "shared",
49
+ lastProcessedEventId: 0n,
50
+ status: "idle",
51
+ attempts: 0,
52
+ rearmCount: 0,
53
+ pendingGaps: [],
54
+ lastError: null,
55
+ updatedAt: Temporal.Now.instant(),
56
+ ...overrides,
57
+ };
58
+ }
59
+
60
+ describe("deliverEvents — batchHandler fast-path", () => {
61
+ test("batch success calls batchHandler once, never handler, and matches the per-event outcome", async () => {
62
+ const rows = [1n, 2n, 3n].map(stubEvent);
63
+ const batchCalls: string[][] = [];
64
+ let handlerCalls = 0;
65
+
66
+ const batchConsumer: EventConsumer = {
67
+ name: "search",
68
+ batchHandler: async (events) => {
69
+ batchCalls.push(events.map((e) => e.id));
70
+ },
71
+ handler: async () => {
72
+ handlerCalls += 1;
73
+ },
74
+ };
75
+ const perEventConsumer: EventConsumer = {
76
+ name: "search",
77
+ handler: async () => {
78
+ // no-op — succeeds for every event, same as the batch above
79
+ },
80
+ };
81
+
82
+ const batchOutcome = await deliverEvents(batchConsumer, rows, stubContext(), 10, stubState());
83
+ const perEventOutcome = await deliverEvents(
84
+ perEventConsumer,
85
+ rows,
86
+ stubContext(),
87
+ 10,
88
+ stubState(),
89
+ );
90
+
91
+ expect(batchCalls).toEqual([["1", "2", "3"]]);
92
+ expect(handlerCalls).toBe(0);
93
+ expect(batchOutcome).toEqual(perEventOutcome);
94
+ expect(batchOutcome.cursor).toBe(3n);
95
+ expect(batchOutcome.attempts).toBe(0);
96
+ expect(batchOutcome.lastError).toBeNull();
97
+ expect(batchOutcome.processed).toBe(3);
98
+ expect(batchOutcome.failed).toBe(0);
99
+ });
100
+
101
+ test("pending-gap ids resolve the same way as per-event delivery", async () => {
102
+ const rows = [4n, 7n, 11n, 12n].map(stubEvent);
103
+ const consumer: EventConsumer = {
104
+ name: "search",
105
+ batchHandler: async () => {
106
+ // succeeds
107
+ },
108
+ handler: async () => {
109
+ throw new Error("handler must not run on batch success");
110
+ },
111
+ };
112
+
113
+ const outcome = await deliverEvents(
114
+ consumer,
115
+ rows,
116
+ stubContext(),
117
+ 10,
118
+ stubState({ lastProcessedEventId: 10n }),
119
+ );
120
+
121
+ expect(outcome.resolvedPendingIds).toEqual([4n, 7n]);
122
+ expect(outcome.cursor).toBe(12n);
123
+ });
124
+
125
+ test("batch throws, one poison row: falls back to per-event delivery without bumping attempts for the batch failure itself", async () => {
126
+ const rows = [1n, 2n, 3n, 4n, 5n].map(stubEvent);
127
+ const handlerCalls: string[] = [];
128
+ const consumer: EventConsumer = {
129
+ name: "search",
130
+ errorPolicy: { maxAttempts: 2 },
131
+ batchHandler: async () => {
132
+ throw new Error("batch failed");
133
+ },
134
+ handler: async (event) => {
135
+ handlerCalls.push(event.id);
136
+ if (event.id === "3") throw new Error("poison event");
137
+ },
138
+ };
139
+
140
+ const first = await deliverEvents(consumer, rows, stubContext(), 10, stubState());
141
+ expect(first.cursor).toBe(2n);
142
+ expect(first.attempts).toBe(1);
143
+ expect(first.deadLettered).toBe(false);
144
+ expect(handlerCalls).toEqual(["1", "2", "3"]);
145
+
146
+ const remaining = [3n, 4n, 5n].map(stubEvent);
147
+ const second = await deliverEvents(
148
+ consumer,
149
+ remaining,
150
+ stubContext(),
151
+ 10,
152
+ stubState({ lastProcessedEventId: first.cursor, attempts: first.attempts }),
153
+ );
154
+ expect(second.attempts).toBe(2);
155
+ expect(second.deadLettered).toBe(true);
156
+ });
157
+
158
+ test("batch throws with skipApplyErrors: true skips the poison row and delivers the rest via handler", async () => {
159
+ const rows = [1n, 2n, 3n, 4n, 5n].map(stubEvent);
160
+ const handlerCalls: string[] = [];
161
+ const consumer: EventConsumer = {
162
+ name: "search",
163
+ errorPolicy: { skipApplyErrors: true },
164
+ batchHandler: async () => {
165
+ throw new Error("batch failed");
166
+ },
167
+ handler: async (event) => {
168
+ handlerCalls.push(event.id);
169
+ if (event.id === "3") throw new Error("poison event");
170
+ },
171
+ };
172
+
173
+ const outcome = await deliverEvents(consumer, rows, stubContext(), 10, stubState());
174
+
175
+ expect(outcome.cursor).toBe(5n);
176
+ expect(handlerCalls).toEqual(["1", "2", "3", "4", "5"]);
177
+ });
178
+ });