graphddb 0.5.1 → 0.5.3

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.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,11 @@
1
- import { S as SelectableOf, g as PrimaryKeyOf, h as RequestContext, i as Middleware, j as ReadRequestKind, k as CtxModel, l as ReadParams, m as ReadRequestCtx, D as DynamoDBOperation, I as Item, E as Executor, n as RetryPolicy, o as ExecutionPlanSpec, p as EntityMetadata, K as KeyDefinition, G as GsiDefinition, q as ModelKind, F as FieldOptions, r as DynamoType, s as ProjectionTransform, t as MaintainEvent, u as MembershipPredicate, v as MaintainConsistency, w as MaintainUpdateMode, x as MembershipPredicateOp, y as RelationOptions, A as AggregateOptions, z as AggregateValue, H as SelectBuilderSpec, J as RawCondition, L as TransactionSpec, N as Manifest, O as RetryOverride, Q as ExecutionPlan, V as FieldMetadata, X as ResolvedKey, R as ReadExecOptions, a as ExecutorResult, B as BatchGetExecInput, P as PutInput, W as WriteExecOptions, b as WriteResult, U as UpdateInput, c as DeleteInput, d as BatchWriteExecItem, e as BatchExecOptions, T as TransactWriteExecItem, Y as CdcEmulatorOptions, Z as ChangeHandler, _ as Unsubscribe, $ as FaultSpec, a0 as ConcurrentRecomputeRef, C as ChangeEvent, a1 as EventLog, a2 as ReplayOptions, a3 as ShardId, a4 as ViewDefinition, a5 as RelationMetadata, a6 as TransactionItemSpec, a7 as MaintainEffect, M as ModelStatic, f as DDBModel, a8 as Param, a9 as ParamDescriptor, aa as DefinitionMap, ab as OperationDefinition, ac as WriteDefinitionOptions, ad as PartialQueryKeyOf, ae as StrictSelectSpec, af as ReadDefinitionOptions, ag as EntityInput, ah as UniqueQueryKeyOf, ai as EntityRef, aj as ConditionInput, ak as QueryModelContract, al as QueryMethodSpec, am as CommandModelContract, an as CommandMethodSpec, ao as ContractSpec, ap as QuerySpec, aq as CommandSpec, ar as ContextSpec, as as OperationsDocument, at as AnyOperationDefinition, au as BridgeBundle, av as ConditionSpec } from './types-B9rJ1z3H.js';
2
- export { aw as AggregateMetadata, ax as BatchDeleteRequest, ay as BatchGetOptions, az as BatchGetRequest, aA as BatchGetResult, aB as BatchPutRequest, aC as BatchResult, aD as BatchWriteRequest, aE as CONTRACT_RANGE_FANOUT_CONCURRENCY, aF as CdcMode, aG as CdcModelRegistry, aH as CdcSubscribeHandlers, aI as Change, aJ as ChangeBatch, aK as ChangeEventName, aL as ClockMode, aM as CollectionEffect, aN as CollectionOptions, aO as Column, aP as ColumnMap, aQ as CommandContractMethodSpec, aR as CommandInputShape, aS as CommandMethod, aT as CommandPlan, aU as CommandResolutionTarget, aV as CommandResultKind, aW as CommandSelectShape, aX as CompiledFragment, aY as ComposeSpec, aZ as CondSlot, a_ as ConditionCheckInput, a$ as Connection, b0 as ContractCallSignature, b1 as ContractCardinality, b2 as ContractCommandParams, b3 as ContractCommandResult, b4 as ContractComposeNode, b5 as ContractFromRef, b6 as ContractInputArity, b7 as ContractItem, b8 as ContractKeyFieldRef, b9 as ContractKeyInput, ba as ContractKeyRef, bb as ContractKeySpec, bc as ContractKind, bd as ContractMethodOp, be as ContractParamRef, bf as ContractQueryParams, bg as ContractResolution, bh as CounterAggregate, bi as CounterEffect, bj as CtxBase, bk as DEFAULT_MAX_ATTEMPTS, bl as DEFAULT_RETRY_POLICY, bm as DeleteOptions, bn as DeriveEffect, bo as DerivedEdgeWrite, bp as DerivedUpdate, bq as DescriptorBinding, br as ENTITY_WRITES_MARKER, bs as EdgeEffect, bt as EffectPath, bu as EmbeddedMetadata, bv as EmitEffect, bw as EntityWritesDefinition, bx as EntityWritesShape, by as ExecutableCommandContract, bz as ExecutableQueryContract, bA as FilterInput, bB as FilterSpec, bC as FragmentInput, bD as GsiDefinitionMarker, bE as GsiOptions, bF as IdempotencyEffect, bG as InProcessWriteDescriptor, bH as InputArity, bI as KeyDefinitionMarker, bJ as KeySegment, bK as KeySlot, bL as KeyStructure, bM as KeyedResult, bN as LIFECYCLE_CONTRACT_MARKER, bO as LifecycleContract, bP as LifecycleEffects, bQ as LiteralParam, bR as MaintainItem, bS as MaintainTrigger, bT as MaintenanceGraph, bU as ManifestEntity, bV as ManifestField, bW as ManifestFieldType, bX as ManifestGsi, bY as ManifestKey, bZ as ManifestRelation, b_ as ManifestTable, b$ as MembershipEffect, c0 as ModelRef, c1 as MutateMode, c2 as MutateOptions, c3 as MutateParallelResult, c4 as MutateTransactionResult, c5 as MutationBody, c6 as MutationDescriptorMap, c7 as MutationFragment, c8 as MutationInputProxy, c9 as MutationInputRef, ca as MutationIntent, cb as NumberParam, cc as OperationKind, cd as OperationSpec, ce as ParallelOpResult, cf as ParamKind, cg as ParamSpec, ch as ParamStructure, ci as PersistCtx, cj as PersistOrigin, ck as PlannedCommandMethod, cl as ProjectionMap, cm as ProjectionTransformOp, cn as PutOptions, co as QueryContractMethodSpec, cp as QueryEnvelopeResult, cq as QueryKeyOf, cr as QueryMethod, cs as QueryResult, ct as RangeConditionSpec, cu as ReadEnvelope, cv as ReadOpCtx, cw as ReadOpKind, cx as ReadOperationType, cy as ReadRouteDescriptor, cz as ReadRouteOptions, cA as ReadRouteResult, cB as RecordedCompose, cC as RelationBuilder, cD as RelationConsistency, cE as RelationLimitOptions, cF as RelationPattern, cG as RelationProjection, cH as RelationReadOptions, cI as RelationSelect, cJ as RelationSpec, cK as RelationUpdateMode, cL as RelationWriteOptions, cM as RequiresEffect, cN as Resolution, cO as RetryInfo, cP as RetryOperationKind, cQ as SPEC_VERSION, cR as SegmentSpec, cS as SegmentedKey, cT as SelectBuilder, cU as SelectOf, cV as SnapshotEffect, cW as StartingPosition, cX as StreamViewType, cY as StringParam, cZ as SubscribeHandler, c_ as SubscribeHandlers, c$ as TransactionContext, d0 as TransactionItemType, d1 as UniqueEffect, d2 as Updatable, d3 as UpdateOptions, d4 as ViewSourceSlice, d5 as WhenSpec, d6 as WriteCtx, d7 as WriteDescriptor, d8 as WriteEnvelope, d9 as WriteInput, da as WriteKind, db as WriteLifecyclePhase, dc as WriteMiddleware, dd as WriteOperationType, de as WriteRecorder, df as WriteResultProjection, dg as attachModelClass, dh as buildDeleteInput, di as buildMaintenanceGraph, dj as buildPutInput, dk as buildSubscribeHandler, dl as buildUpdateInput, dm as collectViewDefinitions, dn as compileFragment, dp as compileMutationPlan, dq as compileSingleFragmentPlan, dr as cond, ds as contractOfMethodSpec, dt as definePlan, du as entityWrites, dv as executeBatchGet, dw as executeBatchWrite, dx as executeCommandMethod, dy as executeDelete, dz as executeKeyedBatchGet, dA as executePut, dB as executeQueryMethod, dC as executeRangeFanout, dD as executeTransaction, dE as executeUpdate, dF as from, dG as getEntityWrites, dH as gsi, dI as identity, dJ as isColumn, dK as isCommandModelContract, dL as isCommandPlan, dM as isContractComposeNode, dN as isContractFromRef, dO as isContractKeyFieldRef, dP as isContractKeyRef, dQ as isContractParamRef, dR as isEntityWritesDefinition, dS as isKeySegment, dT as isLifecycleContract, dU as isMaintainTrigger, dV as isMutationFragment, dW as isMutationInputRef, dX as isParam, dY as isPlannedCommandMethod, dZ as isQueryModelContract, d_ as isRetryableError, d$ as isRetryableTransactionCancellation, e0 as k, e1 as key, e2 as lifecyclePhaseForIntent, e3 as maintainTrigger, e4 as mintContractKeyFieldRef, e5 as mintContractParamRef, e6 as mutation, e7 as param, e8 as preview, e9 as publicCommandModel, ea as publicQueryModel, eb as query, ec as resolveLifecycle, ed as wholeKeysSentinel } from './types-B9rJ1z3H.js';
1
+ export { a as LintResult, L as LintRule, b as Linter, M as MetadataRegistry } from './registry-BD_5Rm5C.js';
2
+ import { aN as SelectableOf, aO as PrimaryKeyOf, aP as RequestContext, aQ as Middleware, aR as ReadRequestKind, aS as CtxModel, aT as ReadParams, aU as ReadRequestCtx, D as DynamoDBOperation, aV as Item, n as Executor, aW as RetryPolicy, am as ExecutionPlanSpec, aX as KeyDefinition, aY as GsiDefinition, aZ as ModelKind, a_ as FieldOptions, a$ as DynamoType, b0 as ProjectionTransform, b1 as MaintainEvent, b2 as MembershipPredicate, b3 as MaintainConsistency, b4 as MaintainUpdateMode, b5 as MembershipPredicateOp, b6 as RelationOptions, b7 as AggregateOptions, b8 as AggregateValue, b9 as SelectBuilderSpec, ba as RawCondition, m as EntityMetadata, N as TransactionSpec, _ as Manifest, bb as RetryOverride, bc as ExecutionPlan, bd as FieldMetadata, be 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, bf as RelationMetadata, aC as TransactionItemSpec, bg as MaintainEffect, M as ModelStatic, w as DDBModel, V as ViewDefinition, A as Param, x as ParamDescriptor, X as DefinitionMap, bh as OperationDefinition, bi as WriteDefinitionOptions, bj as PartialQueryKeyOf, bk as StrictSelectSpec, bl as ReadDefinitionOptions, bm as EntityInput, bn as UniqueQueryKeyOf } from './maintenance-view-adapter-D5t9taTE.js';
3
+ export { bo as AggregateMetadata, Z as AnyOperationDefinition, bp as BatchDeleteRequest, bq as BatchGetOptions, br as BatchGetRequest, bs as BatchGetResult, bt as BatchPutRequest, B as BatchResult, bu as BatchWriteRequest, $ as BridgeBundle, bv as CONTRACT_RANGE_FANOUT_CONCURRENCY, C as CdcEmulatorOptions, a as CdcMode, bw as CdcModelRegistry, bx as CdcSubscribeHandlers, by as Change, b as ChangeBatch, c as ChangeEvent, d as ChangeEventName, e as ChangeHandler, f as ClockMode, bz as CollectionEffect, bA as CollectionOptions, bB as Column, bC as ColumnMap, a1 as CommandContractMethodSpec, bD as CommandInputShape, bE as CommandMethod, I as CommandMethodSpec, H as CommandModelContract, bF as CommandPlan, a2 as CommandResolutionTarget, bG as CommandResultKind, bH as CommandSelectShape, L as CommandSpec, a3 as CompiledFragment, a5 as ComposeSpec, g as ConcurrentRecomputeRef, bI as CondSlot, bJ as ConditionCheckInput, z as ConditionInput, a0 as ConditionSpec, bK as Connection, O as ContextSpec, bL as ContractCallSignature, a7 as ContractCardinality, bM as ContractCommandParams, a8 as ContractCommandResult, bN as ContractComposeNode, bO as ContractFromRef, a9 as ContractInputArity, bP as ContractItem, bQ as ContractKeyFieldRef, bR as ContractKeyInput, bS as ContractKeyRef, aa as ContractKeySpec, ab as ContractKind, bT as ContractMethodOp, bU as ContractParamRef, bV as ContractQueryParams, ac as ContractResolution, J as ContractSpec, bW as CounterAggregate, bX as CounterEffect, bY as CtxBase, bZ as DEFAULT_MAX_ATTEMPTS, b_ as DEFAULT_RETRY_POLICY, b$ as DeleteOptions, c0 as DeriveEffect, ae as DerivedEdgeWrite, ak as DerivedUpdate, c1 as DescriptorBinding, c2 as ENTITY_WRITES_MARKER, c3 as EdgeEffect, c4 as EffectPath, c5 as EmbeddedMetadata, c6 as EmitEffect, y as EntityRef, c7 as EntityWritesDefinition, c8 as EntityWritesShape, E as EventLog, c9 as ExecutableCommandContract, ca as ExecutableQueryContract, F as FaultSpec, cb as FilterInput, an as FilterSpec, cc as FragmentInput, cd as GsiDefinitionMarker, ce as GsiOptions, cf as IdempotencyEffect, cg as InProcessWriteDescriptor, ch as InputArity, ci as KeyDefinitionMarker, cj as KeySegment, ck as KeySlot, cl as KeyStructure, cm as KeyedResult, cn as LIFECYCLE_CONTRACT_MARKER, co as LifecycleContract, cp as LifecycleEffects, cq as LiteralParam, cr as MaintainItem, cs as MaintainTrigger, ct as MaintenanceGraph, ap as ManifestEntity, aq as ManifestField, ar as ManifestFieldType, as as ManifestGsi, at as ManifestKey, au as ManifestRelation, av as ManifestTable, cu as MembershipEffect, cv as ModelRef, cw as MutateMode, cx as MutateOptions, cy as MutateParallelResult, cz as MutateTransactionResult, cA as MutationBody, cB as MutationDescriptorMap, cC as MutationFragment, cD as MutationInputProxy, cE as MutationInputRef, cF as MutationIntent, cG as NumberParam, cH as OperationKind, aw as OperationSpec, Y as OperationsDocument, cI as ParallelOpResult, cJ as ParamKind, ax as ParamSpec, cK as ParamStructure, cL as PersistCtx, cM as PersistOrigin, cN as PlannedCommandMethod, cO as ProjectionMap, cP as ProjectionTransformOp, cQ as PutOptions, ay as QueryContractMethodSpec, cR as QueryEnvelopeResult, cS as QueryKeyOf, cT as QueryMethod, G as QueryMethodSpec, Q as QueryModelContract, cU as QueryResult, K as QuerySpec, az as RangeConditionSpec, cV as ReadEnvelope, cW as ReadOpCtx, cX as ReadOpKind, aA as ReadOperationType, cY as ReadRouteDescriptor, cZ as ReadRouteOptions, c_ as ReadRouteResult, c$ as RecordedCompose, d0 as RelationBuilder, d1 as RelationConsistency, d2 as RelationLimitOptions, d3 as RelationPattern, d4 as RelationProjection, d5 as RelationReadOptions, d6 as RelationSelect, d7 as RelationSpec, d8 as RelationUpdateMode, d9 as RelationWriteOptions, R as ReplayOptions, da as RequiresEffect, db as Resolution, dc as RetryInfo, dd as RetryOperationKind, aB as SPEC_VERSION, de as SegmentSpec, df as SegmentedKey, dg as SelectBuilder, dh as SelectOf, S as ShardId, di as SnapshotEffect, h as StartingPosition, i as StreamViewType, dj as StringParam, j as SubscribeHandler, k as SubscribeHandlers, dk as TransactionContext, aD as TransactionItemType, dl as UniqueEffect, dm as Updatable, dn as UpdateOptions, dp as ViewSourceSlice, aE as WhenSpec, dq as WriteCtx, dr as WriteDescriptor, ds as WriteEnvelope, dt as WriteInput, du as WriteKind, dv as WriteLifecyclePhase, dw as WriteMiddleware, aF as WriteOperationType, dx as WriteRecorder, dy as WriteResultProjection, dz as attachModelClass, dA as buildDeleteInput, dB as buildMaintenanceGraph, dC as buildPutInput, l as buildSubscribeHandler, dD as buildUpdateInput, dE as collectViewDefinitions, aH as compileFragment, aI as compileMutationPlan, aJ as compileSingleFragmentPlan, dF as cond, dG as contractOfMethodSpec, dH as definePlan, dI as entityWrites, dJ as executeBatchGet, dK as executeBatchWrite, dL as executeCommandMethod, dM as executeDelete, dN as executeKeyedBatchGet, dO as executePut, dP as executeQueryMethod, dQ as executeRangeFanout, dR as executeTransaction, dS as executeUpdate, dT as from, dU as getEntityWrites, dV as gsi, dW as identity, dX as isColumn, dY as isCommandModelContract, dZ as isCommandPlan, d_ as isContractComposeNode, d$ as isContractFromRef, e0 as isContractKeyFieldRef, e1 as isContractKeyRef, e2 as isContractParamRef, e3 as isEntityWritesDefinition, e4 as isKeySegment, e5 as isLifecycleContract, e6 as isMaintainTrigger, e7 as isMutationFragment, e8 as isMutationInputRef, e9 as isParam, ea as isPlannedCommandMethod, eb as isQueryModelContract, ec as isRetryableError, ed as isRetryableTransactionCancellation, ee as k, ef as key, eg as lifecyclePhaseForIntent, eh as maintainTrigger, ei as mintContractKeyFieldRef, ej as mintContractParamRef, ek as mutation, el as param, em as preview, en as publicCommandModel, eo as publicQueryModel, ep as query, aL as resolveLifecycle, eq as wholeKeysSentinel } from './maintenance-view-adapter-D5t9taTE.js';
3
4
  import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
