@classytic/mongokit 3.28.0 → 3.30.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 (37) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +54 -1
  3. package/TRADEMARK.md +22 -0
  4. package/dist/{create-repository-D4ZU94b3.d.mts → Repository-BXHkUtLk.d.mts} +30 -57
  5. package/dist/{Repository-BFBTAMlA.mjs → Repository-X7U2d0kU.mjs} +417 -47
  6. package/dist/actions/index.mjs +1 -1
  7. package/dist/adapter/index.mjs +1 -1
  8. package/dist/{adapter-CLvUHiTW.mjs → adapter-BitHg-CN.mjs} +1 -1
  9. package/dist/ai/index.d.mts +1 -1
  10. package/dist/better-auth/index.d.mts +13 -0
  11. package/dist/better-auth/index.mjs +76 -6
  12. package/dist/create-repository-CvD4wzuN.d.mts +54 -0
  13. package/dist/{create-repository-2DMwkYVz.mjs → create-repository-DYe5YEie.mjs} +3 -2
  14. package/dist/index.d.mts +275 -41
  15. package/dist/index.mjs +80 -7
  16. package/dist/kernel-conformance/index.d.mts +217 -0
  17. package/dist/kernel-conformance/index.mjs +603 -0
  18. package/dist/method-registry.plugin-DblM7V6j.mjs +112 -0
  19. package/dist/model-registry-ClKtWiHa.mjs +67 -0
  20. package/dist/{mongooseToJsonSchema-CByt1VhQ.mjs → mongooseToJsonSchema-DKbnKduN.mjs} +14 -3
  21. package/dist/{multi-tenant.plugin-DVyVGREb.d.mts → multi-tenant.plugin-2VtSSm1Y.d.mts} +1 -1
  22. package/dist/outbox/index.d.mts +63 -0
  23. package/dist/outbox/index.mjs +239 -0
  24. package/dist/{plugin-options-vFufQZMZ.d.mts → plugin-options-BsFH0sTi.d.mts} +1 -1
  25. package/dist/plugins/index.d.mts +4 -4
  26. package/dist/plugins/index.mjs +3 -2
  27. package/dist/{repository-DCHRWRXw.d.mts → repository-Q16ErTu8.d.mts} +19 -1
  28. package/dist/testkit/index.d.mts +8 -1
  29. package/dist/testkit/index.mjs +1 -1
  30. package/dist/{timestamp.plugin-ennbatTW.mjs → timestamp.plugin-ChFRcLRJ.mjs} +32 -143
  31. package/dist/{to-plain-DkF5px0R.d.mts → to-plain-BuX1RUZV.d.mts} +12 -4
  32. package/dist/{update-1Lq9OMD2.mjs → update-DHdXdOk_.mjs} +43 -30
  33. package/dist/utils/index.d.mts +2 -2
  34. package/dist/utils/index.mjs +1 -1
  35. package/dist/{validation-chain.plugin-Cm0Ttnd8.d.mts → validation-chain.plugin-BSshLJTA.d.mts} +44 -44
  36. package/dist/{validation-chain.plugin-k9joH2qw.mjs → validation-chain.plugin-BxTl_dYR.mjs} +139 -138
  37. package/package.json +28 -15
package/dist/index.mjs CHANGED
@@ -1,19 +1,21 @@
1
1
  import { n as idVariants } from "./id-resolution-BqDrk0S2.mjs";
