graphddb 0.7.7 → 0.7.9

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.
@@ -1,4 +1,4 @@
1
- import { C as CdcEmulatorOptions, e as ChangeHandler, U as Unsubscribe, F as FaultSpec, g as ConcurrentRecomputeRef, c as ChangeEvent, E as EventLog, R as ReplayOptions, S as ShardId, V as ViewDefinition, m as EntityMetadata } from './maintenance-view-adapter-C1HaBX4y.js';
1
+ import { C as CdcEmulatorOptions, e as ChangeHandler, U as Unsubscribe, F as FaultSpec, g as ConcurrentRecomputeRef, c as ChangeEvent, E as EventLog, R as ReplayOptions, S as ShardId, V as ViewDefinition, m as EntityMetadata } from './maintenance-view-adapter-BATUh_I8.js';
2
2
 
3
3
  /**
4
4
  * CDC emulator (issue #72). Subscribes to the core write-capture seam
@@ -1,5 +1,5 @@
1
- import { Q as QueryModelContract, x as QueryMethodSpec, y as CommandModelContract, z as CommandMethodSpec, A as ContractSpec, G as QuerySpec, H as CommandSpec, I as TransactionSpec, J as ContextSpec, K as SPEC_VERSION, L as ParamSpec, m as EntityMetadata, N as ParamDescriptor, O as EntityRef, X as ConditionInput, Y as Param, M as ModelStatic, w as DDBModel, Z as DefinitionMap, _ as OperationsDocument, $ as AnyOperationDefinition, a0 as Manifest, a1 as BridgeBundle, a2 as ConditionSpec, a3 as PreparedBody } from './maintenance-view-adapter-C1HaBX4y.js';
2
- import { M as MetadataRegistry } from './registry-DWhq5wiA.js';
1
+ import { Q as QueryModelContract, x as QueryMethodSpec, y as CommandModelContract, z as CommandMethodSpec, A as ContractSpec, G as QuerySpec, H as CommandSpec, I as TransactionSpec, J as ContextSpec, K as SPEC_VERSION, L as ParamSpec, m as EntityMetadata, N as ParamDescriptor, O as EntityRef, X as ConditionInput, Y as Param, M as ModelStatic, w as DDBModel, Z as DefinitionMap, _ as OperationsDocument, $ as AnyOperationDefinition, a0 as Manifest, a1 as BridgeBundle, a2 as ConditionSpec, a3 as PreparedBody } from './maintenance-view-adapter-BATUh_I8.js';
2
+ import { M as MetadataRegistry } from './registry-CXhP4TaE.js';
3
3
 
4
4
  /**
5
5
  * Contract-layer serialization (issue #59, CQRS Contract layer, Epic #57;
@@ -401,8 +401,13 @@ interface TxWriteInstruction {
401
401
  /**
402
402
  * The write / assertion condition (subset). Optional on `put` / `update` /
403
403
  * `delete`; **required** on a `conditionCheck` (the assertion it makes).
404
+ *
405
+ * A tx condition operand may be a `p.*` field reference ({@link
406
+ * TransactionRef}) — the serializer renders it to a `{ $param }` marker — so
407
+ * the recorded leaf type is widened with `TransactionRef` in the tx context
408
+ * (#246), matching what the recorder captures from {@link TxWriteOptions}.
404
409
  */
405
- readonly condition?: ConditionInput;
410
+ readonly condition?: ConditionInput<TransactionRef>;
406
411
  /** Optional declarative guard (skip this item when it does not hold). */
407
412
  readonly when?: WhenComparison;
408
413
  }