4
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-DQK2Jm9R.js';
7
+ 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-DLkhG0xX.js';
8
+ export { A as AnyModelContract, B as BuiltContracts, C as ContextOwnership, a as ContextOwnershipMap, b as ContractBoundaryViolation, c as ContractInputs, d as ContractMap, e as ContractN1Violation, T as TransactionDefinition, f as TransactionParamShape, g as TransactionRef, h as TxConditionCheckOptions, i as TxForEachInstruction, j as TxForEachOptions, k as TxInstruction, l as TxRecorder, m as TxWriteInstruction, n as TxWriteOptions, W as WhenComparison, o as assertBundleSerializable, p as assertContractBoundaries, q as assertContractN1Safe, r as assertJsonSerializable, s as assertSupportedCondition, t as buildBridgeBundle, u as buildContexts, v as buildContracts, w as buildManifest, x as buildOperations, y as buildQuerySpec, z as buildTransactionSpec, D as buildTransactions, E as collectContractBoundaryViolations, F as collectContractN1Violations, G as defineTransaction, H as defineTransactions, I as isTransactionRef, J as when } from './index-CtDBo8Se.js';
5
9
 
6
10
  /**
7
11
  * Query options with conditional `consistentRead` availability.
@@ -313,72 +317,6 @@ interface RelationExecutionPlan {
313
317
  readonly resultPaths: readonly string[];
314
318
  }
315
319
 
316
- interface LintRule {
317
- id: string;
318
- severity: 'error' | 'warning';
319
- check(metadata: EntityMetadata, registry: typeof MetadataRegistry): LintResult[];
320
- }
321
- interface LintResult {
322
- ruleId: string;
323
- severity: 'error' | 'warning';
324
- message: string;
325
- entity: string;
326
- field?: string;
327
- }
328
-
329
- declare class Linter {
330
- private rules;
331
- addRule(rule: LintRule): void;
332
- run(metadata: EntityMetadata, registry: typeof MetadataRegistry): LintResult[];
333
- runAll(registry: typeof MetadataRegistry): LintResult[];
334
- }
335
-
336
- declare class MetadataRegistry {
337
- private static store;
338
- private static _linter;
339
- /**
340
- * A monotonically-increasing counter bumped on every change to the set of
341
- * registered models ({@link register} / {@link clear}). It lets a consumer that
342
- * caches a structure derived from the whole registry (e.g. the maintenance graph
343
- * in `src/spec/mutation-command.ts`) detect that the registry has changed since
344
- * the cache was built and rebuild — closing the silent-drop window where a model
345
- * registered after a cache build would be invisible to it. Only the membership
346
- * of {@link store} changes here; per-model lazy finalize ({@link finalize}) does
347
- * not bump it (it adds no relations/triggers, so it cannot change the graph).
348
- */
349
- private static _generation;
350
- /**
351
- * The current registry generation (see {@link _generation}). A consumer caches
352
- * the value it built against and rebuilds when it no longer matches.
353
- */
354
- static get generation(): number;
355
- static register(target: Function, metadata: EntityMetadata): void;
356
- static get(target: Function): EntityMetadata;
357
- static has(target: Function): boolean;
358
- static getAll(): Map<Function, EntityMetadata>;
359
- /**
360
- * Snapshot of the entities that are **already finalized**, WITHOUT triggering
361
- * finalize on any pending entity (unlike {@link getAll}). This is the safe view
362
- * for a cross-entity lint rule that runs *inside* `finalize`: eagerly
363
- * finalizing the rest of the registry from within a finalize pass would
364
- * re-enter (and duplicate) the in-progress entity's finalize. A whole-registry
365
- * rule instead reasons over the already-finalized peers plus the entity
366
- * currently being checked; any conflicting pair is caught when the later of the
367
- * two finalizes (both are present by then).
368
- *
369
- * @internal — for cross-entity linter rules.
370
- */
371
- static getFinalized(): Map<Function, EntityMetadata>;
372
- static get linter(): Linter;
373
- static set linter(linter: Linter);
374
- /** Resets linter to the default built-in rule set. */
375
- static resetLinter(): void;
376
- /** @internal — for testing only */
377
- static clear(): void;
378
- private static finalize;
379
- private static handleLintResults;
380
- }
381
-
382
320
  declare function derivePrefix(customPrefix: string | undefined, className: string | undefined): string;
383
321
 
384
322
  /**
@@ -735,6 +673,16 @@ interface MaintainedFromOptions<Self = unknown> {
735
673
  readonly when?: MembershipPredicate;
736
674
  readonly consistency?: MaintainConsistency;
737
675
  readonly updateMode?: MaintainUpdateMode;
676
+ /**
677
+ * Optional human-readable description of this maintained-from source slice (issue
678
+ * #166, follow-up of #154). Pure documentation metadata — it does NOT affect the
679
+ * maintenance IR or any runtime behaviour. Captured onto
680
+ * {@link MaintainedFromMetadata.description}. The maintenance IR is deliberately
681
+ * kept off `manifest.json` / `operations.json` and the generated Python (see the
682
+ * note on {@link MaintainedFromMetadata.description}), so this is a metadata-layer
683
+ * capture only. Omit for byte-identical metadata.
684
+ */
685
+ readonly description?: string;
738
686
  }
739
687
  /** The `(self, source) =>` symbolic callback evaluated at decoration time. */
740
688
  type MaintainedFromCallback<Self, Source> = (self: SelfProxy<Self>, source: SourceProxy<Source>) => MaintainedFromOptions<Self>;