2
- import { a as supportsTransactions, c as ALL_OPERATIONS, d as READ_OPERATIONS, f as operationsByPolicyKey, i as isTransactionUnsupported, l as MUTATING_OPERATIONS, m as createMongoPurgePort, n as Repository, o as withTransaction, p as MONGOKIT_CAPABILITIES, r as batchTransaction, s as AggregationBuilder, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-BFBTAMlA.mjs";
3
- import { b as LookupBuilder, x as compileFilterToMongo } from "./update-1Lq9OMD2.mjs";
2
+ import { _ as resetCapabilityProbeCache, a as supportsTransactions, b as transactionResolutionOf, c as ALL_OPERATIONS, d as READ_OPERATIONS, f as operationsByPolicyKey, g as probeMongoCapabilities, h as classifyHelloReply, i as isTransactionUnsupported, l as MUTATING_OPERATIONS, m as capabilitiesForSupport, n as Repository, o as withTransaction, p as MONGOKIT_CAPABILITIES, r as batchTransaction, s as AggregationBuilder, t as HOOK_PRIORITY, u as OP_REGISTRY, v as resolveMongoCapabilities, x as createMongoPurgePort, y as resolveTransactionSupport } from "./Repository-X7U2d0kU.mjs";
3
+ import { b as LookupBuilder, x as compileFilterToMongo } from "./update-DHdXdOk_.mjs";
4
4
  import { n as warn, t as configureLogger } from "./logger-K7dPmu2U.mjs";
5
5
  import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BuByZwKU.mjs";
6
6
  import { t as actions_exports } from "./actions/index.mjs";
7
- import { a as methodRegistryPlugin, c as getNextSequence, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, h as ensureAuditTrailReady, i as multiTenantPlugin, l as prefixedId, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, p as AuditTrailQuery, r as adminBypass, s as dateSequentialId, t as timestampPlugin, u as sequentialId } from "./timestamp.plugin-ennbatTW.mjs";
7
+ import { a as customIdPlugin, c as prefixedId, d as AuditTrailQuery, f as auditTrailPlugin, i as multiTenantPlugin, l as sequentialId, m as auditLogPlugin, n as softDeletePlugin, o as dateSequentialId, p as ensureAuditTrailReady, r as adminBypass, s as getNextSequence, t as timestampPlugin, u as cachePlugin } from "./timestamp.plugin-ChFRcLRJ.mjs";
8
+ import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-DblM7V6j.mjs";
8
9
  import { t as PaginationEngine } from "./PaginationEngine-CczbvCAq.mjs";
9
10
  import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
10
- import { t as createRepository } from "./create-repository-2DMwkYVz.mjs";
11
- import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as immutableStatesPlugin, n as blockIf, o as validationChainPlugin, p as idempotencyStorePlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "./validation-chain.plugin-k9joH2qw.mjs";
11
+ import { t as createRepository } from "./create-repository-DYe5YEie.mjs";
12
+ import { n as defineModel, r as isModelRegistered, t as ModelCollisionError } from "./model-registry-ClKtWiHa.mjs";
13
+ import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "./validation-chain.plugin-BxTl_dYR.mjs";
12
14
  import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-FSQFLpsU.mjs";
13
15
  import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
14
16
  import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
15
17
  import { n as createMemoryCache, t as toPlain } from "./to-plain-vksRrLtc.mjs";
16
- import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-CByt1VhQ.mjs";
18
+ import { n as buildCrudSchemasFromMongooseSchema, t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-DKbnKduN.mjs";
17
19
  import { runChunkedPurge } from "@classytic/repo-core/repository";
18
20
  import { isControlParam } from "@classytic/repo-core/query-parser";
19
21
  //#region src/actions/cascade-references.ts
@@ -145,6 +147,77 @@ async function cascadePurgeReferences(options) {
145
147
  return out;
146
148
  }
147
149
  //#endregion
150
+ //#region src/model-blueprint.ts
151
+ function isProductionRuntime() {
152
+ return process.env.NODE_ENV === "production";
153
+ }
154
+ /**
155
+ * Describe a set of models as a connection-free blueprint. Duplicate spec names are rejected
156
+ * here, at describe time, before any connection is involved.
157
+ */
158
+ function defineModels(spec) {
159
+ const { models, assemble } = spec;
160
+ const names = [];
161
+ const seen = /* @__PURE__ */ new Set();
162
+ for (const m of models) {
163
+ if (seen.has(m.name)) throw new Error(`[mongokit] defineModels: duplicate model spec name '${m.name}'. Each model must be described exactly once.`);
164
+ seen.add(m.name);
165
+ names.push(m.name);
166
+ }
167
+ const modelNames = Object.freeze([...names]);
168
+ return {
169
+ modelNames,
170
+ bind(connection) {
171
+ const map = /* @__PURE__ */ new Map();
172
+ const created = [];
173
+ const replaced = [];
174
+ try {
175
+ for (const s of models) {
176
+ const preExisting = isModelRegistered(s.name, connection);
177
+ if (s.existing.mode === "replace") {
178
+ if (isProductionRuntime()) throw new Error(`[mongokit] model '${s.name}' declares existing policy 'replace', which is forbidden when NODE_ENV=production. Use a separate connection for a second engine; do not clobber a live production model.`);
179
+ if (preExisting) {
180
+ const original = connection.models[s.name];
181
+ replaced.push({
182
+ name: s.name,
183
+ schema: original.schema,
184
+ collection: original.collection.name
185
+ });
186
+ connection.deleteModel(s.name);
187
+ }
188
+ }
189
+ const onExisting = s.existing.mode === "reuse" ? "reuse" : "throw";
190
+ const throwHint = s.existing.mode === "throw" && s.existing.hint ? s.existing.hint : `Registering model set [${modelNames.join(", ")}]; already bound this call: [${created.join(", ") || "none"}]${s.collection ? ` (collection '${s.collection}')` : ""}.`;
191
+ const model = defineModel(s.name, s.schema, {
192
+ onExisting,
193
+ connection,
194
+ throwHint,
195
+ ...s.collection !== void 0 ? { collection: s.collection } : {}
196
+ });
197
+ if (!preExisting) created.push(s.name);
198
+ map.set(s.name, model);
199
+ }
200
+ return assemble(map);
201
+ } catch (err) {
202
+ const rollbackErrors = [];
203
+ for (const name of created) try {
204
+ connection.deleteModel(name);
205
+ } catch (e) {
206
+ rollbackErrors.push(e);
207
+ }
208
+ for (const r of replaced) try {
209
+ if (connection.models[r.name]) connection.deleteModel(r.name);
210
+ connection.model(r.name, r.schema, r.collection);
211
+ } catch (e) {
212
+ rollbackErrors.push(e);
213
+ }
214
+ if (rollbackErrors.length > 0) throw new AggregateError([err, ...rollbackErrors], `[mongokit] defineModels.bind failed AND ${rollbackErrors.length} rollback operation(s) failed — the connection model registry may be inconsistent.`);
215
+ throw err;
216
+ }
217
+ }
218
+ };
219
+ }
220
+ //#endregion
148
221
  //#region src/query/parser/pipeline-sanitizer.ts
149
222
  /**
150
223
  * Sanitize $match configuration to prevent dangerous operators.
@@ -1611,4 +1684,4 @@ function systemContext(extra) {
1611
1684
  */
1612
1685
  var src_default = Repository;
1613
1686
  //#endregion
1614
- export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, OP_REGISTRY, PaginationEngine, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, cascadePurgeReferences, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, src_default as default, elasticSearchPlugin, ensureAuditTrailReady, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isDuplicateKeyError, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, repoOptionsFromCtx, requireField, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, timestampPlugin, toPlain, uniqueField, validationChainPlugin, withTransaction };
1687
+ export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, LookupBuilder, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, ModelCollisionError, OP_REGISTRY, PaginationEngine, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureLogger, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, src_default as default, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, getNextSequence, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resolveMongoCapabilities, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
@@ -0,0 +1,217 @@
1
+ import { Connection } from "mongoose";
2
+ //#region src/kernel-conformance/types.d.ts
3
+ /**
4
+ * Every check the suite can run, in execution order. The ids are STABLE — `skip` is typed
5
+ * against this tuple, so a typo is a compile error rather than a silently-ineffective skip
6
+ * (a skip that skips nothing is the same silent-permissiveness bug class the suite exists
7
+ * to catch).
8
+ */
9
+ declare const KERNEL_CONFORMANCE_CHECKS: readonly ["describe-purity", "blueprint-model-names", "bind-registers-declared-models", "bind-connection-scoped", "bind-no-index-io", "no-autoindex-on-bind", "fresh-schema-per-connection", "double-bind-collision", "transport-not-closed-when-supplied", "owned-transport-closed", "close-idempotent", "no-legacy-surface", "maintenance-fails-loud", "bind-verifies-requirements", "outbox-requires-transactional-save", "optional-modules-register-no-models"];
10
+ type ConformanceCheck = (typeof KERNEL_CONFORMANCE_CHECKS)[number];
11
+ /**
12
+ * Checks that only run when the kernel supplies the input they need. When the input is
13
+ * absent they are reported as NOT EXERCISED — a visible marker test plus a report entry,
14
+ * never a silent pass.
15
+ */
16
+ declare const CONDITIONAL_CHECKS: readonly ["bind-verifies-requirements", "outbox-requires-transactional-save", "optional-modules-register-no-models"];
17
+ /**
18
+ * The two runner functions the suite needs, INJECTED by the consumer.
19
+ *
20
+ * mongokit deliberately does not import `vitest` (not even as an optional peer): the suite
21
+ * would then only work under one runner and would put a test framework in the dependency
22
+ * graph of a package every kernel installs in production. Injection costs the consumer one
23
+ * line — `runner: { describe, it }` — and in exchange the suite runs unmodified under
24
+ * vitest, jest, mocha or `node:test`. Assertions are internal (precise `Error` messages),
25
+ * so no `expect` implementation is required either.
26
+ */
27
+ interface ConformanceRunner {
28
+ describe(name: string, fn: () => void): unknown;
29
+ it(name: string, fn: () => void | Promise<void>): unknown;
30
+ }
31
+ /** The minimum a `defineX(shape)` result must expose to be conformance-testable. */
32
+ interface KernelBlueprintLike {
33
+ readonly id?: string;
34
+ readonly modelNames: readonly string[];
35
+ }
36
+ /** A domain-event-shaped envelope. Structural — the suite never imports primitives. */
37
+ interface ConformanceEvent {
38
+ readonly type: string;
39
+ readonly payload?: unknown;
40
+ readonly meta?: Record<string, unknown>;
41
+ }
42
+ /**
43
+ * Structurally compatible with `@classytic/primitives`' `EventTransport` and arc's
44
+ * `MemoryEventTransport`. Declared here so mongokit stays dependency-free.
45
+ */
46
+ interface EventTransportLike {
47
+ readonly name?: string;
48
+ publish(event: ConformanceEvent): Promise<void> | void;
49
+ publishMany?(events: readonly ConformanceEvent[]): Promise<unknown>;
50
+ subscribe?(pattern: string, handler: (event: ConformanceEvent) => unknown): Promise<() => void> | (() => void);
51
+ close?(): Promise<void> | void;
52
+ }
53
+ /** Collaborators the suite hands to `bind`. The kernel maps them onto its own runtime. */
54
+ interface KernelBindContext {
55
+ /**
56
+ * Present ONLY for the supplied-transport ownership check. When absent the kernel must
57
+ * create (and therefore own) its internal bus.
58
+ */
59
+ readonly transport?: EventTransportLike;
60
+ }
61
+ /** A connection plus its teardown. Return this from `connect` when cleanup is needed. */
62
+ interface ConformanceConnectionHandle {
63
+ readonly connection: Connection;
64
+ teardown?(): Promise<void> | void;
65
+ }
66
+ type ConformanceConnect = () => Promise<Connection | ConformanceConnectionHandle>;
67
+ /**
68
+ * An explicit, REASONED opt-out. The reason is required: an unexplained skip is
69
+ * indistinguishable from an oversight, and this suite exists because oversights were
70
+ * invisible.
71
+ */
72
+ interface ConformanceSkip {
73
+ readonly check: ConformanceCheck;
74
+ readonly reason: string;
75
+ }
76
+ type ConformanceCheckOutcome = 'run' | 'skipped' | 'not-exercised';
77
+ interface ConformanceCheckStatus {
78
+ readonly check: ConformanceCheck;
79
+ readonly outcome: ConformanceCheckOutcome;
80
+ /** Why it was skipped, or which option would exercise a conditional check. */
81
+ readonly reason?: string;
82
+ }
83
+ /** Emitted once per suite, before any test runs. */
84
+ interface KernelConformanceReport {
85
+ readonly kernel: string;
86
+ readonly checks: readonly ConformanceCheckStatus[];
87
+ readonly skipped: readonly ConformanceCheckStatus[];
88
+ readonly notExercised: readonly ConformanceCheckStatus[];
89
+ }
90
+ interface KernelConformanceOptions<TBlueprint extends KernelBlueprintLike, TEngine> {
91
+ /** Kernel name, e.g. `'party'`. Used in test titles and to derive legacy export names. */
92
+ readonly name: string;
93
+ /** `describe`/`it` from the consumer's own test runner. See {@link ConformanceRunner}. */
94
+ readonly runner: ConformanceRunner;
95
+ /**
96
+ * A FACTORY, not a value — `() => defineParty({ ... })`.
97
+ *
98
+ * Purity (§11.1) is only observable if the suite can call `defineX` itself while watching
99
+ * the model registries; a pre-built blueprint has already done whatever it was going to do.
100
+ * The factory also gives every check a pristine blueprint, so one check's bind can never
101
+ * poison another's.
102
+ *
103
+ * Describe the conformance blueprint WITHOUT `forceRecreate` (the collision check needs a
104
+ * real collision) and, when the kernel offers it, with `autoIndex: false`.
105
+ */
106
+ readonly blueprint: () => TBlueprint;
107
+ /**
108
+ * A live or registry-only connection. `async () => mongoose.createConnection()` (never
109
+ * connected) is enough for every check and needs no server — model registration and the
110
+ * index-call spies are registry-level. Return a {@link ConformanceConnectionHandle} when
111
+ * teardown is needed. Called once per check that binds.
112
+ */
113
+ readonly connect: ConformanceConnect;
114
+ /** Bind the blueprint the suite handed you. Map `ctx.transport` onto the kernel runtime. */
115
+ readonly bind: (blueprint: TBlueprint, connection: Connection, ctx: KernelBindContext) => TEngine | Promise<TEngine>;
116
+ /**
117
+ * Build the transport used by `transport-not-closed-when-supplied`. Defaults to the
118
+ * suite's own in-process transport, which satisfies the `EventTransport` contract.
119
+ */
120
+ readonly makeTransport?: () => EventTransportLike;
121
+ /**
122
+ * The exact model set the blueprint must declare. Supplied ⇒ an exact match is REQUIRED;
123
+ * a drift in either direction fails.
124
+ */
125
+ readonly expectedModelNames?: readonly string[];
126
+ /**
127
+ * The kernel's public module namespace (`import * as kernel from '../../src/index.js'`)
128
+ * or a list of its exported names. Required by `no-legacy-surface`.
129
+ */
130
+ readonly moduleExports?: Readonly<Record<string, unknown>> | readonly string[];
131
+ /** Extra export names that must NOT exist (legacy factories this kernel used to ship). */
132
+ readonly forbiddenExportNames?: readonly string[];
133
+ /** The sole construction export. Defaults to `define<Pascal(name)>`, e.g. `defineParty`. */
134
+ readonly constructionExportName?: string;
135
+ /**
136
+ * Find the engine's INTERNAL transport for the owned-transport check. Defaults to the
137
+ * first transport-shaped value among `events`, `transport`, `eventTransport`, `bus`.
138
+ */
139
+ readonly resolveInternalTransport?: (engine: TEngine) => EventTransportLike | undefined;
140
+ /**
141
+ * Direct probe for "was the internally-created bus closed?". Overrides the default
142
+ * subscribe-publish-close-publish observation when a kernel's bus is not reachable.
143
+ */
144
+ readonly internalTransportClosed?: (engine: TEngine) => boolean | Promise<boolean>;
145
+ /**
146
+ * Bind with a deliberately UNMET runtime requirement. Must reject/throw (§11.5).
147
+ * Enables `bind-verifies-requirements`.
148
+ */
149
+ readonly bindWithUnmetRequirement?: (connection: Connection) => unknown | Promise<unknown>;
150
+ /**
151
+ * Bind with an injected `OutboxStore` whose `transactionalSave` is ABSENT or `false` — the
152
+ * exact shape of a hand-rolled host store. The bind must reject/throw, and the error must
153
+ * NAME `transactionalSave`. Enables `outbox-requires-transactional-save`.
154
+ *
155
+ * ```ts
156
+ * bindWithNonTransactionalOutbox: (connection) =>
157
+ * defineX({ … }).bind(connection, { outbox: { save: async () => undefined } as never }),
158
+ * ```
159
+ *
160
+ * ## When to supply it — and when a reasoned `skip` is the RIGHT answer
161
+ *
162
+ * The rule is **"this kernel persists outbox rows that must commit atomically with the state
163
+ * change they describe"**, NOT "this kernel's runtime happens to accept an `outbox`". Of the
164
+ * 32 kernels that thread an outbox through their runtime, only three verified the flag; but
165
+ * the remedy for the other 29 is a JUDGEMENT per kernel, not a sweep.
166
+ *
167
+ * Supply it when a rolled-back write could still emit its event and a downstream consumer
168
+ * would ACT on the ghost — a sale that never committed paying a commission, an access grant
169
+ * that never committed syncing a credential. That is the case `@classytic/access` and
170
+ * `@classytic/referral` gate at boot.
171
+ *
172
+ * SKIP it, with the reason stating so, when the kernel's outbox use is genuinely best-effort:
173
+ * the events are notifications/telemetry that a later reconciliation would correct, or nothing
174
+ * downstream takes an irreversible action on them. Inventing a requirement no code path needs
175
+ * is decoration of the opposite kind — a recorded remedy for `referral` demanded `transactions`
176
+ * on the belief that `convert()` wrote a row AND bumped a counter, when `attributeSale` is one
177
+ * read plus one atomic `getOrCreate`. Read the write paths before deciding.
178
+ *
179
+ * A kernel whose runtime accepts no outbox at all skips with that as the reason.
180
+ */
181
+ readonly bindWithNonTransactionalOutbox?: (connection: Connection) => unknown | Promise<unknown>;
182
+ /**
183
+ * A blueprint describing the kernel with its OPTIONAL modules disabled. Enables
184
+ * `optional-modules-register-no-models` (§11.10).
185
+ */
186
+ readonly minimalBlueprint?: () => TBlueprint;
187
+ /**
188
+ * Explicit, reasoned opt-outs. Unknown or duplicate ids throw at call time. Every skip is
189
+ * printed and registered as a visible marker test.
190
+ */
191
+ readonly skip?: readonly ConformanceSkip[];
192
+ /** Receives the manifest before any test runs. Defaults to a `console` summary. */
193
+ readonly onReport?: (report: KernelConformanceReport) => void;
194
+ }
195
+ //#endregion
196
+ //#region src/kernel-conformance/suite.d.ts
197
+ declare function describeKernelConformance<TBlueprint extends KernelBlueprintLike, TEngine>(opts: KernelConformanceOptions<TBlueprint, TEngine>): void;
198
+ //#endregion
199
+ //#region src/kernel-conformance/transport.d.ts
200
+ /** A minimal, valid domain-event envelope (`type` + `meta.id` is all any bus reads). */
201
+ declare function conformanceEvent(type: string): ConformanceEvent;
202
+ /** An in-process transport good enough to stand in for a host-owned shared bus. */
203
+ declare function createConformanceTransport(name?: string): EventTransportLike;
204
+ interface InstrumentedTransport {
205
+ /** Hand THIS to the kernel. */
206
+ readonly transport: EventTransportLike;
207
+ /** How many times the kernel called `close()` on it. Must stay 0. */
208
+ closeCalls(): number;
209
+ }
210
+ /**
211
+ * Wrap a transport so `close()` calls are counted. The wrapper forwards everything else, so
212
+ * the kernel cannot tell the difference — which is the point: ownership must be decided by
213
+ * "did I create this?", never by inspecting the object.
214
+ */
215
+ declare function instrumentTransport(inner: EventTransportLike): InstrumentedTransport;
216
+ //#endregion
217
+ export { CONDITIONAL_CHECKS, type ConformanceCheck, type ConformanceCheckOutcome, type ConformanceCheckStatus, type ConformanceConnect, type ConformanceConnectionHandle, type ConformanceEvent, type ConformanceRunner, type ConformanceSkip, type EventTransportLike, type InstrumentedTransport, KERNEL_CONFORMANCE_CHECKS, type KernelBindContext, type KernelBlueprintLike, type KernelConformanceOptions, type KernelConformanceReport, conformanceEvent, createConformanceTransport, describeKernelConformance, instrumentTransport };