@@ -419,7 +424,7 @@ interface TxForEachInstruction {
419
424
  type TxInstruction = TxWriteInstruction | TxForEachInstruction;
420
425
  /** Options accepted by `tx.put/update/delete`. */
421
426
  interface TxWriteOptions {
422
- readonly condition?: ConditionInput;
427
+ readonly condition?: ConditionInput<TransactionRef>;
423
428
  readonly when?: WhenComparison;
424
429
  }
425
430
  /**
@@ -429,7 +434,7 @@ interface TxWriteOptions {
429
434
  * the check entirely when the guard does not hold.
430
435
  */
431
436
  interface TxConditionCheckOptions {
432
- readonly condition: ConditionInput;
437
+ readonly condition: ConditionInput<TransactionRef>;
433
438
  readonly when?: WhenComparison;
434
439
  }
435
440
  /** Options accepted by `tx.forEach`. */
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- export { a as LintResult, L as LintRule, b as Linter, M as MetadataRegistry } from './registry-DWhq5wiA.js';
2
- import { aO as SelectableOf, aP as PrimaryKeyOf, aQ as RequestContext, aR as Middleware, aS as ReadRequestKind, aT as CtxModel, aU as ReadParams, aV as ReadRequestCtx, D as DynamoDBOperation, aW as Item, n as Executor, aX as RetryPolicy, ap as ExecutionPlanSpec, aY as KeyDefinition, aZ as GsiDefinition, a_ as ModelKind, a$ as FieldOptions, b0 as DynamoType, b1 as ProjectionTransform, b2 as MaintainEvent, b3 as MembershipPredicate, b4 as MaintainConsistency, b5 as MaintainUpdateMode, b6 as MembershipPredicateOp, b7 as RelationOptions, b8 as AggregateOptions, b9 as AggregateValue, ba as SelectBuilderSpec, bb as RawCondition, m as EntityMetadata, I as TransactionSpec, a0 as Manifest, bc as RetryOverride, bd as ExecutionPlan, be as FieldMetadata, bf as ResolvedKey, o as ReadExecOptions, p as ExecutorResult, q as BatchGetExecInput, P as PutInput, W as WriteExecOptions, r as WriteResult, s as UpdateInput, t as DeleteInput, u as BatchWriteExecItem, v as BatchExecOptions, T as TransactWriteExecItem, M as ModelStatic, w as DDBModel, bg as Slot, bh as PreparedWriteExecOptions, bi as CommandReturn, bj as ParallelOpResult, a3 as PreparedBody, bk as PreparedStatement, bl as RelationMetadata, aD as TransactionItemSpec, bm as MaintainEffect, V as ViewDefinition, Y as Param, N as ParamDescriptor, Z as DefinitionMap, bn as OperationDefinition, bo as WriteDefinitionOptions, bp as PartialQueryKeyOf, bq as StrictSelectSpec, br as ReadDefinitionOptions, bs as EntityInput, bt as UniqueQueryKeyOf } from './maintenance-view-adapter-C1HaBX4y.js';
3
- export { bu as AggregateMetadata, $ as AnyOperationDefinition, bv as BatchDeleteRequest, bw as BatchGetOptions, bx as BatchGetRequest, by as BatchGetResult, bz as BatchPutRequest, B as BatchResult, bA as BatchWriteRequest, a1 as BridgeBundle, bB as CONTRACT_RANGE_FANOUT_CONCURRENCY, C as CdcEmulatorOptions, a as CdcMode, bC as CdcModelRegistry, bD as CdcSubscribeHandlers, bE as Change, b as ChangeBatch, c as ChangeEvent, d as ChangeEventName, e as ChangeHandler, f as ClockMode, bF as CollectionEffect, bG as CollectionOptions, bH as Column, bI as ColumnMap, a4 as CommandContractMethodSpec, bJ as CommandInputShape, bK as CommandMethod, z as CommandMethodSpec, y as CommandModelContract, bL as CommandPlan, a5 as CommandResolutionTarget, bM as CommandResultKind, bN as CommandSelectShape, H as CommandSpec, a6 as CompiledFragment, a8 as ComposeSpec, g as ConcurrentRecomputeRef, bO as CondSlot, bP as ConditionCheckInput, X as ConditionInput, a2 as ConditionSpec, bQ as Connection, J as ContextSpec, bR as ContractCallSignature, aa as ContractCardinality, bS as ContractCommandParams, ab as ContractCommandResult, bT as ContractComposeNode, bU as ContractFromRef, ac as ContractInputArity, bV as ContractItem, bW as ContractKeyFieldRef, bX as ContractKeyInput, bY as ContractKeyRef, ad as ContractKeySpec, ae as ContractKind, bZ as ContractMethodOp, b_ as ContractParamRef, b$ as ContractQueryParams, af as ContractResolution, A as ContractSpec, c0 as CounterAggregate, c1 as CounterEffect, c2 as CtxBase, c3 as DEFAULT_MAX_ATTEMPTS, c4 as DEFAULT_RETRY_POLICY, c5 as DeleteOptions, c6 as DeriveEffect, ah as DerivedEdgeWrite, an as DerivedUpdate, c7 as DescriptorBinding, c8 as ENTITY_WRITES_MARKER, c9 as EdgeEffect, ca as EffectPath, cb as EmbeddedMetadata, cc as EmitEffect, O as EntityRef, cd as EntityWritesDefinition, ce as EntityWritesShape, E as EventLog, cf as ExecutableCommandContract, cg as ExecutableQueryContract, F as FaultSpec, ch as FilterInput, aq as FilterSpec, ci as FragmentInput, cj as GsiDefinitionMarker, ck as GsiOptions, cl as IdempotencyEffect, cm as InProcessWriteDescriptor, cn as InlineSnapshotSpec, co as InputArity, cp as KeyDefinitionMarker, cq as KeySegment, cr as KeySlot, cs as KeyStructure, ct as KeyedResult, cu as LIFECYCLE_CONTRACT_MARKER, cv as LifecycleContract, cw as LifecycleEffects, cx as LiteralParam, cy as MaintainItem, cz as MaintainTrigger, cA as MaintenanceGraph, as as ManifestEntity, at as ManifestField, au as ManifestFieldType, av as ManifestGsi, aw as ManifestKey, ax as ManifestRelation, ay as ManifestTable, cB as MembershipEffect, cC as ModelRef, cD as MutateMode, cE as MutateOptions, cF as MutateParallelResult, cG as MutateTransactionResult, cH as MutationBody, cI as MutationDescriptorMap, cJ as MutationFragment, cK as MutationInputProxy, cL as MutationInputRef, cM as MutationIntent, cN as NumberParam, cO as OperationKind, az as OperationSpec, _ as OperationsDocument, cP as PREPARE_CACHE_MAX, cQ as ParamKind, L as ParamSpec, cR as ParamStructure, cS as PersistCtx, cT as PersistOrigin, cU as PlannedCommandMethod, cV as PreparedInputProxy, cW as PreparedParamRef, cX as PreparedReadExecOptions, cY as PreparedReadRoute, cZ as PreparedReadStatement, c_ as PreparedWriteRoute, c$ as PreparedWriteStatement, d0 as ProjectionMap, d1 as ProjectionTransformOp, d2 as PutOptions, aA as QueryContractMethodSpec, d3 as QueryEnvelopeResult, d4 as QueryKeyOf, d5 as QueryMethod, x as QueryMethodSpec, Q as QueryModelContract, d6 as QueryResult, G as QuerySpec, aB as RangeConditionSpec, d7 as ReadEnvelope, d8 as ReadOpCtx, d9 as ReadOpKind, aC as ReadOperationType, da as ReadRouteDescriptor, db as ReadRouteOptions, dc as ReadRouteResult, dd as RecordedCompose, de as RelationBuilder, df as RelationConsistency, dg as RelationLimitOptions, dh as RelationPattern, di as RelationProjection, dj as RelationReadOptions, dk as RelationSelect, dl as RelationSpec, dm as RelationUpdateMode, dn as RelationWriteOptions, R as ReplayOptions, dp as RequiresEffect, dq as Resolution, dr as RetryInfo, ds as RetryOperationKind, K as SPEC_VERSION, dt as SegmentSpec, du as SegmentedKey, dv as SelectBuilder, dw as SelectOf, S as ShardId, dx as SnapshotEffect, h as StartingPosition, i as StreamViewType, dy as StringParam, j as SubscribeHandler, k as SubscribeHandlers, dz as TransactionContext, aE as TransactionItemType, dA as UniqueEffect, dB as Updatable, dC as UpdateOptions, dD as ViewSourceSlice, aF as WhenSpec, dE as WriteCtx, dF as WriteDescriptor, dG as WriteEnvelope, dH as WriteInput, dI as WriteKind, dJ as WriteLifecyclePhase, dK as WriteMiddleware, aG as WriteOperationType, dL as WriteRecorder, dM as WriteResultProjection, dN as attachModelClass, dO as buildDeleteInput, dP as buildMaintenanceGraph, dQ as buildPutInput, l as buildSubscribeHandler, dR as buildUpdateInput, dS as collectViewDefinitions, aI as compileFragment, aJ as compileMutationPlan, aK as compileSingleFragmentPlan, dT as cond, dU as contractOfMethodSpec, dV as definePlan, dW as entityWrites, dX as executeBatchGet, dY as executeBatchWrite, dZ as executeCommandMethod, d_ as executeDelete, d$ as executeKeyedBatchGet, e0 as executePut, e1 as executeQueryMethod, e2 as executeRangeFanout, e3 as executeTransaction, e4 as executeUpdate, e5 as from, e6 as getEntityWrites, e7 as gsi, e8 as identity, e9 as isColumn, ea as isCommandModelContract, eb as isCommandPlan, ec as isContractComposeNode, ed as isContractFromRef, ee as isContractKeyFieldRef, ef as isContractKeyRef, eg as isContractParamRef, eh as isEntityWritesDefinition, ei as isKeySegment, ej as isLifecycleContract, ek as isMaintainTrigger, el as isMutationFragment, em as isMutationInputRef, en as isParam, eo as isPlannedCommandMethod, ep as isPreparedParamRef, eq as isQueryModelContract, er as isRetryableError, es as isRetryableTransactionCancellation, et as k, eu as key, ev as lifecyclePhaseForIntent, ew as maintainTrigger, ex as mintContractKeyFieldRef, ey as mintContractParamRef, ez as mutation, eA as param, eB as prepare, eC as preview, eD as publicCommandModel, eE as publicQueryModel, eF as query, aM as resolveLifecycle, eG as wholeKeysSentinel } from './maintenance-view-adapter-C1HaBX4y.js';
1
+ export { a as LintResult, L as LintRule, b as Linter, M as MetadataRegistry } from './registry-CXhP4TaE.js';
2
+ import { aO as SelectableOf, aP as PrimaryKeyOf, aQ as RequestContext, aR as Middleware, aS as ReadRequestKind, aT as CtxModel, aU as ReadParams, aV as ReadRequestCtx, D as DynamoDBOperation, aW as Item, n as Executor, aX as RetryPolicy, ap as ExecutionPlanSpec, aY as RetryOverride, aZ as KeyDefinition, a_ as GsiDefinition, a$ as ModelKind, b0 as FieldOptions, b1 as DynamoType, b2 as ProjectionTransform, b3 as MaintainEvent, b4 as MembershipPredicate, b5 as MaintainConsistency, b6 as MaintainUpdateMode, b7 as MembershipPredicateOp, b8 as RelationOptions, b9 as AggregateOptions, ba as AggregateValue, bb as SelectBuilderSpec, bc as RawCondition, m as EntityMetadata, I as TransactionSpec, a0 as Manifest, bd as ExecutionPlan, be as FieldMetadata, bf as ResolvedKey, o as ReadExecOptions, p as ExecutorResult, q as BatchGetExecInput, P as PutInput, W as WriteExecOptions, r as WriteResult, s as UpdateInput, t as DeleteInput, u as BatchWriteExecItem, v as BatchExecOptions, T as TransactWriteExecItem, M as ModelStatic, w as DDBModel, bg as Slot, bh as PreparedWriteExecOptions, bi as CommandReturn, bj as ParallelOpResult, a3 as PreparedBody, bk as PreparedStatement, bl as RelationMetadata, aD as TransactionItemSpec, bm as MaintainEffect, V as ViewDefinition, Y as Param, N as ParamDescriptor, Z as DefinitionMap, bn as OperationDefinition, bo as WriteDefinitionOptions, bp as PartialQueryKeyOf, bq as StrictSelectSpec, br as ReadDefinitionOptions, bs as EntityInput, bt as UniqueQueryKeyOf } from './maintenance-view-adapter-BATUh_I8.js';
3
+ export { bu as AggregateMetadata, $ as AnyOperationDefinition, bv as BatchDeleteRequest, bw as BatchGetOptions, bx as BatchGetRequest, by as BatchGetResult, bz as BatchPutRequest, B as BatchResult, bA as BatchWriteRequest, a1 as BridgeBundle, bB as CONTRACT_RANGE_FANOUT_CONCURRENCY, C as CdcEmulatorOptions, a as CdcMode, bC as CdcModelRegistry, bD as CdcSubscribeHandlers, bE as Change, b as ChangeBatch, c as ChangeEvent, d as ChangeEventName, e as ChangeHandler, f as ClockMode, bF as CollectionEffect, bG as CollectionOptions, bH as Column, bI as ColumnMap, a4 as CommandContractMethodSpec, bJ as CommandInputShape, bK as CommandMethod, z as CommandMethodSpec, y as CommandModelContract, bL as CommandPlan, a5 as CommandResolutionTarget, bM as CommandResultKind, bN as CommandSelectShape, H as CommandSpec, a6 as CompiledFragment, a8 as ComposeSpec, g as ConcurrentRecomputeRef, bO as CondSlot, bP as ConditionCheckInput, X as ConditionInput, a2 as ConditionSpec, bQ as Connection, J as ContextSpec, bR as ContractCallSignature, aa as ContractCardinality, bS as ContractCommandParams, ab as ContractCommandResult, bT as ContractComposeNode, bU as ContractFromRef, ac as ContractInputArity, bV as ContractItem, bW as ContractKeyFieldRef, bX as ContractKeyInput, bY as ContractKeyRef, ad as ContractKeySpec, ae as ContractKind, bZ as ContractMethodOp, b_ as ContractParamRef, b$ as ContractQueryParams, af as ContractResolution, A as ContractSpec, c0 as CounterAggregate, c1 as CounterEffect, c2 as CtxBase, c3 as DEFAULT_MAX_ATTEMPTS, c4 as DEFAULT_RETRY_POLICY, c5 as DeleteOptions, c6 as DeriveEffect, ah as DerivedEdgeWrite, an as DerivedUpdate, c7 as DescriptorBinding, c8 as ENTITY_WRITES_MARKER, c9 as EdgeEffect, ca as EffectPath, cb as EmbeddedMetadata, cc as EmitEffect, O as EntityRef, cd as EntityWritesDefinition, ce as EntityWritesShape, E as EventLog, cf as ExecutableCommandContract, cg as ExecutableQueryContract, F as FaultSpec, ch as FilterInput, aq as FilterSpec, ci as FragmentCondition, cj as FragmentConditionOperatorObject, ck as FragmentInput, cl as GsiDefinitionMarker, cm as GsiOptions, cn as IdempotencyEffect, co as InProcessWriteDescriptor, cp as InlineSnapshotSpec, cq as InputArity, cr as KeyDefinitionMarker, cs as KeySegment, ct as KeySlot, cu as KeyStructure, cv as KeyedResult, cw as LIFECYCLE_CONTRACT_MARKER, cx as LifecycleContract, cy as LifecycleEffects, cz as LiteralParam, cA as MaintainItem, cB as MaintainTrigger, cC as MaintenanceGraph, as as ManifestEntity, at as ManifestField, au as ManifestFieldType, av as ManifestGsi, aw as ManifestKey, ax as ManifestRelation, ay as ManifestTable, cD as MembershipEffect, cE as ModelRef, cF as MutateMode, cG as MutateOptions, cH as MutateParallelResult, cI as MutateTransactionResult, cJ as MutationBody, cK as MutationDescriptorMap, cL as MutationFragment, cM as MutationInputProxy, cN as MutationInputRef, cO as MutationIntent, cP as NumberParam, cQ as OperationKind, az as OperationSpec, _ as OperationsDocument, cR as PREPARE_CACHE_MAX, cS as ParamKind, L as ParamSpec, cT as ParamStructure, cU as PersistCtx, cV as PersistOrigin, cW as PlannedCommandMethod, cX as PreparedInputProxy, cY as PreparedParamRef, cZ as PreparedReadExecOptions, c_ as PreparedReadRoute, c$ as PreparedReadStatement, d0 as PreparedWriteRoute, d1 as PreparedWriteStatement, d2 as ProjectionMap, d3 as ProjectionTransformOp, d4 as PutOptions, aA as QueryContractMethodSpec, d5 as QueryEnvelopeResult, d6 as QueryKeyOf, d7 as QueryMethod, x as QueryMethodSpec, Q as QueryModelContract, d8 as QueryResult, G as QuerySpec, aB as RangeConditionSpec, d9 as ReadEnvelope, da as ReadOpCtx, db as ReadOpKind, aC as ReadOperationType, dc as ReadRouteDescriptor, dd as ReadRouteOptions, de as ReadRouteResult, df as RecordedCompose, dg as RelationBuilder, dh as RelationConsistency, di as RelationLimitOptions, dj as RelationPattern, dk as RelationProjection, dl as RelationReadOptions, dm as RelationSelect, dn as RelationSpec, dp as RelationUpdateMode, dq as RelationWriteOptions, R as ReplayOptions, dr as RequiresEffect, ds as Resolution, dt as RetryInfo, du as RetryOperationKind, K as SPEC_VERSION, dv as SegmentSpec, dw as SegmentedKey, dx as SelectBuilder, dy as SelectOf, S as ShardId, dz as SnapshotEffect, h as StartingPosition, i as StreamViewType, dA as StringParam, j as SubscribeHandler, k as SubscribeHandlers, dB as TransactionContext, aE as TransactionItemType, dC as UniqueEffect, dD as Updatable, dE as UpdateOptions, dF as ViewSourceSlice, aF as WhenSpec, dG as WriteCtx, dH as WriteDescriptor, dI as WriteEnvelope, dJ as WriteInput, dK as WriteKind, dL as WriteLifecyclePhase, dM as WriteMiddleware, aG as WriteOperationType, dN as WriteRecorder, dO as WriteResultProjection, dP as attachModelClass, dQ as buildDeleteInput, dR as buildMaintenanceGraph, dS as buildPutInput, l as buildSubscribeHandler, dT as buildUpdateInput, dU as collectViewDefinitions, aI as compileFragment, aJ as compileMutationPlan, aK as compileSingleFragmentPlan, dV as cond, dW as contractOfMethodSpec, dX as definePlan, dY as entityWrites, dZ as executeBatchGet, d_ as executeBatchWrite, d$ as executeCommandMethod, e0 as executeDelete, e1 as executeKeyedBatchGet, e2 as executePut, e3 as executeQueryMethod, e4 as executeRangeFanout, e5 as executeTransaction, e6 as executeUpdate, e7 as from, e8 as getEntityWrites, e9 as gsi, ea as identity, eb as isColumn, ec as isCommandModelContract, ed as isCommandPlan, ee as isContractComposeNode, ef as isContractFromRef, eg as isContractKeyFieldRef, eh as isContractKeyRef, ei as isContractParamRef, ej as isEntityWritesDefinition, ek as isKeySegment, el as isLifecycleContract, em as isMaintainTrigger, en as isMutationFragment, eo as isMutationInputRef, ep as isParam, eq as isPlannedCommandMethod, er as isPreparedParamRef, es as isQueryModelContract, et as isRetryableError, eu as isRetryableTransactionCancellation, ev as k, ew as key, ex as lifecyclePhaseForIntent, ey as maintainTrigger, ez as mintContractKeyFieldRef, eA as mintContractParamRef, eB as mutation, eC as param, eD as prepare, eE as preview, eF as publicCommandModel, eG as publicQueryModel, eH as query, aM as resolveLifecycle, eI as wholeKeysSentinel } from './maintenance-view-adapter-BATUh_I8.js';
4
4
  import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
5
5
  import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
6
- export { C as CdcEmulator, M as MAINT_OUTBOX_PK_PREFIX, a as MaintenanceDrain, b as MaintenanceDrainOptions, c as createCdcEmulator, d as createMaintenanceDrain, e as createMaintenanceDrainHandler, p as parseChange } from './from-change-D2zFApzb.js';
7
- import { P as PreparedWriteOpSpec, a as PreparedPlanDocument } from './index-BnTZQ_IG.js';
8
- export { A as AnyModelContract, B as BuiltContracts, C as ContextOwnership, b as ContextOwnershipMap, c as ContractBoundaryViolation, d as ContractInputs, e as ContractMap, f as ContractN1Violation, g as PreparedBindSpec, h as PreparedPlanSpec, i as PreparedReadRouteSpec, T as TransactionDefinition, j as TransactionParamShape, k as TransactionRef, l as TxConditionCheckOptions, m as TxForEachInstruction, n as TxForEachOptions, o as TxInstruction, p as TxRecorder, q as TxWriteInstruction, r as TxWriteOptions, W as WhenComparison, s as assertBundleSerializable, t as assertContractBoundaries, u as assertContractN1Safe, v as assertJsonSerializable, w as assertSupportedCondition, x as buildBridgeBundle, y as buildContexts, z as buildContracts, D as buildManifest, E as buildOperations, F as buildQuerySpec, G as buildTransactionSpec, H as buildTransactions, I as collectContractBoundaryViolations, J as collectContractN1Violations, K as defineTransaction, L as defineTransactions, M as isTransactionRef, N as when } from './index-BnTZQ_IG.js';
9
- export { c as createDefaultLinter, g as gsiAmbiguityRule, m as missingGsiRule, n as noScanRule, q as queryBoundaryRule, r as relationDepthRule, a as requireLimitRule } from './relation-depth-BnqfKkZB.js';
6
+ export { C as CdcEmulator, M as MAINT_OUTBOX_PK_PREFIX, a as MaintenanceDrain, b as MaintenanceDrainOptions, c as createCdcEmulator, d as createMaintenanceDrain, e as createMaintenanceDrainHandler, p as parseChange } from './from-change-DanwjE5b.js';
7
+ import { P as PreparedWriteOpSpec, a as PreparedPlanDocument } from './index-CtPJSMrc.js';
8
+ export { A as AnyModelContract, B as BuiltContracts, C as ContextOwnership, b as ContextOwnershipMap, c as ContractBoundaryViolation, d as ContractInputs, e as ContractMap, f as ContractN1Violation, g as PreparedBindSpec, h as PreparedPlanSpec, i as PreparedReadRouteSpec, T as TransactionDefinition, j as TransactionParamShape, k as TransactionRef, l as TxConditionCheckOptions, m as TxForEachInstruction, n as TxForEachOptions, o as TxInstruction, p as TxRecorder, q as TxWriteInstruction, r as TxWriteOptions, W as WhenComparison, s as assertBundleSerializable, t as assertContractBoundaries, u as assertContractN1Safe, v as assertJsonSerializable, w as assertSupportedCondition, x as buildBridgeBundle, y as buildContexts, z as buildContracts, D as buildManifest, E as buildOperations, F as buildQuerySpec, G as buildTransactionSpec, H as buildTransactions, I as collectContractBoundaryViolations, J as collectContractN1Violations, K as defineTransaction, L as defineTransactions, M as isTransactionRef, N as when } from './index-CtPJSMrc.js';
9
+ export { c as createDefaultLinter, g as gsiAmbiguityRule, m as missingGsiRule, n as noScanRule, q as queryBoundaryRule, r as relationDepthRule, a as requireLimitRule } from './relation-depth-Dg3yhl7S.js';
10
10
 
11
11
  /**
12
12
  * Query options with conditional `consistentRead` availability.
@@ -318,6 +318,113 @@ interface RelationExecutionPlan {
318
318
  readonly resultPaths: readonly string[];
319
319
  }
320
320
 
321
+ interface QueryOptions {
322
+ consistentRead?: boolean;
323
+ maxDepth?: number;
324
+ /**
325
+ * Per-call throttle / transient-error retry override (issue #111), applied to the
326
+ * parent read AND to every relation-fan-out send under it. A {@link RetryPolicy}
327
+ * replaces the global policy for this call; `false` disables retry. Omit to use
328
+ * the configured (or built-in default) policy.
329
+ */
330
+ retry?: RetryOverride;
331
+ /**
332
+ * When `true`, the returned item carries its resolved base-table key as a
333
+ * non-enumerable Symbol property so it can be passed back to `update()`
334
+ * directly — even for a partial `select` or a GSI-based query. Host-side
335
+ * runtime behaviour only; not part of the serialized query.
336
+ */
337
+ updatable?: boolean;
338
+ /**
339
+ * Opt-in class / domain-object hydration (issue #53). When provided, the
340
+ * factory is applied as the **final after-fetch step** to the fully-built
341
+ * plain object (after projection, relation resolution, and any `updatable`
342
+ * hidden-key attachment) and its return value is what the read resolves to —
343
+ * the return type propagates from the factory (see `ModelStatic.query`).
344
+ *
345
+ * Semantics:
346
+ * - applied to a **present** item only; a `null` read stays `null` and the
347
+ * factory is NOT invoked, so the factory need not be null-tolerant;
348
+ * - a throw from the factory propagates verbatim as the read's rejection
349
+ * (the fetch already succeeded; the failure is purely in caller code);
350
+ * - synchronous by design — an async transform is a caller-side `await` on
351
+ * the plain result, intentionally out of scope here.
352
+ *
353
+ * Host-side runtime behaviour ONLY: like `updatable` / `consistentRead`, the
354
+ * factory is a host-language closure that is NEVER serialized into the SSoT /
355
+ * `operations.json`, so it does not impede the multi-language bridge (#48).
356
+ * "What to fetch" stays declarative; "what object to load it onto" is host-side.
357
+ */
358
+ hydrate?: (raw: Record<string, unknown> | null) => unknown;
359
+ /**
360
+ * Host-injected per-call read context (issue #50 / #138) — exposed to every
361
+ * read hook (R1–R5) as `ctx.context`, and threaded UNCHANGED to every relation
362
+ * fan-out op so a hook (e.g. a tenant-scope R2 filter) applies across the root
363
+ * read AND the fan-out fetches. A host-language value, NEVER serialized into the
364
+ * SSoT / `operations.json` (the bridge #48 is unaffected). Absent ⇒ `{}`.
365
+ */
366
+ context?: RequestContext;
367
+ }
368
+ declare function executeQuery(modelClass: Function, key: Record<string, unknown>, selectSpec: Record<string, unknown>, options?: QueryOptions): Promise<Record<string, unknown> | null>;
369
+
370
+ interface ListInput {
371
+ limit?: number;
372
+ after?: string;
373
+ order?: 'ASC' | 'DESC';
374
+ /** Declarative server-side DynamoDB FilterExpression input. */
375
+ filter?: Record<string, unknown>;
376
+ /**
377
+ * When `true`, each returned item carries its resolved base-table key as a
378
+ * non-enumerable Symbol property so it can be passed back to `update()`
379
+ * directly. Host-side runtime behaviour only; not part of the serialized
380
+ * query.
381
+ */
382
+ updatable?: boolean;
383
+ /**
384
+ * Per-call throttle / transient-error retry override (issue #111). A
385
+ * {@link RetryPolicy} replaces the global policy for this read; `false` disables
386
+ * retry. Omit to use the configured (or built-in default) policy.
387
+ */
388
+ retry?: RetryOverride;
389
+ /**
390
+ * Host-injected per-call read context (issue #50 / #138) — exposed to every
391
+ * read hook as `ctx.context`. Used only when this `list` is the read ENTRY
392
+ * point (the public `DDBModel.list` / a `list` envelope route): a fresh
393
+ * {@link MiddlewareRuntime} is built from it. Ignored when a relation fan-out
394
+ * threads an already-built {@link mw} (the runtime then carries the root read's
395
+ * context). Absent ⇒ `{}`.
396
+ */
397
+ context?: RequestContext;
398
+ /**
399
+ * @internal The per-read middleware runtime, threaded UNCHANGED from a relation
400
+ * fan-out (issue #138) so the hasMany Query's op-level hooks (R2/R3/R5) fire
401
+ * with the root read's context + the fan-out's {@link relationPath}. When absent
402
+ * at the entry point, one is built from {@link context}.
403
+ */
404
+ mw?: MiddlewareRuntime;
405
+ /**
406
+ * @internal The relation path to THIS list read — `[]` (or absent) for a
407
+ * top-level `list`; the fan-out leg (e.g. `['orders']`) for a hasMany Query.
408
+ * Populates the op-level ctx's `relationPath` (issue #138).
409
+ */
410
+ relationPath?: readonly string[];
411
+ }
412
+ /**
413
+ * Public list result returned by `DDBModel.list()`. Contains exactly the
414
+ * `items` and `cursor` keys — no `rawItems` leak.
415
+ */
416
+ interface ListResult {
417
+ items: Record<string, unknown>[];
418
+ cursor: string | null;
419
+ }
420
+ /**
421
+ * Public list execution backing `DDBModel.list()`. Delegates to
422
+ * {@link executeListInternal} and constructs a fresh result object exposing
423
+ * only `{ items, cursor }`, so internal-only fields such as `rawItems` never
424
+ * cross the public API boundary (no reliance on `as` type narrowing).
425
+ */
426
+ declare function executeList(modelClass: Function, key: Record<string, unknown>, selectSpec: Record<string, unknown>, options?: ListInput): Promise<ListResult>;
427
+
321
428
  declare function derivePrefix(customPrefix: string | undefined, className: string | undefined): string;