@@ -837,7 +785,7 @@ type HasManyVersionedCallback<Self, Source> = (self: SelfProxy<Self>, source: So
837
785
  declare function hasMany(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>, options?: RelationOptions): (value: undefined, context: ClassFieldDecoratorContext) => void;
838
786
  declare function hasMany<Self = unknown, Source = unknown>(targetFactory: () => new (...args: unknown[]) => unknown, callback: HasManyVersionedCallback<Self, Source>): (value: undefined, context: ClassFieldDecoratorContext) => void;
839
787
  declare function belongsTo(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>, options?: RelationOptions): (_value: undefined, context: ClassFieldDecoratorContext) => void;
840
- declare function hasOne(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>): (value: undefined, context: ClassFieldDecoratorContext) => void;
788
+ declare function hasOne(targetFactory: () => new (...args: unknown[]) => unknown, keyBinding: Record<string, string>, options?: RelationOptions): (value: undefined, context: ClassFieldDecoratorContext) => void;
841
789
  declare function hasOne<Self = unknown, Source = unknown>(targetFactory: () => new (...args: unknown[]) => unknown, callback: HasOneVersionedCallback<Self, Source>): (value: undefined, context: ClassFieldDecoratorContext) => void;
842
790
 
843
791
  /**
@@ -1332,330 +1280,6 @@ declare function encodeCursor(lastEvaluatedKey: Record<string, unknown>): string
1332
1280
  */
1333
1281
  declare function decodeCursor(cursor: string): Record<string, unknown>;
1334
1282
 
1335
- /**
1336
- * CDC emulator (issue #72). Subscribes to the core write-capture seam
1337
- * ({@link ChangeCaptureRegistry}) and turns each {@link RawWriteRecord} into a
1338
- * DynamoDB-Streams-equivalent {@link ChangeEvent}, then delivers events to a
1339
- * consumer under a deterministic delivery contract (spec §6): per-shard ordered,
1340
- * batched, at-least-once, with checkpoint/resume, partial-batch failure, and a
1341
- * dead-letter queue. Faults (duplicate / reorder / delay / dropThenRedeliver /
1342
- * partialBatchFailure) and a concurrent-recompute race are injectable and
1343
- * seeded for deterministic reproduction (spec §8).
1344
- *
1345
- * The emulator is dev/test only. The {@link ChangeEvent} type and delivery
1346
- * contract match real Streams so a consumer is portable to production (spec §1).
1347
- */
1348
-
1349
- /**
1350
- * The CDC emulator (spec §10 API). Construct via {@link createCdcEmulator}.
1351
- */
1352
- declare class CdcEmulator {
1353
- private readonly mode;
1354
- private readonly clockMode;
1355
- private readonly batchSize;
1356
- private readonly maxRetries;
1357
- private readonly startingPosition;
1358
- private readonly shardCount;
1359
- private readonly seed;
1360
- private rng;
1361
- private faultSpec;
1362
- private concurrentRecompute;
1363
- private concurrentRecomputeHook;
1364
- /** Per-shard monotonic sequence counter. */
1365
- private seqCounters;
1366
- /** Per-shard delivery queue (queued/replay modes). */
1367
- private queues;
1368
- /** Per-shard last successfully checkpointed sequence number. */
1369
- private checkpointMap;
1370
- /**
1371
- * Per-shard set of acked sequence numbers (as ints) not yet folded into the
1372
- * checkpoint. The checkpoint advances over the contiguous prefix of acked
1373
- * sequences (ReportBatchItemFailures semantics): a sequence is checkpointed
1374
- * only once every sequence at or before it has been acked.
1375
- */
1376
- private ackedSeqs;
1377
- /** Per-shard count of sequences ever assigned, to bound the prefix scan. */
1378
- private maxSeqSeen;
1379
- /** Recorded event log (record mode and always, for replay()). */
1380
- private log;
1381
- /** Dead-letter buffer. */
1382
- private dlq;
1383
- private handler;
1384
- /** Virtual clock (ms since EPOCH). */
1385
- private clockMs;
1386
- /** Pending async work from inline-mode captures, awaited by callers. */
1387
- private inflight;
1388
- private detachCapture;
1389
- private readonly models;
1390
- constructor(opts?: CdcEmulatorOptions);
1391
- private onRawWrite;
1392
- private toChangeEvent;
1393
- /** Parse a zero-padded sequence string back to its integer value. */
1394
- private seqToInt;
1395
- /** Render an integer sequence as the zero-padded string form. */
1396
- private intToSeq;
1397
- /**
1398
- * Advance a shard's checkpoint over the contiguous prefix of acked sequence
1399
- * numbers. Starting just past the current checkpoint, consume every
1400
- * consecutive acked sequence; stop at the first gap (an un-acked sequence
1401
- * still pending redelivery). Consumed sequences are removed from the acked
1402
- * set to bound its size.
1403
- */
1404
- private advanceCheckpoint;
1405
- private deriveEventName;
1406
- private nowIso;
1407
- private enqueue;
1408
- /**
1409
- * Deliver buffered, due records to the consumer, advancing per-shard
1410
- * checkpoints on success and redelivering failures. In `queued`/`replay`
1411
- * modes call this (or {@link advanceClock}) to drive delivery; `inline` calls
1412
- * it automatically after each capture.
1413
- */
1414
- pump(maxBatches?: number): Promise<void>;
1415
- /**
1416
- * Pull up to `batchSize` due records from a shard, preserving ascending
1417
- * sequence order (spec §6). When the `reorder` fault is on, the within-shard
1418
- * order is deliberately shuffled to exercise invariant detection.
1419
- */
1420
- private collectBatch;
1421
- private deliverBatch;
1422
- /** Register the consumer. Returns an unsubscribe handle. */
1423
- subscribe(handler: ChangeHandler): Unsubscribe;
1424
- /** Await any inline-mode async deliveries triggered by writes. */
1425
- flush(): Promise<void>;
1426
- /**
1427
- * Advance the virtual clock by `ms` and deliver records whose due-time has
1428
- * arrived (spec §7). Reproduces throttle T / sweep period / staleness S time
1429
- * behavior deterministically (AC4).
1430
- */
1431
- advanceClock(ms: number): Promise<void>;
1432
- /** Current virtual time (ms since the emulator epoch). */
1433
- now(): number;
1434
- /** Configure fault injection (spec §8). Merges into the current spec. */
1435
- fault(spec: FaultSpec): void;
1436
- /**
1437
- * Force a recompute to race a mark for the given ref (spec §8, §7). The
1438
- * harness supplies the actual recompute via {@link onConcurrentRecompute};
1439
- * this records which ref to race and arms the hook.
1440
- */
1441
- injectConcurrentRecompute(ref: ConcurrentRecomputeRef): void;
1442
- /**
1443
- * Register the callback the emulator invokes (before each record reaches the
1444
- * consumer) when a concurrent recompute has been injected. This is how the
1445
- * test harness wires its recompute into the delivery race.
1446
- */
1447
- onConcurrentRecompute(hook: (ref: ConcurrentRecomputeRef, event: ChangeEvent) => void | Promise<void>): void;
1448
- /** Snapshot the recorded event log (spec §10). */
1449
- record(): EventLog;
1450
- /**
1451
- * Replay an event log through the delivery pipeline, optionally shuffled and
1452
- * duplicated (spec §10, AC5). Used to prove **replay equivalence**: starting
1453
- * from any global order plus duplicates, a consumer that respects the
1454
- * per-shard ordering contract (spec §6) reaches a final aggregate equal to a
1455
- * full recompute from source.
1456
- *
1457
- * The shuffle models cross-shard reordering and at-least-once chaos at the
1458
- * delivery boundary. It must NOT, however, break the within-shard ordering
1459
- * guarantee that real DynamoDB Streams provides and that incremental
1460
- * aggregation depends on — so after shuffling/duplicating, each shard's queue
1461
- * is re-sorted into ascending original `sequenceNumber` order before delivery.
1462
- * The original `sequenceNumber` (assigned at record time) is preserved so it
1463
- * remains the source-of-truth ordering the consumer can rely on.
1464
- */
1465
- replay(log: EventLog, opts?: ReplayOptions): Promise<void>;
1466
- /** Per-shard checkpoints (last acked sequence number). */
1467
- checkpoints(): Record<ShardId, string>;
1468
- /** Dead-lettered events (exceeded maxRetries). */
1469
- deadLetters(): ChangeEvent[];
1470
- /** Reset delivery state and re-seed (keeps the subscription + model opt-in). */
1471
- reset(): void;
1472
- /** Tear down: detach from the core seam and disable model streaming. */
1473
- close(): void;
1474
- }
1475
- /** Create a CDC emulator (spec §10). */
1476
- declare function createCdcEmulator(opts?: CdcEmulatorOptions): CdcEmulator;
1477
-
1478
- /**
1479
- * CDC **maintenance drain** (issue #130) — the asynchronous lower for
1480
- * `updateMode: 'stream'` maintainers (Epic #118 §5.1).
1481
- *
1482
- * A synchronous (`updateMode: 'mutation'`) maintainer composes its owner-row write
1483
- * into the SAME atomic `TransactWriteItems` as the source write (#127). A
1484
- * `updateMode: 'stream'` maintainer instead emits a **maintenance-outbox** marker row
1485
- * (`OUTBOX#MAINT#…`) ATOMICALLY with the source write (the #130 compile lowering in
1486
- * `src/spec/mutation-command.ts`), and THIS consumer — driven by the {@link
1487
- * import('./emulator.js').CdcEmulator} (or, in production, real DynamoDB Streams +
1488
- * a Lambda built around {@link createMaintenanceDrainHandler}) — applies the owner-row
1489
- * write asynchronously.
1490
- *
1491
- * ## Why a separate async path exists (not just "do it later synchronously")
1492
- *
1493
- * The async path realizes the maintenance operations a single synchronous
1494
- * `UpdateExpression` cannot express against an unread item:
1495
- *
1496
- * - **collection `maxItems` trim** — keeping a bounded, ordered list requires reading
1497
- * the current list, appending, sorting, and trimming (a read-modify-write); a
1498
- * synchronous `list_append` can only append (Phase 1 was append-only, #127).
1499
- * - **`removed`-driven splice** — removing an entry from a maintained collection on a
1500
- * source `removed` event likewise needs the current list.
1501
- * - **running `max(field)`** — a conditional `SET` (`#a = :v` guarded by
1502
- * `attribute_not_exists(#a) OR #a < :v`) whose failed guard, if run synchronously,
1503
- * would roll back the legitimate source write.
1504
- *
1505
- * ## Delivery guarantees (reused from the CDC substrate)
1506
- *
1507
- * The maintenance-outbox row is recorded ATOMICALLY with the source write, so the
1508
- * intent can never be lost ("wrote the row, lost the maintenance" is impossible). The
1509
- * CDC substrate then delivers it **at-least-once**, **per-shard ordered** (a shard is
1510
- * `hash(pk)`, and the outbox row's `pk` is keyed off the SOURCE row's key, so all
1511
- * maintenance events for one source entity land on one shard in source-write order),
1512
- * with a **DLQ** for poison events. This consumer is therefore written to be
1513
- * **idempotent / commutative** wherever at-least-once redelivery could double-apply:
1514
- *
1515
- * - a `snapshot` `SET` is naturally idempotent (re-applying the same projection is a
1516
- * no-op);
1517
- * - a `collection` rebuild de-duplicates by the projected item's identity key, so a
1518
- * redelivered append does not grow the list twice;
1519
- * - a `max` conditional `SET` is idempotent (the guard rejects a non-greater value);
1520
- * - a `count` `ADD` is the ONE non-idempotent op — but the source-row create guard
1521
- * (`attribute_not_exists`) means a given source `created` event is emitted at most
1522
- * once into the outbox, and the per-shard checkpoint advances only over acked events,
1523
- * so a `count` is applied once per genuine source lifecycle. (A duplicate DELIVERY of
1524
- * the same event is folded by the consumer's per-event de-dup set within a drain.)
1525
- */
1526
-
1527
- /**
1528
- * The PK prefix a maintenance-outbox row keys on — the single source of truth shared
1529
- * with the compiler ({@link import('../spec/mutation-command.js')}'s
1530
- * `MAINT_OUTBOX_PK_PREFIX`). The drain selects its events by `keys.pk.startsWith` of
1531
- * this. Kept as a local literal (rather than importing a non-exported compiler const)
1532
- * so the cdc module does not depend on the spec module; the value is asserted equal by
1533
- * the integration tests that round-trip a real stream maintainer through both.
1534
- */
1535
- declare const MAINT_OUTBOX_PK_PREFIX = "OUTBOX#MAINT#";
1536
- /** Options for {@link createMaintenanceDrain}. */
1537
- interface MaintenanceDrainOptions {
1538
- /**
1539
- * The model classes (or `ModelStatic`s) whose stream maintainers this drain
1540
- * applies. The drain builds a scoped {@link MaintenanceGraph} over them to resolve
1541
- * each maintenance-outbox event back to its declared effect. Defaults to the GLOBAL
1542
- * registry when omitted.
1543
- */
1544
- readonly models?: readonly Function[];
1545
- /**
1546
- * The {@link ViewDefinition}s (`defineView`) whose maintainers this drain applies
1547
- * (issue #132). A view's destination is its dedicated view model; its source
1548
- * classes should also be in {@link models} so the drain can resolve their
1549
- * maintenance-outbox events. Defaults to none.
1550
- */
1551
- readonly views?: readonly ViewDefinition[];
1552
- }
1553
- /**
1554
- * A maintenance drain: a CDC consumer ({@link ChangeHandler}) that applies the
1555
- * owner-row writes for `updateMode: 'stream'` maintainers. Construct via
1556
- * {@link createMaintenanceDrain}, then `subscribe` its {@link handler} to a
1557
- * {@link import('./emulator.js').CdcEmulator} (dev/test) or wire it into a real
1558
- * Streams Lambda (production).
1559
- */
1560
- declare class MaintenanceDrain {
1561
- private readonly graph;
1562
- /** Owner entity name → its model class (for the owner-row key derivation). */
1563
- private readonly ownerByName;
1564
- /** Per-event-id de-dup within a single handler invocation (at-least-once). */
1565
- private appliedSeq;
1566
- /** Count of owner-row writes applied (test/diagnostic). */
1567
- private applied;
1568
- constructor(opts?: MaintenanceDrainOptions);
1569
- /** The CDC {@link ChangeHandler} to subscribe to an emulator / Streams source. */
1570
- readonly handler: ChangeHandler;
1571
- /** Resolve one maintenance-outbox event to its effect and apply the owner-row write. */
1572
- private applyOne;
1573
- /** Resolve a maintenance-outbox event back to the declared {@link MaintainItem}. */
1574
- private resolve;
1575
- /** A `snapshot` SET of each projected attribute onto the owner row (idempotent). */
1576
- private applySnapshot;
1577
- /**
1578
- * A sparse-view **membership** write (#133): evaluate the membership predicate against
1579
- * the source image; PUT the view row (its projection + key fields) when the predicate
1580
- * holds, DELETE it when it flips false. A source `removed` event always deletes (the
1581
- * source no longer exists, so its view row must disappear regardless of the predicate).
1582
- *
1583
- * Both ops are idempotent under at-least-once redelivery: a repeated PUT writes the same
1584
- * row, a repeated DELETE is a no-op. The view row is keyed by the source identity
1585
- * (`effect.keys`), so the PUT/DELETE always targets the SAME physical row the predicate
1586
- * gates.
1587
- */
1588
- private applyMembership;
1589
- /**
1590
- * A running `max`: read the owner row, and `SET` the attribute to the source value
1591
- * only when it is greater (or absent). Implemented as a conditional update so a
1592
- * redelivered / out-of-order older value never regresses the stored max — idempotent
1593
- * and commutative under at-least-once delivery.
1594
- */
1595
- private applyMax;
1596
- /**
1597
- * A bounded `collection`: read the current list, apply the event (append for a
1598
- * `created`/`updated` source, splice for a `removed`), de-duplicate by the projected
1599
- * identity key, order by `orderBy` (in `orderDir`, default DESC), trim to `maxItems`, and write the whole
1600
- * list back. The read-modify-write is exactly what a single synchronous
1601
- * `UpdateExpression` cannot do — the reason a bounded/ordered collection is a stream
1602
- * maintainer (Phase 1 sync was append-only).
1603
- */
1604
- private applyCollection;
1605
- /** Owner-row writes applied so far (test/diagnostic). */
1606
- appliedCount(): number;
1607
- /** Clear the per-delivery de-dup set + counters (test reset). */
1608
- reset(): void;
1609
- }
1610
- /** Create a {@link MaintenanceDrain} (issue #130). */
1611
- declare function createMaintenanceDrain(opts?: MaintenanceDrainOptions): MaintenanceDrain;
1612
- /**
1613
- * Create just the CDC {@link ChangeHandler} for a maintenance drain — the form to
1614
- * subscribe to an emulator or wire into a production Streams Lambda. A thin wrapper
1615
- * over {@link createMaintenanceDrain} for callers that only need the handler.
1616
- */
1617
- declare function createMaintenanceDrainHandler(opts?: MaintenanceDrainOptions): ChangeHandler;
1618
-
1619
- /**
1620
- * `fromChange` — the pure `(event) => [old, new]` typed mapper (issue #153).
1621
- *
1622
- * This is graphddb's HALF of the CDC-projection boundary (see
1623
- * `docs/cdc-projection.md`): it parses a raw {@link ChangeEvent}'s `oldImage` /
1624
- * `newImage` into typed model instances and does nothing downstream of that (no
1625
- * sink write, no dedup, no subscription). `Model.fromChange(event)` on `DDBModel`
1626
- * delegates here.
1627
- *
1628
- * The two responsibilities packed into one call are **routing** and **parse**:
1629
- *
1630
- * - Routing — an event that is not for `modelClass` yields `[null, null]`. A valid
1631
- * event for the class always has at least one non-null image, so `[null, null]`
1632
- * is an unambiguous "not for this model" signal and no separate `owns()` guard is
1633
- * needed. The match is by `event.model` (the resolved model name the write path /
1634
- * emulator stamps) when present, falling back to the model's PK prefix
1635
- * (`keys.pk` begins with `<prefix>`) when the event carries no `model`.
1636
- * - Parse — each present image is hydrated via the existing {@link hydrate}
1637
- * (raw item → typed value, INCLUDING ISO 8601 → `Date` for `@datetime` and
1638
- * embedded reconstruction), returning ALL fields (no projection — narrowing does
1639
- * not reduce network cost since the image is already on the stream). The hydrated
1640
- * plain record is then loaded onto a fresh model instance so the result is a
1641
- * genuine `InstanceType` (like the read path's `{ hydrate }` factory option).
1642
- *
1643
- * The image side present per event kind mirrors DynamoDB Streams:
1644
- *
1645
- * - INSERT → `[null, new ]`
1646
- * - MODIFY → `[old, new ]`
1647
- * - REMOVE → `[old, null]`
1648
- */
1649
-
1650
- /**
1651
- * Parse a {@link ChangeEvent} into the `[oldRecord, newRecord]` tuple for the given
1652
- * model. Returns `[null, null]` when the event is not for this model (routing). The
1653
- * caller (`DDBModel.fromChange`) supplies the resolved metadata + class; this
1654
- * function is the runtime core and is deliberately model-name-string driven so
1655
- * `DDBModel.subscribe` can reuse it when routing a batch.
1656
- */
1657
- declare function parseChange<T extends object>(event: ChangeEvent, metadata: EntityMetadata, modelName: string, modelClass: new () => T): [T | null, T | null];
1658
-
1659
1283
  /**
1660
1284
  * Per-key cursor envelope for batched `range` (`list`) contract methods (issue
1661
1285
  * #62, CQRS single-service runtime; spec `docs/cqrs-contract.md`,
@@ -1737,39 +1361,6 @@ declare function encodePerKeyCursor(key: Record<string, unknown>, inner: string
1737
1361
  */
1738
1362
  declare function decodePerKeyCursor(cursor: string, expectedKey: Record<string, unknown>): string;
1739
1363
 
1740
- /**
1741
- * Creates a Linter pre-loaded with rules safe for Entity registration.
1742
- *
1743
- * Rules included: no-scan, require-limit, gsi-ambiguity, missing-gsi,
1744
- * relation-depth, same-partition-preset, plus the Epic #118 Phase 1 maintenance
1745
- * validators (issue #126): missing-context, 400kb, hot-partition, fan-out,
1746
- * multi-maintainer-same-row. The maintenance validators are no-ops for any
1747
- * relation that does not declare `write.maintainedOn`, so unannotated models are
1748
- * unaffected. query-boundary is excluded because it flags non-unique GSIs which
1749
- * are valid for list() operations; boundary enforcement is handled at runtime by
1750
- * the planner's boundary-check.
1751
- *
1752
- * Also includes cfn-schema-consistency (issue #169): a whole-table validator
1753
- * that rejects entities sharing a physical table with an ambiguous base
1754
- * KeySchema, inconsistently-shared GSI index names, or more than 20 unioned
1755
- * GSIs — the CFn deploy-consistency user-error class, caught statically at
1756
- * finalize. It is additive: a single entity on its own table with ≤ 20 GSIs is
1757
- * never affected.
1758
- */
1759
- declare function createDefaultLinter(): Linter;
1760
-
1761
- declare const noScanRule: LintRule;
1762
-
1763
- declare const requireLimitRule: LintRule;
1764
-
1765
- declare const queryBoundaryRule: LintRule;
1766
-
1767
- declare const gsiAmbiguityRule: LintRule;
1768
-
1769
- declare const missingGsiRule: LintRule;
1770
-
1771
- declare const relationDepthRule: LintRule;
1772
-
1773
1364
  declare function detectRelationFields(select: Record<string, unknown>, metadata: EntityMetadata): RelationMetadata[];
1774
1365
  declare function getImplicitKeyFields(select: Record<string, unknown>, metadata: EntityMetadata): string[];
1775
1366
 
@@ -2464,690 +2055,4 @@ type WriteOnlyDefinitions<D extends DefinitionMap> = {
2464
2055
  [K in keyof D]: D[K] extends OperationDefinition<infer _T, infer Op, infer _K, infer _S, infer _Ch, infer _P> ? Op extends 'put' | 'update' | 'delete' ? D[K] : OperationDefinition<DDBModel, 'put' | 'update' | 'delete', unknown, unknown, unknown, Record<string, ParamDescriptor>> : never;
2465
2056
  };
2466
2057
 
2467
- /**
2468
- * Declarative transaction definition DSL (issue #46, Python-bridge Phase 4).
2469
- *
2470
- * `defineTransaction(params, (tx, p) => { … })` captures a **single source of
2471
- * truth** for a `TransactWriteItems` batch: a parameter map plus a declarative
2472
- * instruction list (`tx.put` / `tx.update` / `tx.delete`, plus `tx.forEach` over
2473
- * an array param). The callback is evaluated at definition time with sentinel
2474
- * proxies in place of params / loop elements, so the recorded instructions carry
2475
- * **field-reference templates** (`{groupId}`, `{item.userId}`) rather than
2476
- * concrete values — exactly the shape the static planner (#42) turns into a
2477
- * serializable `transaction` op the TS and Python runtimes expand identically.
2478
- *
2479
- * ## Declarativity boundary (enforced — same soundness as #42 keys)
2480
- *
2481
- * The callback body may only:
2482
- * - call `tx.put/update/delete(Model, …)` with **field references** (from `p`
2483
- * or a `forEach` element) or **concrete literals** at scalar leaves;
2484
- * - call `tx.forEach(p.<arrayParam>, (el) => { … }, { when? })` whose body is
2485
- * itself only `tx.*` writes;
2486
- * - attach a declarative `when` (a small comparison over field refs) and/or a
2487
- * `condition` (the `{ notExists } | equality` subset, as for single writes).
2488
- *
2489
- * The same hardening that protects **key** positions (#42 `src/spec/symbolic.ts`)
2490
- * is applied to **value** positions (item / changes / condition values, `when`
2491
- * right-hand side). Value positions are in fact held to a *stricter* boundary
2492
- * than keys: a key may legitimately interpolate a field (`` `USER#${id}` ``), so
2493
- * coercion is allowed there and the differential template check is the boundary;
2494
- * a value leaf may **only** be a *direct* field reference or a concrete literal,
2495
- * so at a value position a faithful reference is **never coerced**. That single
2496
- * fact is the soundness boundary:
2497
- *
2498
- * 1. **Throwing sentinel Proxy.** Each param / element placeholder is a Proxy
2499
- * whose `get` trap whitelists only primitive coercion
2500
- * (`Symbol.toPrimitive` / `toString` / `valueOf`) and the brand / `token` /
2501
- * `origin` reads the planner needs, and **throws on every other property or
2502
- * method access**. So a *direct* transform on a value placeholder —
2503
- * `p.role.length`, `p.role[0]`, `p.role.toUpperCase()` — fails at the access
2504
- * site, exactly like a key sentinel. (Same first-line defense as #42.)
2505
- * 2. **Per-access coercion ledger (primary boundary).** Every minted field ref
2506
- * records each time it is coerced to a primitive (`Symbol.toPrimitive` /
2507
- * `toString` / `valueOf`). Because a faithful value reference is stored as
2508
- * the Proxy *object* and never coerced, **any** coercion of a value ref is
2509
- * positive proof the callback consumed the parameter into a transform, a
2510
- * branch, an interpolation, or a comparison — and the build is rejected. This
2511
- * is *access-site* accurate: it fires even when the same field is *also*
2512
- * referenced faithfully elsewhere in the item (so its token still surfaces),
2513
- * and it catches transforms that **converge to a constant or a shared marker
2514
- * fragment** — `String(p.role).slice(0,0)` → `''`, `.slice(0,3)` → a shared
2515
- * prefix, `[0]` / `.charAt(0)`, `.includes('Tx')` → a constant boolean, any
2516
- * `… + 'CONST'` built atop them — which a purely output-comparing check could
2517
- * not (the dropped field is masked by its faithful sibling, and the converged
2518
- * value is byte-identical across passes).
2519
- * 3. **Differential evaluation (secondary).** The callback is evaluated **twice**,
2520
- * each run delivering placeholders that coerce to a *different* per-field
2521
- * marker (the two markers share no common prefix and no common substring of
2522
- * length ≥ 2, and differ in length). Every recorded value leaf must be either
2523
- * (a) a faithful field reference (the Proxy object survived intact in *both*
2524
- * runs) or (b) a concrete literal byte-identical across both runs. This is a
2525
- * defense-in-depth layer behind the coercion ledger.
2526
- * 4. **Consumed-field check.** A placeholder field that the callback *accessed*
2527
- * but that never reached the recorded output — e.g. `(p.role === 'admin') ?
2528
- * 'A' : 'B'`, where `===` does **not** coerce (so the ledger does not fire),
2529
- * the comparison is `false`, and only a literal is emitted — is rejected: the
2530
- * param was silently dropped and a branch burned into the spec. (Same
2531
- * consumed-field accounting #42 uses for `kind === 'admin' ? … : …`.)
2532
- *
2533
- * Arbitrary JS, reads, value branching, arithmetic, coercion, or string
2534
- * transforms on a param / element placeholder are therefore rejected at build
2535
- * time, in **both** key and value positions — **never silently emitted as a
2536
- * wrong spec**. Unlike key positions, value positions have **no residual class**:
2537
- * because a faithful value ref is never coerced, even an identity-shaped
2538
- * transform (`String(p.x).slice(0)`, `.normalize()`, `.trim()`, `.replace('§',…)`
2539
- * on an absent substring) is rejected (it coerced the ref). The only operations
2540
- * that *do not* coerce a ref are (a) storing it directly and (b) the brand read;
2541
- * (a) is the supported faithful reference and (b) is internal — so the ledger has
2542
- * no false positives and no escape.
2543
- */
2544
-
2545
- declare const TX_REF_BRAND: unique symbol;
2546
- /**
2547
- * A captured reference to a parameter (`{name}`) or a `forEach` element field
2548
- * (`{item.<field>}`). Branded so the planner can distinguish a reference from a
2549
- * concrete literal, and so a stray reference cannot be silently coerced.
2550
- */
2551
- interface TransactionRef {
2552
- readonly [TX_REF_BRAND]: true;
2553
- /** The template token this reference renders to, e.g. `{groupId}`. */
2554
- readonly token: string;
2555
- /** Human-readable origin (for error messages), e.g. `param 'groupId'`. */
2556
- readonly origin: string;
2557
- }
2558
- /** Runtime guard: is `value` a {@link TransactionRef}? */
2559
- declare function isTransactionRef(value: unknown): value is TransactionRef;
2560
- /** A declarative comparison used by `when` (the only branching allowed). */
2561
- type WhenComparison = {
2562
- readonly op: 'eq';
2563
- readonly left: TransactionRef;
2564
- readonly right: unknown;
2565
- } | {
2566
- readonly op: 'ne';
2567
- readonly left: TransactionRef;
2568
- readonly right: unknown;
2569
- };
2570
- /**
2571
- * A single captured instruction inside a transaction. The three write operations
2572
- * (`put` / `update` / `delete`) mutate an item; `conditionCheck` (issue #81) is a
2573
- * **read-only assertion** on another keyed item — it carries a `key` and a
2574
- * **required** `condition` and never mutates, but its failure rolls the whole
2575
- * transaction back. It is the foundation for referential-integrity derivation
2576
- * (`requires <Entity> exists` → a `conditionCheck` with `attributeExists`).
2577
- */
2578
- interface TxWriteInstruction {
2579
- readonly kind: 'write';
2580
- readonly operation: 'put' | 'update' | 'delete' | 'conditionCheck';
2581
- readonly entity: EntityRef;
2582
- /** Put: the item structure (field → ref / literal). */
2583
- readonly item?: Record<string, unknown>;
2584
- /** Update / delete / conditionCheck: the key structure. */
2585
- readonly key?: Record<string, unknown>;
2586
- /** Update: the changes structure. */
2587
- readonly changes?: Record<string, unknown>;
2588
- /**
2589
- * The write / assertion condition (subset). Optional on `put` / `update` /
2590
- * `delete`; **required** on a `conditionCheck` (the assertion it makes).
2591
- */
2592
- readonly condition?: ConditionInput;
2593
- /** Optional declarative guard (skip this item when it does not hold). */
2594
- readonly when?: WhenComparison;
2595
- }
2596
- /** A `forEach` block expanding `body` once per element of an array param. */
2597
- interface TxForEachInstruction {
2598
- readonly kind: 'forEach';
2599
- /** The array-param name iterated. */
2600
- readonly source: string;
2601
- /** Optional per-element declarative guard. */
2602
- readonly when?: WhenComparison;
2603
- /** The (write-only) instructions emitted per element. */
2604
- readonly body: TxWriteInstruction[];
2605
- }
2606
- type TxInstruction = TxWriteInstruction | TxForEachInstruction;
2607
- /** Options accepted by `tx.put/update/delete`. */
2608
- interface TxWriteOptions {
2609
- readonly condition?: ConditionInput;
2610
- readonly when?: WhenComparison;
2611
- }
2612
- /**
2613
- * Options accepted by `tx.conditionCheck` (issue #81). The `condition` is the
2614
- * read-only assertion the check makes against the keyed item and is **required**
2615
- * — a ConditionCheck with no condition is meaningless. An optional `when` skips
2616
- * the check entirely when the guard does not hold.
2617
- */
2618
- interface TxConditionCheckOptions {
2619
- readonly condition: ConditionInput;
2620
- readonly when?: WhenComparison;
2621
- }
2622
- /** Options accepted by `tx.forEach`. */
2623
- interface TxForEachOptions {
2624
- readonly when?: WhenComparison;
2625
- }
2626
- /** A small comparison helper: `when.eq(ref, value)` / `when.ne(ref, value)`. */
2627
- declare const when: {
2628
- readonly eq: (left: TransactionRef, right: unknown) => WhenComparison;
2629
- readonly ne: (left: TransactionRef, right: unknown) => WhenComparison;
2630
- };
2631
- /** The transaction recorder handed to the callback as `tx`. */
2632
- interface TxRecorder {
2633
- put(model: ModelStatic<DDBModel>, item: Record<string, unknown>, options?: TxWriteOptions): void;
2634
- update(model: ModelStatic<DDBModel>, key: Record<string, unknown>, changes: Record<string, unknown>, options?: TxWriteOptions): void;
2635
- delete(model: ModelStatic<DDBModel>, key: Record<string, unknown>, options?: TxWriteOptions): void;
2636
- /**
2637
- * Record a **read-only** `ConditionCheck` assertion on a keyed item (issue
2638
- * #81): the item is not mutated, but `options.condition` must hold or the whole
2639
- * transaction is cancelled atomically. The foundation for referential-integrity
2640
- * derivation (`requires <Entity> exists` → `conditionCheck(Model, key, {
2641
- * condition: { attributeExists: 'PK' } })`).
2642
- */
2643
- conditionCheck(model: ModelStatic<DDBModel>, key: Record<string, unknown>, options: TxConditionCheckOptions): void;
2644
- forEach<E>(source: E, body: (element: ElementProxy<E>) => void, options?: TxForEachOptions): void;
2645
- }
2646
- /** The element proxy type inside a `forEach` body (fields → refs). */
2647
- type ElementProxy<E> = E extends Param<infer T> ? T extends (infer Item)[] ? {
2648
- readonly [K in keyof Item]: TransactionRef;
2649
- } : never : never;
2650
- /** The typed IR node produced by {@link defineTransaction}. */
2651
- interface TransactionDefinition {
2652
- /** @internal Marks this object as a transaction definition IR node. */
2653
- readonly __isTransactionDefinition: true;
2654
- /** Collected parameters: name → descriptor (array params carry `element`). */
2655
- readonly params: Readonly<Record<string, ParamDescriptor>>;
2656
- /** The captured, declarative instruction list. */
2657
- readonly instructions: readonly TxInstruction[];
2658
- }
2659
- /** A param map accepted by {@link defineTransaction}. */
2660
- type TransactionParamShape = Record<string, Param<unknown>>;
2661
- /** The `p` proxy type: each scalar param → ref; each array param → itself. */
2662
- type ParamProxy<P extends TransactionParamShape> = {
2663
- readonly [K in keyof P]: P[K] extends {
2664
- readonly kind: 'array';
2665
- } ? P[K] : TransactionRef;
2666
- };
2667
- /**
2668
- * Define a declarative transaction. The callback is evaluated **twice** with
2669
- * throwing value sentinels (one differential marker set per pass); its `tx.*`
2670
- * calls are recorded and the two passes are checked against each other so any
2671
- * non-declarative value (a transform, a value branch, a coercion escape) is
2672
- * rejected at build time — the same soundness #42 enforces for key positions.
2673
- *
2674
- * @param params A record of `param.*` placeholders (scalars and/or `param.array`).
2675
- * @param build `(tx, p) => void` — records the write instructions.
2676
- */
2677
- declare function defineTransaction<const P extends TransactionParamShape>(params: P, build: (tx: TxRecorder, p: ParamProxy<P>) => void): TransactionDefinition;
2678
- /**
2679
- * Group a record of transaction definitions into the IR consumed by the static
2680
- * planner (#42/#46). Validates each entry is a transaction definition.
2681
- */
2682
- declare function defineTransactions<const D extends Record<string, TransactionDefinition>>(definitions: D): D;
2683
-
2684
- /**
2685
- * Contract-layer serialization (issue #59, CQRS Contract layer, Epic #57;
2686
- * spec `docs/cqrs-contract.md`, "SSoT Schema").
2687
- *
2688
- * The Contract IR (#58, `src/define/contract.ts`) holds, per contract method, a
2689
- * resolved declarative {@link ContractMethodOp} plus the **decided facts** the
2690
- * planner derived (`resolution` / `inputArity` / `result`). This module
2691
- * **serializes** those facts into the JSON SSoT — it does **not** re-derive them:
2692
- *
2693
- * - The `contracts` map (contract name → {@link ContractSpec}) is layered **on
2694
- * top of** the existing `queries` / `commands` / `transactions`. Each method
2695
- * references one of them by name (`ContractName__methodName`), so the existing
2696
- * operation-spec shapes are unchanged and the current runtime keeps working.
2697
- * - The referenced operation spec is produced by **reusing** the proven
2698
- * {@link buildQuerySpec} / {@link buildCommandSpec} planners: a
2699
- * {@link ContractMethodOp} is translated back into the {@link AnyOperationDefinition}
2700
- * shape those planners consume (the contract's sentinel references become the
2701
- * `Param` placeholders the planner already understands), so the symbolic key
2702
- * evaluation, projection, relation chaining, and condition handling are shared
2703
- * — never re-implemented, never drifting.
2704
- *
2705
- * Everything emitted is **JSON-serializable** by construction (only strings /
2706
- * numbers / booleans / arrays / plain objects). A contract-free input emits no
2707
- * `contracts` / `contexts` keys, so the pre-#59 operations document is reproduced
2708
- * byte-for-byte (backward compatibility).
2709
- *
2710
- * ## What this issue serializes vs. defers
2711
- *
2712
- * The #58 IR captures a single declarative op per method with a boolean `select`
2713
- * projection; it does **not** model External Query / Query Composition (no
2714
- * `query(Contract.method, { from(...) })` primitive exists yet). So no #58
2715
- * contract produces a `compose`. The serializer nonetheless **supports** it: when
2716
- * a method op carries composition (a forward-compatible {@link ContractMethodOp}
2717
- * extension), it is emitted per the proposal's `compose` shape. The N+1 checker
2718
- * (#60), boundary lint (#61), and runtime execution (#62) are out of scope here —
2719
- * this is serialization + generator only.
2720
- */
2721
-
2722
- /**
2723
- * A contract as accepted by the serializer: either a resolved
2724
- * {@link QueryModelContract} or a {@link CommandModelContract} (the #58 factory
2725
- * output). The Key type is erased — the serializer reads the key **fields** off
2726
- * the resolved op / model metadata, not the phantom type.
2727
- */
2728
- type AnyModelContract = QueryModelContract<unknown, Record<string, QueryMethodSpec<unknown, unknown, unknown>>> | CommandModelContract<unknown, Record<string, CommandMethodSpec<unknown, unknown, unknown>>>;
2729
- /** A map of contract name → resolved contract IR (as passed to the generator). */
2730
- type ContractMap = Record<string, AnyModelContract>;
2731
- /**
2732
- * A context-ownership declaration as authored by the producer: context name →
2733
- * the Model (entity) and Contract names that belong to it. The serializer sorts
2734
- * the member lists deterministically; see {@link ContextSpec}.
2735
- */
2736
- interface ContextOwnership {
2737
- readonly models?: readonly string[];
2738
- readonly contracts?: readonly string[];
2739
- }
2740
- /** A map of context name → its membership (as passed to the generator). */
2741
- type ContextOwnershipMap = Record<string, ContextOwnership>;
2742
- /**
2743
- * The output of {@link buildContracts}: the `contracts` map and the
2744
- * **synthesized** operation specs each method references. The caller merges the
2745
- * synthesized `queries` / `commands` / `transactions` into the document's
2746
- * existing maps (a contract method's referenced op lives alongside hand-written
2747
- * definitions, addressed by name).
2748
- */
2749
- interface BuiltContracts {
2750
- readonly contracts: Record<string, ContractSpec>;
2751
- /** Synthesized read ops referenced by query contract methods. */
2752
- readonly queries: Record<string, QuerySpec>;
2753
- /** Synthesized write ops referenced by command contract methods (single form). */
2754
- readonly commands: Record<string, CommandSpec>;
2755
- /**
2756
- * Synthesized transactions referenced by command contract methods whose array
2757
- * form resolves to a `'transact'` batched write (issue #64). One transaction per
2758
- * such method, named `<Contract>__<method>__batch`: a single `forEach`-over-keys
2759
- * write item that the runtime expands once per key (≤25, atomic), reusing the
2760
- * proven declarative-transaction machinery (#46). Empty when no command method
2761
- * declares a `'transact'` batch.
2762
- */
2763
- readonly transactions: Record<string, TransactionSpec>;
2764
- }
2765
- /**
2766
- * Serialize a map of resolved contracts into the `contracts` SSoT map plus the
2767
- * synthesized operation specs each method references. Deterministic: contracts
2768
- * and methods are emitted in sorted-key order.
2769
- *
2770
- * @param contracts Contract name → resolved {@link QueryModelContract} /
2771
- * {@link CommandModelContract} (the #58 factory output). Empty → empty output.
2772
- * @throws if a contract method op cannot be serialized (a non-boolean projection
2773
- * slot, an unsupported write condition); or if a contract violates an N+1
2774
- * safety rule (#60, {@link assertContractN1Safe}) — an array into a `range`
2775
- * method, a "list under a list", or a `range` composed child.
2776
- */
2777
- declare function buildContracts(contracts?: ContractMap): BuiltContracts;
2778
- /**
2779
- * Serialize the context-ownership declarations into the SSoT `contexts` map.
2780
- * Member lists are sorted for determinism. An empty input yields an empty map
2781
- * (the caller then omits the key for backward compatibility).
2782
- */
2783
- declare function buildContexts(contexts?: ContextOwnershipMap): Record<string, ContextSpec>;
2784
-
2785
- /**
2786
- * Static parameterized operation-spec generation (issue #42, Phase 0b).
2787
- *
2788
- * Turns the parameterized definition IR (#41) into JSON-serializable
2789
- * {@link OperationSpec} / {@link CommandSpec} via **symbolic evaluation** of the
2790
- * key / GSI mapping functions. The result is deterministic and contains only
2791
- * `{param}` / `{result.field}` template placeholders, never concrete values.
2792
- *
2793
- * Relation chains in a read `select` become **multiple operations** wired with
2794
- * `resultPath` and `{result.*}` key templates, mirroring the runtime
2795
- * `relation-planner` policy: `hasMany` → `Query` + `begins_with`, `belongsTo` /
2796
- * `hasOne` → `BatchGetItem`.
2797
- */
2798
-
2799
- /** Build the {@link QuerySpec} for a single read definition. */
2800
- declare function buildQuerySpec(def: AnyOperationDefinition): QuerySpec;
2801
- /**
2802
- * Optional contract-layer inputs to {@link buildOperations} (issue #59). Both are
2803
- * absent on a pre-#59 (contract-free) build, in which case the produced document
2804
- * is byte-identical to the pre-#59 shape (no `contracts` / `contexts` keys).
2805
- */
2806
- interface ContractInputs {
2807
- /** Resolved contracts (publicQueryModel / publicCommandModel output). */
2808
- readonly contracts?: ContractMap;
2809
- /** Context-ownership declarations (context → member models / contracts). */
2810
- readonly contexts?: ContextOwnershipMap;
2811
- }
2812
- /**
2813
- * Build the operations document from grouped read (`queries`) and write
2814
- * (`commands`) definition maps, plus the optional CQRS contract layer (#59).
2815
- * All inputs are optional. Output is deterministic (definitions emitted in
2816
- * sorted-key order; the runtime resolves by name).
2817
- *
2818
- * The contract layer (#59) is layered **on top of** the existing specs: each
2819
- * contract method's underlying op is synthesized into `queries` / `commands` and
2820
- * referenced by name, and the `contracts` / `contexts` maps are emitted. A
2821
- * contract-free input (`contractInputs` empty / absent) reproduces the pre-#59
2822
- * document byte-for-byte — no `contracts` / `contexts` keys appear.
2823
- *
2824
- * @throws if a command carries a write condition outside the supported subset
2825
- * (`{ notExists }` or pure equality) — the bridge guard; or if a contract op
2826
- * name collides with a hand-written definition.
2827
- */
2828
- declare function buildOperations(queries?: DefinitionMap, commands?: DefinitionMap, transactions?: Record<string, TransactionDefinition>, contractInputs?: ContractInputs): OperationsDocument;
2829
-
2830
- /**
2831
- * Manifest generation (issue #42, Python-bridge Phase 0b).
2832
- *
2833
- * Produces the JSON-serializable {@link Manifest} from a {@link MetadataRegistry}
2834
- * snapshot: entity → table / physicalName / prefix / field types / key & GSI
2835
- * templates / relation metadata. Generation is **deterministic** — entities,
2836
- * fields, GSIs, and relations are emitted in a stable (sorted) order so the same
2837
- * registry always yields byte-identical JSON.
2838
- */
2839
-
2840
- /**
2841
- * Build the full {@link Manifest} from the {@link MetadataRegistry}.
2842
- *
2843
- * Every registered entity is included. Output ordering is deterministic
2844
- * (entities / fields / relations sorted by name, GSIs by index name).
2845
- */
2846
- declare function buildManifest(registry?: typeof MetadataRegistry): Manifest;
2847
-
2848
- /**
2849
- * N+1 static checker for the CQRS Contract layer (issue #60, Epic #57; proposal
2850
- * `docs/cqrs-contract.md`, "N+1 Safety (Static Restriction)").
2851
- *
2852
- * Whether a resolution is N+1-safe depends on **two** facts the planner already
2853
- * decided in #58 and #59 serialized into the SSoT — the checker **honors** them,
2854
- * it does **not** re-derive policy ("decide once, declare in the SSoT"):
2855
- *
2856
- * - `resolution` — `'point'` (target keys known → `BatchGetItem` / another
2857
- * contract's `get(keys[])`; coalesces) or `'range'` (target key set unknown →
2858
- * partition `Query`; one request per partition key).
2859
- * - `inputArity` / parent `cardinality` — how many keys are fed in. A `range`
2860
- * method is one query for one key but N queries for N keys.
2861
- *
2862
- * The rule (absolute, no opt-in escape hatch): **a `range` resolution is allowed
2863
- * only with single-key input.** Three forms are build-time errors:
2864
- *
2865
- * (a) **array into a `range` method** — a `range` method whose `inputArity` is
2866
- * not `'single'` (`'array'` / `'either'`). A `range` method must be
2867
- * `'single'`; anything else is an N partition-`Query` fan-out.
2868
- * (a′) **array into a unique-GSI `point` method** (issue #71) — a `point` method
2869
- * whose Key resolves via a **unique GSI** (a per-key `Query`, since
2870
- * `BatchGetItem` cannot read a GSI) but whose `inputArity` is not `'single'`.
2871
- * A base-table `point` coalesces a key array into one `BatchGetItem`, but a
2872
- * unique-GSI `point` would issue N `Query`s — an N+1 fan-out, the same shape
2873
- * as (a). graphddb's official spec does not include N+1-producing queries, so
2874
- * it is rejected at build time; the application-side loop is the escape (same
2875
- * philosophy as `range`).
2876
- * (b) **"list under a list"** — a `range` child nested under a parent step whose
2877
- * output cardinality is `'many'`. The composition's parent yields N records,
2878
- * so a `range` child fans out to N partition `Query`s.
2879
- * (c) **`compose` child that is `range`** — the cross-contract / composition form
2880
- * of (b): a composed (External Query) child declared `range` under a parent
2881
- * that can yield many. (Rule (b) and (c) are the same axis — a `range` child
2882
- * under a many-yielding parent — surfaced through nested model relations vs.
2883
- * cross-contract composition respectively.)
2884
- *
2885
- * `point` resolutions are always allowed (they coalesce). If a caller genuinely
2886
- * needs "just these few", it loops in its own application code (the proposal's
2887
- * `Promise.all(ids.map(...))`), keeping the N visible at the call site —
2888
- * the contract surface never hides a fan-out.
2889
- *
2890
- * ## Placement — build path, not the model `LintRule` framework
2891
- *
2892
- * This checker runs on the **contract build path** ({@link buildContracts} in
2893
- * `src/spec/contracts.ts`), where every other contract validation surfaces
2894
- * (#59's projection audit, write-condition guard, and the original inline
2895
- * `compose` rule all `throw` there). It operates on the serialized
2896
- * {@link ContractSpec} facts, not on {@link EntityMetadata}: the existing
2897
- * `src/linter/` `LintRule` framework is keyed on a single model's `EntityMetadata`
2898
- * (model relations / GSIs), which carries none of the contract `resolution` /
2899
- * `inputArity` / `compose` facts the N+1 rule needs. Surfacing the violation as a
2900
- * thrown build error — exactly as `relation/traversal.ts` `validateDepth` and the
2901
- * #59 contract validations do — fails the build the same way `inputArity`
2902
- * mismatches and `range` composed children already failed it.
2903
- *
2904
- * The cross-contract `range`-child form (c) and the nested-relation form (b) are
2905
- * only fully reachable once the composition DSL primitive
2906
- * (`query(Contract.method, { from() })`, owned by #63) lands; until then no #58
2907
- * DSL produces a `compose` node. The checker implements the full logic now so it
2908
- * is ready, and the forward forms are exercised by feeding synthesized SSoT nodes
2909
- * (exactly as #59's serializer tests do).
2910
- */
2911
-
2912
- /** A single N+1 rule violation, carrying the rule label and a clear message. */
2913
- interface ContractN1Violation {
2914
- /** Which of the N+1 forms was violated. */
2915
- readonly rule: 'array-into-range' | 'array-into-gsi-point' | 'list-under-list' | 'compose-range-under-many';
2916
- /** The offending contract name. */
2917
- readonly contract: string;
2918
- /** The offending method name. */
2919
- readonly method: string;
2920
- /** A clear, actionable error message (the same text the thrown error carries). */
2921
- readonly message: string;
2922
- }
2923
- /**
2924
- * Tells, for a query contract method name, whether its `point` read resolves via
2925
- * a **unique GSI** (a per-key `Query`) rather than the base-table primary key (a
2926
- * coalescible `GetItem` / `BatchGetItem`). Supplied by the serializer (issue #71),
2927
- * which recovers the fact from the method's synthesized read op (a root `Query`
2928
- * carrying an `indexName`). Absent → no method is treated as a GSI point (the
2929
- * pre-#71 default; e.g. synthesized-SSoT checker tests that exercise only the
2930
- * `range` / `compose` rules).
2931
- */
2932
- type IsGsiPointMethod = (methodName: string) => boolean;
2933
- /**
2934
- * Collect every N+1 violation in a single serialized {@link ContractSpec}.
2935
- * Command contracts carry no `resolution` / `compose` and are always N+1-safe
2936
- * (writes resolve to known keys), so only query contracts are inspected.
2937
- *
2938
- * @param isGsiPoint Optional predicate (issue #71): does the named method's
2939
- * `point` read resolve via a unique GSI? Used to reject array-into-GSI-point
2940
- * (rule a′). Defaults to "never" when not supplied.
2941
- */
2942
- declare function collectContractN1Violations(contractName: string, spec: ContractSpec, isGsiPoint?: IsGsiPointMethod): ContractN1Violation[];
2943
- /**
2944
- * Assert a single serialized contract is N+1-safe, throwing the first violation
2945
- * as a build error (mirroring `relation/traversal.ts` `validateDepth` and the
2946
- * #59 contract validations, which `throw` on the build path). Multiple violations
2947
- * are summarized in the thrown message so the build surfaces them all at once.
2948
- *
2949
- * @throws if any of the N+1 forms is present.
2950
- *
2951
- * @param isGsiPoint Optional predicate (issue #71) identifying unique-GSI `point`
2952
- * methods, so rule (a′) (array into a GSI point) can be enforced.
2953
- */
2954
- declare function assertContractN1Safe(contractName: string, spec: ContractSpec, isGsiPoint?: IsGsiPointMethod): void;
2955
-
2956
- /**
2957
- * Bounded-context boundary checker for the CQRS Contract layer (issue #61, Epic
2958
- * #57; spec `docs/cqrs-contract.md`, External Query section "Why it
2959
- * exists: boundary enforcement").
2960
- *
2961
- * The rule, stated in the proposal and the issue: a **Model is a private
2962
- * implementation detail of its bounded context; a Contract is the published
2963
- * interface**. Within its own context a contract resolves its own Models directly
2964
- * (internal `query` / `list` / `put` / `update` / `delete`). Across a context
2965
- * boundary it may depend on another context **only through that context's
2966
- * published Contract** (an External Query / Command). Reaching directly into a
2967
- * **foreign** Model is a **build-time error** — it couples one context to
2968
- * another's private storage shape and silently defeats the boundary the contexts
2969
- * declaration is meant to enforce.
2970
- *
2971
- * ## What "own" vs. "foreign" means here
2972
- *
2973
- * The decision is made entirely from the **context-ownership declaration** (#59,
2974
- * the `contexts` map: context name → `{ models, contracts }`). For each contract:
2975
- *
2976
- * - its **owning context** is the (unique) context whose `contracts` list names
2977
- * it; and
2978
- * - for every Model its method ops touch (the recorded {@link ContractMethodOp}
2979
- * `entity` refs, #58), that Model's **owning context** is the context whose
2980
- * `models` list names it.
2981
- *
2982
- * A method op against a Model owned by a **different** context than the contract's
2983
- * own is the violation. Three cases are deliberately **allowed**, never flagged:
2984
- *
2985
- * - the Model and the contract are in the **same** context (the normal internal
2986
- * case);
2987
- * - the **contract is in no declared context** — there is no boundary to enforce
2988
- * *from*, so the contract is unconstrained (a partial / incremental adoption of
2989
- * the contexts declaration must not turn unrelated contracts into errors);
2990
- * - the touched **Model is in no declared context** — an undeclared Model has no
2991
- * owner to protect, so it is not "foreign" to anyone. (Declaring the Model into
2992
- * a context is what opts it into boundary protection.)
2993
- *
2994
- * In short: the check fires **only** when both the contract *and* the foreign
2995
- * Model have declared, *different* owners. This is the least-surprising reading of
2996
- * a *partial* contexts declaration and keeps the rule purely additive — declaring
2997
- * more ownership can only ever surface *more* violations, never fewer.
2998
- *
2999
- * ## Placement — build path, not the model `LintRule` framework (decision B)
3000
- *
3001
- * This checker runs in **{@link buildOperations}** (`src/spec/operations.ts`),
3002
- * immediately before the {@link buildContracts} call — the seam where both the
3003
- * raw contract IR (the recorded op `entity` refs) and the `contexts` map are
3004
- * still available, alongside #59's projection audit, the write-condition guard,
3005
- * and #60's N+1 checker — every contract validation surfaces there as a thrown
3006
- * build error. It is **not** added to the `src/linter/` `LintRule`
3007
- * framework, even though the issue text suggests a `context-boundary` rule there,
3008
- * because that framework's contract — `check(metadata: EntityMetadata, registry)`
3009
- * — is keyed on a **single model's** {@link EntityMetadata} and carries **none** of
3010
- * the facts this rule needs:
3011
- *
3012
- * - which context a *contract* belongs to (a contract is not an `EntityMetadata`);
3013
- * - which Models a contract's *methods* touch (these live on the unserialized
3014
- * {@link ContractMethodOp} `entity` refs, not on any model's metadata);
3015
- * - the cross-cutting `contexts` map relating the two.
3016
- *
3017
- * A `LintRule` sees one model at a time and no contract facts at all, so a naive
3018
- * rule physically cannot observe a contract→foreign-Model reference. Bending the
3019
- * framework to carry contracts + contexts would be an invasive, parallel
3020
- * "rule kind" that no other rule uses — exactly the ugly refactor the brief warns
3021
- * against. Placing the check here is consistent with how #60 already resolved the
3022
- * identical tension (`src/spec/contract-n1-check.ts`, "Placement"), and it reads
3023
- * the **same facts the rule actually depends on** at the one point where contracts
3024
- * and contexts are both in hand. The boundary violation fails the build the same
3025
- * way an `inputArity` mismatch or a `range` composed child already does.
3026
- */
3027
-
3028
- /** A single context-boundary violation, carrying the offending facts + message. */
3029
- interface ContractBoundaryViolation {
3030
- /** The offending contract name. */
3031
- readonly contract: string;
3032
- /** The context that owns the offending contract. */
3033
- readonly contractContext: string;
3034
- /** The contract method whose op touched the foreign Model. */
3035
- readonly method: string;
3036
- /** The foreign Model (entity / model-class name) referenced directly. */
3037
- readonly foreignModel: string;
3038
- /** The context that owns the foreign Model. */
3039
- readonly foreignContext: string;
3040
- /** A clear, actionable error message (the same text the thrown error carries). */
3041
- readonly message: string;
3042
- }
3043
- /**
3044
- * Collect every context-boundary violation across a map of resolved contracts,
3045
- * given the context-ownership declaration. A violation is a contract method whose
3046
- * recorded op touches a Model owned by a **different** context than the contract's
3047
- * own (see the module doc for the precise own / foreign / undeclared rule).
3048
- *
3049
- * @param contracts Contract name → resolved {@link QueryModelContract} /
3050
- * {@link CommandModelContract} (the #58 factory output).
3051
- * @param contexts The context-ownership declaration (#59). When empty, no
3052
- * contract has a declared owner, so there are no boundaries to enforce → no
3053
- * violations.
3054
- * @throws if the contexts declaration claims a Model / Contract in two contexts
3055
- * (an ambiguous, self-contradictory declaration).
3056
- */
3057
- declare function collectContractBoundaryViolations(contracts: ContractMap, contexts: ContextOwnershipMap): ContractBoundaryViolation[];
3058
- /**
3059
- * Assert a map of resolved contracts respects bounded-context boundaries, throwing
3060
- * the first violation as a build error (mirroring #60's {@link assertContractN1Safe}
3061
- * and the other #59 contract validations, which `throw` on the build path).
3062
- * Multiple violations are summarized in the thrown message so the build surfaces
3063
- * them all at once.
3064
- *
3065
- * @param contracts Contract name → resolved contract IR.
3066
- * @param contexts The context-ownership declaration (#59).
3067
- * @throws if any contract directly references a foreign context's Model, or if the
3068
- * contexts declaration is ambiguous (a Model / Contract claimed twice).
3069
- */
3070
- declare function assertContractBoundaries(contracts: ContractMap, contexts: ContextOwnershipMap): void;
3071
-
3072
- /**
3073
- * Static planning for declarative transactions (issue #46, Phase 4).
3074
- *
3075
- * Turns a {@link TransactionDefinition} (captured by `defineTransaction`) into a
3076
- * serializable {@link TransactionSpec}. Each `tx.put/update/delete` becomes a
3077
- * templated {@link TransactionItemSpec}; a `tx.forEach` block marks its items
3078
- * with a `forEach` binding so the runtime expands them once per array-param
3079
- * element. Key templates are derived with the **same** symbolic key-mapping
3080
- * evaluator (#42 `evaluateKey`) the single-write planner uses — the
3081
- * declarativity of the field references is what lets that reuse work: every
3082
- * key / item / changes leaf is either a field reference (whose token the planner
3083
- * substitutes) or a concrete literal.
3084
- */
3085
-
3086
- /** Build the {@link TransactionSpec} for one transaction definition. */
3087
- declare function buildTransactionSpec(txName: string, def: TransactionDefinition): TransactionSpec;
3088
- /** Build the transactions map from a record of transaction definitions. */
3089
- declare function buildTransactions(transactions?: Record<string, TransactionDefinition>): Record<string, TransactionSpec>;
3090
-
3091
- /**
3092
- * Bridge guard (issue #42, Phase 0b).
3093
- *
3094
- * The Python bridge can only carry a **declarative, serializable subset** of
3095
- * graphddb. This module enforces that subset at build time:
3096
- *
3097
- * 1. **Write conditions** must be `{ notExists }`, an existence primitive
3098
- * (`{ attributeExists }` / `{ attributeNotExists }` on any field, issue #81),
3099
- * *or* pure field equality (mirroring `expression/condition-expression.ts`,
3100
- * which only emits `attribute_(not_)exists(...)` or `#f = :v` clauses). Any
3101
- * other condition shape is rejected — there is no serializable representation
3102
- * for it. {@link conditionInputToSpec} is the single place the IR-shaped input
3103
- * is mapped to the {@link ConditionSpec} subset.
3104
- * 2. The produced bundle must be **JSON-serializable** — no functions, classes,
3105
- * `Date`, `Set`, `Map`, `Symbol`, or non-finite numbers may leak into the
3106
- * spec. {@link assertJsonSerializable} walks the value and throws on any.
3107
- *
3108
- * (Note: the post-load TS predicate `refine` was removed in #49, so no guard for
3109
- * it is needed; see `docs/python-bridge.md`.)
3110
- */
3111
-
3112
- /**
3113
- * Assert a write {@link ConditionSpec} is within the supported subset. The spec
3114
- * type already constrains it to `notExists` | `attributeExists` |
3115
- * `attributeNotExists` | `equals`, so this defends against a malformed `equals`
3116
- * (empty / non-template values) or a blank existence field and gives a clear,
3117
- * single-source build-time error message for any future widening.
3118
- */
3119
- declare function assertSupportedCondition(commandName: string, condition: ConditionSpec): void;
3120
- /**
3121
- * Walk an arbitrary value and throw if it contains anything that does not
3122
- * survive `JSON.stringify` round-tripping as itself (functions, symbols,
3123
- * `undefined`, `Date`, `Map`, `Set`, class instances, non-finite numbers).
3124
- */
3125
- declare function assertJsonSerializable(value: unknown, path?: string): void;
3126
- /** Convenience: assert an entire {@link BridgeBundle} is JSON-serializable. */
3127
- declare function assertBundleSerializable(bundle: BridgeBundle): void;
3128
-
3129
- /**
3130
- * Static parameterized planner: serializable OperationSpec + manifest + bridge
3131
- * guard (issue #42, Python-bridge Phase 0b). Public surface.
3132
- *
3133
- * The CLI / file output is #43's responsibility; this module stops at the
3134
- * **generation functions** producing the typed, JSON-serializable
3135
- * `{ manifest, operations }` bundle.
3136
- */
3137
-
3138
- /**
3139
- * Build the full `{ manifest, operations }` bridge bundle from grouped query /
3140
- * command definition maps. The bundle is typed and JSON-serializable; the bridge
3141
- * guard runs (unsupported write conditions throw during `buildOperations`, and
3142
- * the whole bundle is asserted JSON-serializable here).
3143
- *
3144
- * @param queries Read definitions (`defineQueries(...)` output). Optional.
3145
- * @param commands Write definitions (`defineCommands(...)` output). Optional.
3146
- * @param registry Metadata source (defaults to the global registry).
3147
- * @param transactions Declarative transactions (`defineTransactions(...)`). Optional.
3148
- * @param contractInputs The CQRS contract layer (#59): resolved contracts +
3149
- * context-ownership. Optional — absent reproduces the pre-#59 document.
3150
- */
3151
- declare function buildBridgeBundle(queries?: DefinitionMap, commands?: DefinitionMap, registry?: typeof MetadataRegistry, transactions?: Record<string, TransactionDefinition>, contractInputs?: ContractInputs): BridgeBundle;
3152
-
3153
- export { AggregateOptions, AggregateValue, type AnyModelContract, AnyOperationDefinition, BATCH_GET_MAX_KEYS, BATCH_WRITE_MAX_ITEMS, BatchExecOptions, BatchGetExecInput, BatchWriteExecItem, BridgeBundle, type BuiltContracts, CdcEmulator, CdcEmulatorOptions, ChangeEvent, ChangeHandler, ClientManager, type CollectParams, CommandMethodSpec, CommandModelContract, CommandSpec, ConcurrentRecomputeRef, type ConditionExpressionResult, ConditionInput, ConditionSpec, type ContextOwnership, type ContextOwnershipMap, ContextSpec, type ContractBoundaryViolation, type ContractInputs, type ContractMap, type ContractN1Violation, ContractSpec, CtxModel, DDBModel, DefinitionMap, DeleteInput, type DriftReport, DynamoDBOperation, DynamoExecutor, DynamoType, EDGE_WRITES_MARKER, type EdgeLifecycle, type EdgeWriteDeclaration, type EdgeWriteRecorder, type EdgeWritesDefinition, EntityMetadata, EntityRef, EventLog, ExecutionPlan, Executor, ExecutorResult, type ExplainInput, FaultSpec, FieldMetadata, FieldOptions, type FilterExpressionResult, GsiDefinition, type HasManyVersionedCallback, type HasManyVersionedOptions, type HasOneVersionedCallback, type HasOneVersionedOptions, Item, KeyDefinition, type LintResult, type LintRule, Linter, type ListInput, type ListOptions, MAINT_OUTBOX_PK_PREFIX, MAX_TRANSACT_ITEMS, MaintainConsistency, MaintainEffect, MaintainEvent, MaintainUpdateMode, type MaintainedFromCallback, type MaintainedFromOptions, MaintenanceDrain, type MaintenanceDrainOptions, type MaintenanceRebuildOptions, MaintenanceRebuilder, Manifest, MembershipPredicate, MembershipPredicateOp, MetadataRegistry, Middleware, type ModelOptions, ModelStatic, OLD_VALUE_NAMESPACE, OperationDefinition, OperationsDocument, Param, ParamDescriptor, type Parameterize, PartialQueryKeyOf, type PerKeyCursorEnvelope, type PlanInput, PrimaryKeyOf, type ProjectionResult, ProjectionTransform, type ProjectionValue, PutInput, QueryMethodSpec, QueryModelContract, type QueryOptions$1 as QueryOptions, QuerySpec, RawCondition, ReadExecOptions, ReadParams, ReadRequestCtx, ReadRequestKind, type RebuildResult, RelationMetadata, RelationOptions, type RelationTraversalOptions, ReplayOptions, RequestContext, ResolvedKey, RetryOverride, RetryPolicy, RetryingExecutor, SelectableOf, type SelfProxy, type SelfRef, ShardId, type SourceProxy, type SourceRef, TableMapping, TransactWriteExecItem, type TransactionDefinition, TransactionItemSpec, type TransactionParamShape, type TransactionRef, TransactionSpec, type TxConditionCheckOptions, type TxForEachInstruction, type TxForEachOptions, type TxInstruction, type TxRecorder, type TxWriteInstruction, type TxWriteOptions, UniqueQueryKeyOf, type UpdateExpressionResult, UpdateInput, type VersionedHistoryOptions, type VersionedLatestOptions, ViewDefinition, type WhenComparison, WriteDefinitionOptions, WriteExecOptions, WriteResult, aggregate, assertBundleSerializable, assertContractBoundaries, assertContractN1Safe, assertJsonSerializable, assertSupportedCondition, belongsTo, binary, boolean, buildBridgeBundle, buildConditionExpression, buildContexts, buildContracts, buildManifest, buildOperations, buildProjection, buildQuerySpec, buildTransactionSpec, buildTransactions, buildUpdateExpression, cdcProjected, collectContractBoundaryViolations, collectContractN1Violations, compileFilterExpression, count, createCdcEmulator, createDefaultLinter, createMaintenanceDrain, createMaintenanceDrainHandler, createMaintenanceRebuilder, datetime, decodeCursor, decodePerKeyCursor, defineCommands, defineDelete, defineList, definePut, defineQueries, defineQuery, defineTransaction, defineTransactions, defineUpdate, deriveEdgeWriteItems, deriveEdgeWriteItemsFor, deriveModelEdgeWriteItems, derivePrefix, detectRelationFields, edgeWrites, embedded, encodeCursor, encodePerKeyCursor, evaluateFilter, execute, executeDeclarativeTransaction, executeExplain, executeList, executeQuery, expandTransaction, field, getEdgeWrites, getImplicitKeyFields, gsiAmbiguityRule, hasMany, hasOne, hydrate, isEdgeWritesDefinition, isSelectBuilder, isTransactionRef, list, literal, maintainedFrom, map, max, missingGsiRule, model, noScanRule, number, numberSet, parseChange, plan, queryBoundaryRule, relationDepthRule, requireLimitRule, resolveKey, resolveRelations, serializeContractKey, serializeFieldValue, string, stringSet, ttl, validateDepth, validateGsiAmbiguity, when, whenMember };
2058
+ export { AggregateOptions, AggregateValue, BATCH_GET_MAX_KEYS, BATCH_WRITE_MAX_ITEMS, BatchExecOptions, BatchGetExecInput, BatchWriteExecItem, ClientManager, type CollectParams, type ConditionExpressionResult, CtxModel, DDBModel, DefinitionMap, DeleteInput, type DriftReport, DynamoDBOperation, DynamoExecutor, DynamoType, EDGE_WRITES_MARKER, type EdgeLifecycle, type EdgeWriteDeclaration, type EdgeWriteRecorder, type EdgeWritesDefinition, EntityMetadata, ExecutionPlan, Executor, ExecutorResult, type ExplainInput, FieldMetadata, FieldOptions, type FilterExpressionResult, GsiDefinition, type HasManyVersionedCallback, type HasManyVersionedOptions, type HasOneVersionedCallback, type HasOneVersionedOptions, Item, KeyDefinition, type ListInput, type ListOptions, MAX_TRANSACT_ITEMS, MaintainConsistency, MaintainEffect, MaintainEvent, MaintainUpdateMode, type MaintainedFromCallback, type MaintainedFromOptions, type MaintenanceRebuildOptions, MaintenanceRebuilder, Manifest, MembershipPredicate, MembershipPredicateOp, Middleware, type ModelOptions, ModelStatic, OLD_VALUE_NAMESPACE, OperationDefinition, Param, ParamDescriptor, type Parameterize, PartialQueryKeyOf, type PerKeyCursorEnvelope, type PlanInput, PrimaryKeyOf, type ProjectionResult, ProjectionTransform, type ProjectionValue, PutInput, type QueryOptions$1 as QueryOptions, RawCondition, ReadExecOptions, ReadParams, ReadRequestCtx, ReadRequestKind, type RebuildResult, RelationMetadata, RelationOptions, type RelationTraversalOptions, RequestContext, ResolvedKey, RetryOverride, RetryPolicy, RetryingExecutor, SelectableOf, type SelfProxy, type SelfRef, type SourceProxy, type SourceRef, TableMapping, TransactWriteExecItem, TransactionItemSpec, TransactionSpec, UniqueQueryKeyOf, type UpdateExpressionResult, UpdateInput, type VersionedHistoryOptions, type VersionedLatestOptions, ViewDefinition, WriteDefinitionOptions, WriteExecOptions, WriteResult, aggregate, belongsTo, binary, boolean, buildConditionExpression, buildProjection, buildUpdateExpression, cdcProjected, compileFilterExpression, count, createMaintenanceRebuilder, datetime, decodeCursor, decodePerKeyCursor, defineCommands, defineDelete, defineList, definePut, defineQueries, defineQuery, defineUpdate, deriveEdgeWriteItems, deriveEdgeWriteItemsFor, deriveModelEdgeWriteItems, derivePrefix, detectRelationFields, edgeWrites, embedded, encodeCursor, encodePerKeyCursor, evaluateFilter, execute, executeDeclarativeTransaction, executeExplain, executeList, executeQuery, expandTransaction, field, getEdgeWrites, getImplicitKeyFields, hasMany, hasOne, hydrate, isEdgeWritesDefinition, isSelectBuilder, list, literal, maintainedFrom, map, max, model, number, numberSet, plan, resolveKey, resolveRelations, serializeContractKey, serializeFieldValue, string, stringSet, ttl, validateDepth, validateGsiAmbiguity, whenMember };