322
429
 
323
430
  /**
@@ -1062,113 +1169,6 @@ declare function expandTransaction(spec: TransactionSpec, manifest: Manifest, pa
1062
1169
  */
1063
1170
  declare function executeDeclarativeTransaction(spec: TransactionSpec, manifest: Manifest, params: Record<string, unknown>): Promise<void>;
1064
1171
 
1065
- interface QueryOptions {
1066
- consistentRead?: boolean;
1067
- maxDepth?: number;
1068
- /**
1069
- * Per-call throttle / transient-error retry override (issue #111), applied to the
1070
- * parent read AND to every relation-fan-out send under it. A {@link RetryPolicy}
1071
- * replaces the global policy for this call; `false` disables retry. Omit to use
1072
- * the configured (or built-in default) policy.
1073
- */
1074
- retry?: RetryOverride;
1075
- /**
1076
- * When `true`, the returned item carries its resolved base-table key as a
1077
- * non-enumerable Symbol property so it can be passed back to `update()`
1078
- * directly — even for a partial `select` or a GSI-based query. Host-side
1079
- * runtime behaviour only; not part of the serialized query.
1080
- */
1081
- updatable?: boolean;
1082
- /**
1083
- * Opt-in class / domain-object hydration (issue #53). When provided, the
1084
- * factory is applied as the **final after-fetch step** to the fully-built
1085
- * plain object (after projection, relation resolution, and any `updatable`
1086
- * hidden-key attachment) and its return value is what the read resolves to —
1087
- * the return type propagates from the factory (see `ModelStatic.query`).
1088
- *
1089
- * Semantics:
1090
- * - applied to a **present** item only; a `null` read stays `null` and the
1091
- * factory is NOT invoked, so the factory need not be null-tolerant;
1092
- * - a throw from the factory propagates verbatim as the read's rejection
1093
- * (the fetch already succeeded; the failure is purely in caller code);
1094
- * - synchronous by design — an async transform is a caller-side `await` on
1095
- * the plain result, intentionally out of scope here.
1096
- *
1097
- * Host-side runtime behaviour ONLY: like `updatable` / `consistentRead`, the
1098
- * factory is a host-language closure that is NEVER serialized into the SSoT /
1099
- * `operations.json`, so it does not impede the multi-language bridge (#48).
1100
- * "What to fetch" stays declarative; "what object to load it onto" is host-side.
1101
- */
1102
- hydrate?: (raw: Record<string, unknown> | null) => unknown;
1103
- /**
1104
- * Host-injected per-call read context (issue #50 / #138) — exposed to every
1105
- * read hook (R1–R5) as `ctx.context`, and threaded UNCHANGED to every relation
1106
- * fan-out op so a hook (e.g. a tenant-scope R2 filter) applies across the root
1107
- * read AND the fan-out fetches. A host-language value, NEVER serialized into the
1108
- * SSoT / `operations.json` (the bridge #48 is unaffected). Absent ⇒ `{}`.
1109
- */
1110
- context?: RequestContext;
1111
- }
1112
- declare function executeQuery(modelClass: Function, key: Record<string, unknown>, selectSpec: Record<string, unknown>, options?: QueryOptions): Promise<Record<string, unknown> | null>;
1113
-
1114
- interface ListInput {
1115
- limit?: number;
1116
- after?: string;
1117
- order?: 'ASC' | 'DESC';
1118
- /** Declarative server-side DynamoDB FilterExpression input. */
1119
- filter?: Record<string, unknown>;
1120
- /**
1121
- * When `true`, each returned item carries its resolved base-table key as a
1122
- * non-enumerable Symbol property so it can be passed back to `update()`
1123
- * directly. Host-side runtime behaviour only; not part of the serialized
1124
- * query.
1125
- */
1126
- updatable?: boolean;
1127
- /**
1128
- * Per-call throttle / transient-error retry override (issue #111). A
1129
- * {@link RetryPolicy} replaces the global policy for this read; `false` disables
1130
- * retry. Omit to use the configured (or built-in default) policy.
1131
- */
1132
- retry?: RetryOverride;
1133
- /**
1134
- * Host-injected per-call read context (issue #50 / #138) — exposed to every
1135
- * read hook as `ctx.context`. Used only when this `list` is the read ENTRY
1136
- * point (the public `DDBModel.list` / a `list` envelope route): a fresh
1137
- * {@link MiddlewareRuntime} is built from it. Ignored when a relation fan-out
1138
- * threads an already-built {@link mw} (the runtime then carries the root read's
1139
- * context). Absent ⇒ `{}`.
1140
- */
1141
- context?: RequestContext;
1142
- /**
1143
- * @internal The per-read middleware runtime, threaded UNCHANGED from a relation
1144
- * fan-out (issue #138) so the hasMany Query's op-level hooks (R2/R3/R5) fire
1145
- * with the root read's context + the fan-out's {@link relationPath}. When absent
1146
- * at the entry point, one is built from {@link context}.
1147
- */
1148
- mw?: MiddlewareRuntime;
1149
- /**
1150
- * @internal The relation path to THIS list read — `[]` (or absent) for a
1151
- * top-level `list`; the fan-out leg (e.g. `['orders']`) for a hasMany Query.
1152
- * Populates the op-level ctx's `relationPath` (issue #138).
1153
- */
1154
- relationPath?: readonly string[];
1155
- }
1156
- /**
1157
- * Public list result returned by `DDBModel.list()`. Contains exactly the
1158
- * `items` and `cursor` keys — no `rawItems` leak.
1159
- */
1160
- interface ListResult {
1161
- items: Record<string, unknown>[];
1162
- cursor: string | null;
1163
- }
1164
- /**
1165
- * Public list execution backing `DDBModel.list()`. Delegates to
1166
- * {@link executeListInternal} and constructs a fresh result object exposing
1167
- * only `{ items, cursor }`, so internal-only fields such as `rawItems` never
1168
- * cross the public API boundary (no reliance on `as` type narrowing).
1169
- */
1170
- declare function executeList(modelClass: Function, key: Record<string, unknown>, selectSpec: Record<string, unknown>, options?: ListInput): Promise<ListResult>;
1171
-
1172
1172
  interface ExplainInput {
1173
1173
  select?: Record<string, unknown>;
1174
1174
  limit?: number;
@@ -1375,10 +1375,20 @@ interface PerKeyCursorEnvelope {
1375
1375
  /**
1376
1376
  * Canonical, cross-runtime-stable string identity of a contract key. Object
1377
1377
  * fields are sorted by name so `{ a, b }` and `{ b, a }` serialize identically;
1378
- * values are emitted via `JSON.stringify`, matching the Python runtime's
1378
+ * values are emitted as compact JSON, matching the Python runtime's
1379
1379
  * `serialize_contract_key` (sorted items, compact separators). This is the
1380
1380
  * identity used to key a batch result map and to bind a per-key cursor.
1381
1381
  *
1382
+ * **#253 adapter (behavior-contracts)**: this is the shared COMMON
1383
+ * `canonicalValue` primitive (runtime-boundary.md §2.1 →
1384
+ * canonical-serialization.md §2: key identity = top-level key sort + compact
1385
+ * JSON), the same delegation the Python / Rust / Go runtimes adopted in #255.
1386
+ * graphddb's former field-sorted `JSON.stringify` is deleted; plain JS key
1387
+ * values cross the boundary through {@link toSharedValue} (integral `number` →
1388
+ * shared int, `Date` → ISO string, `undefined` fields dropped — the exact
1389
+ * `JSON.stringify` semantics the old implementation had). Byte identity of the
1390
+ * output is locked by the frozen #253 conformance golden.
1391
+ *
1382
1392
  * @param key A plain contract-key object (e.g. `{ categoryId: 'tech' }`).
1383
1393
  * @returns A deterministic JSON string, e.g. `{"categoryId":"tech"}`.
1384
1394
  */
@@ -2011,6 +2021,8 @@ declare function createMaintenanceRebuilder(opts?: MaintenanceRebuildOptions): M
2011
2021
 
2012
2022
  /** Scalar leaf types that may be replaced by a {@link Param} placeholder. */
2013
2023
  type Replaceable = string | number;
2024
+ /** `null` / `undefined` — peeled off an optional leaf before the scalar test. */
2025
+ type Nullish = null | undefined;
2014
2026
  /**
2015
2027
  * Relaxes an input type `K` so each scalar leaf additionally accepts a
2016
2028
  * {@link Param} standing in for that leaf's value type. Non-scalar leaves and
@@ -2019,8 +2031,25 @@ type Replaceable = string | number;
2019
2031
  *
2020
2032
  * A leaf of type `V` becomes `V | Param<V>`; a `string` literal field that is a
2021
2033
  * fixed discriminator (no param) is still assignable as its literal.
2022
- */
2023
- type Parameterize<K> = K extends Replaceable ? K | Param<K> : K extends object ? {
2034
+ *
2035
+ * The scalar test is written with a **tuple wrap** (`[…] extends […]`) so it does
2036
+ * **not** distribute over a literal-union leaf. A field typed `'a' | 'b'`
2037
+ * therefore yields the whole-union placeholder `Param<'a' | 'b'>` (what
2038
+ * `param.literal('a','b')` produces) rather than the distributed
2039
+ * `Param<'a'> | Param<'b'>`, which rejected the multi-value literal param (#246).
2040
+ * Because `Param` is covariant in its value type, a single-member placeholder
2041
+ * (`param.literal('a')` → `Param<'a'>`) still fits, while a placeholder carrying a
2042
+ * value **outside** the union (`Param<'a' | 'x'>`), a wider-typed placeholder
2043
+ * (`Param<string>` / `Param<number>` on a literal field), or a plain literal not
2044
+ * in the union stays a type error.
2045
+ *
2046
+ * `null` / `undefined` are peeled off first (via `Exclude`/`Extract`) and carried
2047
+ * through verbatim, so an **optional** leaf (`Partial<EntityInput>` in
2048
+ * `defineUpdate` changes) keeps accepting its placeholder — the tuple wrap alone
2049
+ * would otherwise send `string | undefined` down the object arm and drop the
2050
+ * placeholder.
2051
+ */
2052
+ type Parameterize<K> = [Exclude<K, Nullish>] extends [Replaceable] ? [Exclude<K, Nullish>] extends [never] ? K : Exclude<K, Nullish> | Param<Exclude<K, Nullish>> | Extract<K, Nullish> : K extends object ? {
2024
2053
  [P in keyof K]: Parameterize<K[P]>;
2025
2054
  } : K;
2026
2055
  /**
package/dist/index.js CHANGED
@@ -90,7 +90,7 @@ import {
90
90
  validateDepth,
91
91
  when,
92
92
  wholeKeysSentinel
93
- } from "./chunk-WPABX7WG.js";
93
+ } from "./chunk-NYM7K2ST.js";
94
94
  import {
95
95
  CdcEmulator,
96
96
  MAINT_OUTBOX_PK_PREFIX,
@@ -102,7 +102,7 @@ import {
102
102
  orderAndTrimCollection,
103
103
  pathField,
104
104
  projectFrom
105
- } from "./chunk-5NXNEW43.js";
105
+ } from "./chunk-ZPNRLOKA.js";
106
106
  import {
107
107
  BATCH_GET_MAX_KEYS,
108
108
  BATCH_WRITE_MAX_ITEMS,
@@ -157,7 +157,7 @@ import {
157
157
  resolveConditionTree,
158
158
  resolveModelClass,
159
159
  serializeFieldValue
160
- } from "./chunk-F2DI3GTI.js";
160
+ } from "./chunk-PFFPLD4B.js";
161
161
  import {
162
162
  Linter,
163
163
  TableMapping,
@@ -742,32 +742,86 @@ function cdcProjected() {
742
742
  };
743
743
  }
744
744
 
745
+ // src/operations/declarative-transaction.ts
746
+ import { renderTemplate, TemplateFailure } from "behavior-contracts";
747
+
748
+ // src/runtime/behavior-contracts-adapter.ts
749
+ function toSharedValue(v) {
750
+ if (v === null || v === void 0) return null;
751
+ switch (typeof v) {
752
+ case "string":
753
+ case "boolean":
754
+ case "bigint":
755
+ return v;
756
+ case "number":
757
+ return Number.isInteger(v) ? BigInt(v) : v;
758
+ default:
759
+ break;
760
+ }
761
+ if (v instanceof Date) return v.toJSON();
762
+ if (Array.isArray(v)) return v.map((e) => toSharedValue(e));
763
+ if (typeof v === "object") {
764
+ const out = {};
765
+ for (const [k2, field2] of Object.entries(v)) {
766
+ if (field2 === void 0) continue;
767
+ out[k2] = toSharedValue(field2);
768
+ }
769
+ return out;
770
+ }
771
+ return v;
772
+ }
773
+ function toSharedParams(params) {
774
+ const out = {};
775
+ for (const [name, value] of Object.entries(params)) {
776
+ if (value === void 0) continue;
777
+ out[name] = toSharedValue(value);
778
+ }
779
+ return out;
780
+ }
781
+
745
782
  // src/operations/declarative-transaction.ts
746
783
  var PLACEHOLDER_RE = /\{[^{}]+\}/g;
784
+ function hasNonCoreScope(template) {
785
+ return (template.match(PLACEHOLDER_RE) ?? []).some((m) => {
786
+ const name = m.slice(1, -1);
787
+ return name.startsWith("item.") || name.startsWith("result.");
788
+ });
789
+ }
747
790
  function resolveTemplate(template, params, element) {
748
- return template.replace(PLACEHOLDER_RE, (match) => {
749
- const name = match.slice(1, -1);
750
- if (name.startsWith("item.")) {
751
- const field2 = name.slice("item.".length);
752
- if (!element || !(field2 in element)) {
791
+ if (hasNonCoreScope(template)) {
792
+ return template.replace(PLACEHOLDER_RE, (match) => {
793
+ const name = match.slice(1, -1);
794
+ if (name.startsWith("item.")) {
795
+ const field2 = name.slice("item.".length);
796
+ if (!element || !(field2 in element)) {
797
+ throw new Error(
798
+ `declarative transaction: element field '${field2}' is not bound; template '${template}' is only valid inside a forEach over the array param that supplies '${field2}'.`
799
+ );
800
+ }
801
+ return String(element[field2]);
802
+ }
803
+ if (!(name in params) || params[name] === void 0 || params[name] === null) {
753
804
  throw new Error(
754
- `declarative transaction: element field '${field2}' is not bound; template '${template}' is only valid inside a forEach over the array param that supplies '${field2}'.`
805
+ `declarative transaction: template '${template}' references unbound parameter '${name}'.`
755
806
  );
756
807
  }
757
- return String(element[field2]);
758
- }
759
- if (!(name in params) || params[name] === void 0 || params[name] === null) {
760
- throw new Error(
761
- `declarative transaction: template '${template}' references unbound parameter '${name}'.`
762
- );
808
+ return String(params[name]);
809
+ });
810
+ }
811
+ try {
812
+ return renderTemplate(template, toSharedParams(params));
813
+ } catch (exc) {
814
+ if (exc instanceof TemplateFailure && exc.code === "UNBOUND_PARAM") {
815
+ throw new Error(`declarative transaction: ${exc.message}.`);
763
816
  }
764
- return String(params[name]);
765
- });
817
+ throw exc;
818
+ }
766
819
  }
767
820
  function isWholePlaceholder(template) {
768
821
  return /^\{[^{}]+\}$/.test(template);
769
822
  }
770
823
  function resolveValue(template, params, element) {
824
+ if (typeof template !== "string") return template;
771
825
  if (isWholePlaceholder(template)) {
772
826
  const name = template.slice(1, -1);
773
827
  if (name.startsWith("item.")) {
@@ -1079,9 +1133,9 @@ async function executeDeclarativeTransaction(spec, manifest, params) {
1079
1133
  }
1080
1134
 
1081
1135
  // src/runtime/per-key-cursor.ts
1136
+ import { canonicalValue } from "behavior-contracts";
1082
1137
  function serializeContractKey(key2) {
1083
- const sortedEntries = Object.keys(key2).sort().map((field2) => [field2, key2[field2]]);
1084
- return JSON.stringify(Object.fromEntries(sortedEntries));
1138
+ return canonicalValue(toSharedValue(key2));
1085
1139
  }
1086
1140
  function encodePerKeyCursor(key2, inner) {
1087
1141
  if (inner === null) return null;
@@ -1290,6 +1344,7 @@ async function executeRangeFanout(op, keys, params = {}) {
1290
1344
  }
1291
1345
 
1292
1346
  // src/runtime/prepared-loader.ts
1347
+ import { validateEnvelope, EnvelopeFailure } from "behavior-contracts";
1293
1348
  var LOAD_LABEL = "graphddb.loadPreparedPlan";
1294
1349
  function slotOfBind(bind) {
1295
1350
  if ("param" in bind) return { kind: "param", name: bind.param };
@@ -1489,10 +1544,15 @@ function bindPlan(doc, planId) {
1489
1544
  `${LOAD_LABEL}: unsupported artifact format version '${String(doc.formatVersion)}' (this runtime supports '${PREPARED_FORMAT_VERSION}'). Regenerate the artifact: \`graphddb transform prepared --aot <artifact> --write\`.`
1490
1545
  );
1491
1546
  }
1492
- if (doc.specVersion !== SPEC_VERSION) {
1493
- throw new Error(
1494
- `${LOAD_LABEL}: the artifact was compiled against operation-IR version '${String(doc.specVersion)}' but this runtime speaks '${SPEC_VERSION}'. A version-skewed static plan never executes \u2014 regenerate the artifact.`
1495
- );
1547
+ try {
1548
+ validateEnvelope(doc, SPEC_VERSION, { field: "specVersion", label: LOAD_LABEL });
1549
+ } catch (exc) {
1550
+ if (exc instanceof EnvelopeFailure) {
1551
+ throw new Error(
1552
+ `${LOAD_LABEL}: the artifact was compiled against operation-IR version '${String(doc.specVersion)}' but this runtime speaks '${SPEC_VERSION}'. A version-skewed static plan never executes \u2014 regenerate the artifact.`
1553
+ );
1554
+ }
1555
+ throw exc;
1496
1556
  }
1497
1557
  const plan2 = doc.plans[planId];
1498
1558
  if (plan2 === void 0) {
@@ -1,7 +1,7 @@
1
- import { L as LintRule } from '../registry-DWhq5wiA.js';
2
- export { a as LintResult, b as Linter } from '../registry-DWhq5wiA.js';
3
- export { c as createDefaultLinter, g as gsiAmbiguityRule, m as missingGsiRule, n as noScanRule, q as queryBoundaryRule, r as relationDepthRule, a as requireLimitRule } from '../relation-depth-BnqfKkZB.js';
4
- import '../maintenance-view-adapter-C1HaBX4y.js';
1
+ import { L as LintRule } from '../registry-CXhP4TaE.js';
2
+ export { a as LintResult, b as Linter } from '../registry-CXhP4TaE.js';
3
+ export { c as createDefaultLinter, g as gsiAmbiguityRule, m as missingGsiRule, n as noScanRule, q as queryBoundaryRule, r as relationDepthRule, a as requireLimitRule } from '../relation-depth-Dg3yhl7S.js';
4
+ import '../maintenance-view-adapter-BATUh_I8.js';
5
5
  import '@aws-sdk/client-dynamodb';
6
6
 
7
7
  /**