@dbsp/adapter-pgsql 5.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2727 @@
1
+ import * as _dbsp_types from '@dbsp/types';
2
+ import { DialectCapabilities, IndexIR, ModelIR, DbCasing, NormalizedManagedStep, DeclarableResourceAddress, TableIR, CatalogueIdentity, SequenceIR, LedgerPayload, ResourceAddress, LedgerAddress, HierarchyIR, PhysicalNameInventory, Adapter, AdapterLogger, AdapterCapabilities, ConnectionAvailability, PlanReport, CompiledNqlQuery, CompileOptions, CompiledQuery, CompileResultWithIncludes, SubqueryIncludeInfo, ExpressionIntent, InsertIntent, InsertFromIntent, UpdateIntent, BatchUpdateIntent, DeleteIntent, UpsertIntent, UpsertFromIntent, RecursivePlanReport, CteQueryIntent, SetOperationIntent, DumpMeta, Dump, AdapterStreamOptions, PinnedConnectionOptions, TransactionOptions, LedgerHome, DurableIntentRecord, TransitionRunAuthorization, TransitionRunJournal, ProvenPlanShape, LedgerReservationRow, LedgerIdentity, LedgerChainMember, LedgerMarkerState, DeclarationSet, ReinitializePreflightReport, OutcomeClaimPlan, DestructiveDecision, LedgerEventKind, OutcomeVacancy, OutcomeProtocolRefusal, ClaimBundleStatement, ControllerIdentity, AdmittedOutcomeClaim, ClaimToken, OutcomeIndeterminateRecoveryEvidence, OutcomeRecoveryEffect, OutcomeRecoveryClassification, ScopedApprovalSet, OutcomeRecoveryReadBack, OutcomeClaimAdmission } from '@dbsp/types';
3
+ import { Pool, PoolClient } from 'pg';
4
+ import { IndexInfo, TruncateOptions, VacuumOptions, AlterColumnOptions, CreateIndexOptions, DropIndexOptions, TransitionRunPersister, ValidatedManagedStepManifest } from '@dbsp/core';
5
+ import { AdmittedDestructiveOutcomeClaim, DurablyLoadedRun } from '@dbsp/core/internal';
6
+
7
+ /**
8
+ * Default primary key column name used as convention fallback
9
+ * when schema metadata doesn't provide an explicit PK.
10
+ *
11
+ * Consumers (handlers, compiler) must NOT use this directly —
12
+ * they use `requiredColumn()` to throw on missing data.
13
+ * Only convention mappers (extractors, introspection) should reference this.
14
+ */
15
+ declare const DEFAULT_PK_COLUMN = "id";
16
+ /**
17
+ * Derive a foreign key column name from a table name and the PK column it references.
18
+ *
19
+ * Convention: `${singularTableName}_${pkColumnName}`
20
+ * e.g. (authors, id) → author_id, (categories, id) → category_id
21
+ *
22
+ * Consumers should use `deriveFkColumnName` from CompilerContext or options
23
+ * for configurable behavior.
24
+ */
25
+ type FkColumnDerivation = (tableName: string, pkColumnName: string) => string;
26
+ declare const defaultFkDerivation: FkColumnDerivation;
27
+
28
+ /**
29
+ * NamingPlugin - Identifier transformation between model and database naming conventions
30
+ *
31
+ * Inspired by Kysely's CamelCasePlugin architecture.
32
+ * The plugin transforms identifiers bidirectionally:
33
+ * - toDatabase: model name (camelCase) → database name (snake_case)
34
+ * - toModel: database name (snake_case) → model name (camelCase)
35
+ */
36
+ /**
37
+ * Interface for naming convention transformation plugins
38
+ */
39
+ interface NamingPlugin {
40
+ /**
41
+ * Transform a model identifier to database format
42
+ * Example: "createdAt" → "created_at"
43
+ */
44
+ toDatabase(identifier: string): string;
45
+ /**
46
+ * Transform a database identifier to model format
47
+ * Example: "created_at" → "createdAt"
48
+ */
49
+ toModel(identifier: string): string;
50
+ }
51
+ /**
52
+ * Identity plugin - no transformation
53
+ * Use this when model and database naming conventions match
54
+ */
55
+ declare class IdentityNamingPlugin implements NamingPlugin {
56
+ toDatabase(identifier: string): string;
57
+ toModel(identifier: string): string;
58
+ }
59
+ /**
60
+ * CamelCase ↔ snake_case transformation plugin
61
+ *
62
+ * Follows the same logic as Kysely's CamelCasePlugin:
63
+ * - Handles consecutive uppercase letters (e.g., "parseJSON" → "parse_json")
64
+ * - Handles numbers (e.g., "field1Name" → "field1_name")
65
+ * - Preserves leading underscores
66
+ */
67
+ declare class CamelCaseNamingPlugin implements NamingPlugin {
68
+ /**
69
+ * camelCase → snake_case
70
+ */
71
+ toDatabase(identifier: string): string;
72
+ /**
73
+ * snake_case → camelCase
74
+ */
75
+ toModel(identifier: string): string;
76
+ }
77
+ /**
78
+ * Singleton instances for convenience
79
+ */
80
+ declare const identityNaming: IdentityNamingPlugin;
81
+ declare const camelCaseNaming: CamelCaseNamingPlugin;
82
+ /**
83
+ * Get a naming plugin by DbCasing (intuitive semantics).
84
+ * - `'snake_case'`: DB uses snake_case → CamelCaseNamingPlugin (transforms to camelCase)
85
+ * - `'camelCase'`: DB uses camelCase → IdentityNamingPlugin (no transform)
86
+ * - `'preserve'`: No transformation → IdentityNamingPlugin
87
+ */
88
+ declare function getNamingPluginForDbCasing(casing: 'snake_case' | 'camelCase' | 'preserve'): NamingPlugin;
89
+
90
+ type IndexRenderKey = {
91
+ readonly column?: string | undefined;
92
+ readonly expression?: string | undefined;
93
+ readonly opclass?: string | undefined;
94
+ };
95
+ type IndexRenderSpec = {
96
+ readonly name: string;
97
+ readonly table: string;
98
+ readonly schema?: string | undefined;
99
+ readonly unique: boolean;
100
+ readonly method?: string | undefined;
101
+ readonly keys: readonly IndexRenderKey[];
102
+ readonly include?: readonly string[] | undefined;
103
+ readonly nullsNotDistinct?: boolean | undefined;
104
+ readonly with?: Readonly<Record<string, unknown>> | undefined;
105
+ readonly where?: string | undefined;
106
+ /** The in-process index value that owns a deparsed `where` predicate. */
107
+ readonly whereSource?: IndexIR | undefined;
108
+ readonly concurrently?: boolean | undefined;
109
+ readonly ifNotExists?: boolean | undefined;
110
+ };
111
+ type IndexCapabilityContext = {
112
+ readonly caps: DialectCapabilities;
113
+ readonly targetVersion?: string | undefined;
114
+ };
115
+ type IndexFeature = 'INCLUDE' | 'PARTIAL INDEX' | 'EXPRESSION INDEX' | 'INDEX METHOD' | 'OPCLASS' | 'NULLS NOT DISTINCT';
116
+ declare class IndexFeatureUnsupportedError extends Error {
117
+ readonly indexName: string;
118
+ readonly unsupportedFeatures: readonly IndexFeature[];
119
+ constructor(indexName: string, unsupportedFeatures: readonly IndexFeature[], message: string);
120
+ }
121
+ declare class AutoIncrementTransitionUnsupportedError extends Error {
122
+ readonly table: string;
123
+ readonly column: string;
124
+ readonly direction: 'enable' | 'disable' | 'retype' | 'unknown';
125
+ constructor(table: string, column: string, direction: 'enable' | 'disable' | 'retype' | 'unknown');
126
+ }
127
+ declare function assertCreateIndexSupported(spec: IndexRenderSpec, ctx?: IndexCapabilityContext): void;
128
+ declare function assertCreateIndexesSupported(specs: readonly IndexRenderSpec[], ctx?: IndexCapabilityContext): void;
129
+ declare function renderCreateIndex(spec: IndexRenderSpec, ctx?: IndexCapabilityContext): string;
130
+
131
+ /**
132
+ * DDL Generator - Generates PostgreSQL DDL statements from ModelIR
133
+ *
134
+ * Generates SQL strings directly for better compatibility and control.
135
+ * Two-pass strategy handles circular FK dependencies.
136
+ *
137
+ * @module ddl/ddl-generator
138
+ */
139
+
140
+ interface GenerateDDLOptions$1 {
141
+ /** Include DROP TABLE IF EXISTS statements before CREATE TABLE */
142
+ readonly includeDropStatements?: boolean;
143
+ /**
144
+ * Database schema name (e.g., 'public', 'tenant_123').
145
+ * Required when emitted DDL would otherwise mix non-default target-scoped
146
+ * custom types/enums with unqualified table SQL.
147
+ */
148
+ readonly schemaName?: string;
149
+ /**
150
+ * Automatically create indexes on foreign key columns.
151
+ * FK columns are frequently used in JOINs, so indexing is a best practice.
152
+ * @default true
153
+ */
154
+ readonly fkAutoIndex?: boolean;
155
+ /** Naming plugin for logical-model callers. Physical models omit this option. */
156
+ readonly naming?: NamingPlugin;
157
+ /** Dialect capabilities — unsupported index features throw during DDL generation */
158
+ readonly dialectCapabilities?: DialectCapabilities;
159
+ }
160
+ /**
161
+ * Generate DDL statements from a ModelIR schema.
162
+ *
163
+ * Uses a two-pass approach to handle circular FK dependencies:
164
+ * 1. CREATE TABLE (without FK constraints)
165
+ * 2. ALTER TABLE ADD CONSTRAINT for foreign keys
166
+ * 3. CREATE INDEX (explicit + auto-generated for FKs)
167
+ *
168
+ * @param schema - The ModelIR schema to generate DDL from
169
+ * @param options - Optional configuration
170
+ * @returns Array of DDL statements in dependency order
171
+ */
172
+ declare function generateDDL$1(schema: ModelIR, options?: GenerateDDLOptions$1): string[];
173
+ declare function generateCreateIndex(tableName: string, idx: IndexIR, schemaName: string | undefined, context?: IndexCapabilityContext, ifNotExists?: boolean): string;
174
+ /**
175
+ * Returns whether the PostgreSQL DDL generator can emit this IndexIR.
176
+ *
177
+ * Keep this as the single representability predicate for generated schema
178
+ * omission and destructive-drop classification: both sides must agree on the
179
+ * exact validation surface used by generateCreateIndex().
180
+ */
181
+ declare function canGenerateCreateIndex(tableName: string, idx: IndexIR, schemaName?: string | undefined): boolean;
182
+
183
+ /**
184
+ * Schema Comparison Engine (DDL-PROV Block 1)
185
+ *
186
+ * Compares two ModelIRs (schema definition vs database state)
187
+ * and produces a structured diff of changes needed.
188
+ *
189
+ * @module schema-diff
190
+ */
191
+
192
+ type ChangeKind = 'create_table' | 'drop_table' | 'readdress_table' | 'add_column' | 'drop_column' | 'alter_column_type' | 'alter_column_nullable' | 'alter_column_default' | 'alter_column_unique' | 'alter_column_auto_increment' | 'add_primary_key' | 'drop_primary_key' | 'add_foreign_key' | 'drop_foreign_key' | 'alter_foreign_key' | 'validate_constraint' | 'create_index' | 'drop_index' | 'add_check_constraint' | 'drop_check_constraint' | 'create_enum' | 'alter_enum_add_value' | 'drop_enum' | 'alter_column_collation' | 'alter_column_identity' | 'add_comment' | 'drop_comment' | 'create_extension' | 'drop_extension' | 'create_sequence' | 'alter_sequence' | 'drop_sequence' | 'enable_rls' | 'disable_rls' | 'create_policy' | 'drop_policy';
193
+ interface SchemaChange {
194
+ readonly kind: ChangeKind;
195
+ readonly table: string;
196
+ readonly column?: string;
197
+ readonly destructive: boolean;
198
+ readonly details: string;
199
+ /** Additional metadata for SQL generation */
200
+ readonly meta?: Readonly<Record<string, unknown>>;
201
+ }
202
+ interface DiffSummary {
203
+ readonly tables: {
204
+ readonly added: number;
205
+ readonly dropped: number;
206
+ };
207
+ readonly columns: {
208
+ readonly added: number;
209
+ readonly dropped: number;
210
+ readonly altered: number;
211
+ };
212
+ readonly indexes: {
213
+ readonly added: number;
214
+ readonly dropped: number;
215
+ };
216
+ readonly constraints: {
217
+ readonly added: number;
218
+ readonly dropped: number;
219
+ readonly altered: number;
220
+ };
221
+ }
222
+ interface SchemaDiff {
223
+ readonly changes: readonly SchemaChange[];
224
+ readonly hasDestructive: boolean;
225
+ readonly summary: DiffSummary;
226
+ }
227
+ interface CompareSchemataOptions$1 {
228
+ /** Internal compatibility metadata; public physical-model comparison owns schema. */
229
+ readonly schema?: string;
230
+ /** Internal callers must already pass physical names; this value is ignored. */
231
+ dbCasing?: DbCasing;
232
+ /** Authored standalone-sequence names retained by the physical-model boundary. */
233
+ readonly declaredSequenceNames?: ReadonlyMap<string, string>;
234
+ /** Dialect capabilities — comparisons for unsupported features will be skipped */
235
+ readonly dialectCapabilities?: DialectCapabilities;
236
+ /**
237
+ * When `true`, extensions present in the live DB but absent from the model
238
+ * schema are silently ignored — no `drop_extension` change is emitted for them.
239
+ * Only extensions explicitly declared in the model are managed (created if missing).
240
+ *
241
+ * Use this when the database image pre-installs extensions that the application
242
+ * schema does not own (e.g. pgvector, pg_search bundled in a custom Postgres image).
243
+ * Default: `false` (full-sync behaviour — unmanaged DB extensions produce a
244
+ * `drop_extension` entry).
245
+ */
246
+ readonly ignoreUnmanagedExtensions?: boolean;
247
+ /**
248
+ * Strict compile-only mode for callers that require convergence guarantees.
249
+ *
250
+ * `compareSchemata()` is intentionally pure and cannot ask PostgreSQL to
251
+ * canonicalise raw-SQL expression surfaces. By default it keeps the historic
252
+ * best-effort verbatim comparison for column defaults, CHECK expressions,
253
+ * partial-index predicates, and index expressions. Set this flag to throw when either model
254
+ * contains one of those surfaces so a caller cannot accidentally rely on a
255
+ * compile-only diff for a convergence-sensitive check.
256
+ *
257
+ * Live PostgreSQL callers should use `comparePgsqlDatabaseSchema()`, which
258
+ * canonicalises CHECK constraint expressions, column defaults, and partial-index predicates before calling this function.
259
+ * Under that live mode, each side is canonicalised independently; rejected
260
+ * predicates refuse the migration and infrastructure fallback uses both raw
261
+ * models. This does not prove
262
+ * that the resulting migration is executable.
263
+ * Index expressions are not canonicalised by the live helper and are rejected
264
+ * there when this strict flag is set.
265
+ */
266
+ readonly requireExpressionCanonicalization?: boolean;
267
+ }
268
+ declare class ExpressionCanonicalizationUnavailableError extends Error {
269
+ readonly surfaces: readonly string[];
270
+ constructor(surfaces: readonly string[]);
271
+ }
272
+ type ReferencedKeyKind = 'unique_index' | 'primary_key' | 'column_unique';
273
+ interface ReferencedKeyRemovalConflict {
274
+ readonly keyKind: ReferencedKeyKind;
275
+ readonly table: string;
276
+ readonly keyColumns: readonly string[];
277
+ readonly keyName?: string;
278
+ readonly referencingTable: string;
279
+ readonly foreignKeyColumns: readonly string[];
280
+ }
281
+ /**
282
+ * Refusal raised when executable UP SQL would remove a key a foreign key may
283
+ * depend on. Only foreign keys visible in the compared model are detected, so
284
+ * a single-schema comparison cannot see a foreign key whose source table is in
285
+ * another schema. A hand-built `SchemaDiff` without the comparison annotation
286
+ * is not covered.
287
+ */
288
+ declare class ReferencedKeyRemovalError extends Error {
289
+ readonly conflicts: readonly ReferencedKeyRemovalConflict[];
290
+ constructor(conflicts: readonly ReferencedKeyRemovalConflict[]);
291
+ }
292
+ /**
293
+ * Compare two ModelIRs and produce a structured diff.
294
+ *
295
+ * @param schema - The desired schema (from definition)
296
+ * @param db - The current database state (from introspection)
297
+ * @param options - Optional comparison settings (e.g. dbCasing)
298
+ * @returns SchemaDiff with all changes needed to bring DB in sync with schema
299
+ */
300
+ declare function compareSchemata$1(schema: ModelIR, db: ModelIR, options?: CompareSchemataOptions$1): SchemaDiff;
301
+ /** Collect comparison annotations from the changes an executable path selected. */
302
+ declare function collectReferencedKeyRemovalConflicts(changes: readonly SchemaChange[]): readonly ReferencedKeyRemovalConflict[];
303
+
304
+ type Address = DeclarableResourceAddress & {
305
+ readonly scope: 'schema' | 'database';
306
+ };
307
+ type GeneratedConstraintPostcondition = {
308
+ readonly type: 'p' | 'u';
309
+ readonly columns: readonly string[];
310
+ readonly deferrable: boolean;
311
+ readonly initiallyDeferred: boolean;
312
+ readonly enforced: boolean;
313
+ } | {
314
+ readonly type: 'f';
315
+ readonly columns: readonly string[];
316
+ readonly references: {
317
+ readonly schema: string;
318
+ readonly table: string;
319
+ readonly columns: readonly string[];
320
+ };
321
+ readonly onDelete: GeneratedForeignKeyAction;
322
+ readonly onUpdate: GeneratedForeignKeyAction;
323
+ readonly deferrable: boolean;
324
+ readonly initiallyDeferred: boolean;
325
+ readonly enforced: boolean;
326
+ readonly notValid: boolean;
327
+ } | {
328
+ readonly type: 'c';
329
+ /** The ModelIR CHECK expression, never a rendered constraint definition. */
330
+ readonly expression: string;
331
+ readonly notValid: boolean;
332
+ };
333
+ /** The semantic FK actions PostgreSQL can represent in pg_constraint. */
334
+ type GeneratedForeignKeyAction = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';
335
+ type GeneratedIndexPostcondition = {
336
+ /** The identity is persisted separately from the rendered CREATE INDEX SQL. */
337
+ readonly schema: string;
338
+ readonly table: string;
339
+ readonly name: string;
340
+ /** PostgreSQL exposes an omitted method as btree; make that expectation explicit. */
341
+ readonly method: string;
342
+ readonly unique: boolean;
343
+ readonly valid: true;
344
+ readonly ready: true;
345
+ readonly live: true;
346
+ readonly columns: readonly string[];
347
+ readonly expressions?: readonly string[];
348
+ readonly include?: readonly string[];
349
+ readonly nullsNotDistinct: boolean;
350
+ readonly opclass?: Readonly<Record<string, string>>;
351
+ readonly with?: Readonly<Record<string, string>>;
352
+ readonly where?: string;
353
+ };
354
+ /** A canonical SQL fact, never an unversioned deparse string. */
355
+ type CanonicalSqlFact = {
356
+ readonly canonicalFormVersion: 1;
357
+ readonly sql: string;
358
+ };
359
+ /**
360
+ * The default, identity, and expression facts are one discriminated state.
361
+ * In particular, an identity cannot also claim an authored/default sequence
362
+ * expression, and a missing default cannot carry an expression.
363
+ */
364
+ type GeneratedColumnDefaultState = {
365
+ readonly defaultKind: 'none';
366
+ readonly hasDefault: false;
367
+ readonly identity: null;
368
+ readonly defaultExpression?: never;
369
+ } | {
370
+ readonly defaultKind: 'authored';
371
+ readonly hasDefault: true;
372
+ readonly identity: null;
373
+ readonly defaultExpression: CanonicalSqlFact;
374
+ } | {
375
+ readonly defaultKind: 'generated-sequence';
376
+ readonly hasDefault: true;
377
+ readonly identity: null;
378
+ readonly defaultExpression?: never;
379
+ } | {
380
+ readonly defaultKind: 'identity';
381
+ readonly hasDefault: false;
382
+ readonly identity: 'always' | 'byDefault';
383
+ readonly defaultExpression?: never;
384
+ };
385
+ type GeneratedColumnDeclaration = {
386
+ readonly type?: string;
387
+ readonly nullable?: boolean;
388
+ /** null means no COLLATE clause was authored; it is not an effective default. */
389
+ readonly authoredCollation?: string | null;
390
+ readonly default?: GeneratedColumnDefaultState;
391
+ };
392
+ type GeneratedTableColumnDeclaration = GeneratedColumnDeclaration & {
393
+ /** A table-shape member name, not the table target binding. */
394
+ readonly name: string;
395
+ };
396
+ type GeneratedIndexDeclaration = Omit<GeneratedIndexPostcondition, 'schema' | 'table' | 'name' | 'expressions' | 'where'> & {
397
+ readonly expressions?: readonly CanonicalSqlFact[];
398
+ readonly where?: CanonicalSqlFact;
399
+ };
400
+ type GeneratedConstraintDeclaration = Extract<GeneratedConstraintPostcondition, {
401
+ readonly type: 'p' | 'u';
402
+ }> | Extract<GeneratedConstraintPostcondition, {
403
+ readonly type: 'f';
404
+ }>;
405
+ /** Table names live only in TargetBinding; columns describe table structure. */
406
+ type V3TableDeclaration = {
407
+ readonly kind: 'table';
408
+ readonly columns: readonly GeneratedTableColumnDeclaration[];
409
+ };
410
+ /** Column names live only in TargetBinding; this is the column's shape. */
411
+ type V3ColumnDeclaration = {
412
+ readonly kind: 'column';
413
+ readonly column: GeneratedColumnDeclaration;
414
+ };
415
+ /** Constraint names live only in TargetBinding; this is a non-CHECK constraint fact. */
416
+ type V3ConstraintDeclaration = {
417
+ readonly kind: 'constraint';
418
+ readonly constraint: GeneratedConstraintDeclaration;
419
+ };
420
+ /** CHECK names live only in TargetBinding; expression is canonical and versioned. */
421
+ type V3CheckDeclaration = {
422
+ readonly kind: 'check';
423
+ readonly check: {
424
+ readonly expression: CanonicalSqlFact;
425
+ readonly notValid: boolean;
426
+ };
427
+ };
428
+ /** Index schema, table, and name live only in TargetBinding; options are structured facts. */
429
+ type V3IndexDeclaration = {
430
+ readonly kind: 'index';
431
+ readonly index: GeneratedIndexDeclaration;
432
+ };
433
+ /** Enum names live only in TargetBinding; labels are the declaration. */
434
+ type V3EnumDeclaration = {
435
+ readonly kind: 'enum';
436
+ readonly labels: readonly string[];
437
+ };
438
+ /** Sequence names live only in TargetBinding; options are the declaration. */
439
+ type V3SequenceDeclaration = {
440
+ readonly kind: 'sequence';
441
+ readonly startValue?: string;
442
+ readonly incrementBy?: string;
443
+ readonly minValue?: string;
444
+ readonly maxValue?: string;
445
+ readonly cycle?: boolean;
446
+ };
447
+ /** Extension names live only in TargetBinding; requested version is the declaration. */
448
+ type V3ExtensionDeclaration = {
449
+ readonly kind: 'extension';
450
+ readonly version?: string;
451
+ };
452
+ /** Address-free v3 declaration variants. */
453
+ type GeneratedPostconditionDeclarationV3 = {
454
+ readonly canonicalFormVersion: 1;
455
+ } & (V3TableDeclaration | V3ColumnDeclaration | V3ConstraintDeclaration | V3CheckDeclaration | V3IndexDeclaration | V3EnumDeclaration | V3SequenceDeclaration | V3ExtensionDeclaration | {
456
+ readonly kind: 'absent';
457
+ });
458
+ /**
459
+ * The separate binding selects the surrounding managed step's canonical
460
+ * address. It is versioned independently so later verifiers can resolve it
461
+ * without teaching any declaration variant about physical addresses.
462
+ */
463
+ type TargetBinding = {
464
+ readonly bindingVersion: 1;
465
+ readonly bindingKind: 'managed-step-address';
466
+ };
467
+ /** Version 3 carries an address-free declaration and a separately decoded binding. */
468
+ type GeneratedPostconditionV3 = {
469
+ readonly postconditionVersion: 3;
470
+ /** v3 kind lives only in the address-free declaration, never beside the binding. */
471
+ readonly kind?: never;
472
+ readonly declaration: GeneratedPostconditionDeclarationV3;
473
+ readonly targetBinding: TargetBinding;
474
+ };
475
+ /** Only v3 is a decodable generated postcondition. Older values replan. */
476
+ type GeneratedPostcondition = GeneratedPostconditionV3;
477
+ /** The version tag is part of the digest domain, never an implicit convention. */
478
+ declare function generatedPostconditionDigest(value: {
479
+ readonly postconditionVersion: number;
480
+ }): string;
481
+ declare function generatedPostconditionForChange(input: {
482
+ readonly change: SchemaChange;
483
+ readonly schema: string;
484
+ }): _dbsp_types.LedgerPayload | undefined;
485
+ /**
486
+ * The only change-kind boundary between diagnostic schema diffing and managed
487
+ * execution. Keep it at manifest construction: diagnostic-only controls must
488
+ * never acquire an address, claim, reservation, or DDL bundle.
489
+ */
490
+ declare function assertDeclarableChangeKind(kind: ChangeKind): asserts kind is Exclude<ChangeKind, 'enable_rls' | 'disable_rls' | 'create_policy' | 'drop_policy' | 'add_comment' | 'drop_comment' | 'alter_column_auto_increment'>;
491
+ /**
492
+ * PostgreSQL's total ChangeKind-to-address producer. The mapping is run at
493
+ * plan time, so no executable generator step can later fall through to a
494
+ * permissive "no managed address" branch.
495
+ */
496
+ declare function createPgsqlGeneratedManagedStep(input: {
497
+ readonly change: SchemaChange;
498
+ readonly database: string;
499
+ readonly schema: string;
500
+ readonly stepKey: string;
501
+ readonly order: number;
502
+ readonly dependencyOrder?: readonly string[];
503
+ readonly statements: readonly string[];
504
+ }): NormalizedManagedStep;
505
+ /**
506
+ * The live differ is the shape comparator. Persist the exact authored table
507
+ * shape, rather than a boolean that could later be reinterpreted.
508
+ */
509
+ declare function pgsqlDeclaredAdoptionDeclaration(table: TableIR): LedgerPayload;
510
+ /**
511
+ * Create the persisted, token-gated declaration that admits an already-live
512
+ * table into the managed ledger. It intentionally mirrors the historical
513
+ * generator lifecycle material so CLI plans retain their byte representation.
514
+ */
515
+ declare function createPgsqlDeclaredAdoptionStep(input: {
516
+ readonly address: Address;
517
+ readonly table: TableIR;
518
+ readonly stepKey: string;
519
+ readonly order: number;
520
+ readonly catalogueIdentity: CatalogueIdentity;
521
+ }): NormalizedManagedStep;
522
+ declare function pgsqlDeclaredSequenceAdoptionDeclaration(sequence: SequenceIR): LedgerPayload;
523
+ /** Creates the token-gated adoption claim for a physical standalone sequence. */
524
+ declare function createPgsqlDeclaredSequenceAdoptionStep(input: {
525
+ readonly address: Address;
526
+ readonly sequence: SequenceIR;
527
+ readonly stepKey: string;
528
+ readonly order: number;
529
+ readonly catalogueIdentity: CatalogueIdentity;
530
+ }): NormalizedManagedStep;
531
+
532
+ type GeneratedPostconditionQuery = {
533
+ query(sql: string, params?: readonly unknown[]): Promise<{
534
+ readonly rows: readonly Record<string, unknown>[];
535
+ }>;
536
+ };
537
+ declare const generatedPostconditionSessionBrand: unique symbol;
538
+ /** An adapter-minted, exclusive PostgreSQL session for rollback-only proof. */
539
+ type GeneratedPostconditionSession = GeneratedPostconditionQuery & {
540
+ readonly [generatedPostconditionSessionBrand]: true;
541
+ };
542
+ /** A retained session capability was used after its owning bracket ended. */
543
+ declare class GeneratedPostconditionSessionDeactivatedError extends Error {
544
+ constructor();
545
+ }
546
+ /** A caller attempted to overlap rollback-only proofs on one capability. */
547
+ declare class GeneratedPostconditionProofInFlightError extends Error {
548
+ constructor();
549
+ }
550
+ /** A session bracket completed while rollback-only proof work was still running. */
551
+ declare class GeneratedPostconditionWorkInFlightError extends Error {
552
+ constructor();
553
+ }
554
+ /**
555
+ * Public verifier checkout bracket. Scratch-backed proofs require the active
556
+ * role to hold database TEMP privilege; callers must preflight that capability
557
+ * before applying managed DDL whose postcondition needs scratch staging.
558
+ */
559
+ declare function withGeneratedPostconditionSession<T>(executor: {
560
+ connect(): Promise<GeneratedPostconditionQuery & {
561
+ release(error?: unknown): void | Promise<void>;
562
+ }>;
563
+ }, work: (session: GeneratedPostconditionSession) => Promise<T>, lockTimeoutMs?: number): Promise<T>;
564
+ type ResolvableGeneratedPostconditionKind = 'table' | 'column' | 'constraint';
565
+ type GeneratedPostconditionBindingKind = ResolvableGeneratedPostconditionKind | 'index' | 'enum' | 'sequence' | 'extension';
566
+ type GeneratedPostconditionSchemaBindingKind = Exclude<GeneratedPostconditionBindingKind, 'extension'>;
567
+ type GeneratedPostconditionTableChildKind = 'column' | 'index' | 'constraint';
568
+ /** The canonical schema-scoped table parent of a managed table child. */
569
+ type GeneratedPostconditionTableParent = {
570
+ readonly scope: 'schema';
571
+ readonly engine: string;
572
+ readonly database: string;
573
+ readonly schema: string;
574
+ readonly kind: 'table';
575
+ readonly name: string;
576
+ readonly parent?: never;
577
+ readonly catalogueIdentity?: never;
578
+ readonly qualifiedBy?: never;
579
+ };
580
+ type GeneratedPostconditionSchemaRootAddress<K extends Exclude<GeneratedPostconditionSchemaBindingKind, GeneratedPostconditionTableChildKind>> = Omit<ResourceAddress, 'engine' | 'schema' | 'parent' | 'kind'> & {
581
+ readonly engine: string;
582
+ readonly scope: 'schema';
583
+ readonly schema: string;
584
+ readonly parent?: never;
585
+ readonly kind: K;
586
+ };
587
+ type GeneratedPostconditionTableChildAddress<K extends GeneratedPostconditionTableChildKind> = Omit<ResourceAddress, 'engine' | 'schema' | 'parent' | 'kind'> & {
588
+ readonly engine: string;
589
+ readonly scope: 'schema';
590
+ readonly schema: string;
591
+ readonly parent: GeneratedPostconditionTableParent;
592
+ readonly kind: K;
593
+ };
594
+ type GeneratedPostconditionExtensionAddress = Omit<ResourceAddress, 'engine' | 'schema' | 'parent' | 'kind'> & {
595
+ readonly engine: string;
596
+ readonly scope: 'database';
597
+ readonly schema?: never;
598
+ readonly parent?: never;
599
+ readonly kind: 'extension';
600
+ };
601
+ /** The complete topology selected by a v3 managed-step binding. */
602
+ type GeneratedPostconditionBindingAddress = GeneratedPostconditionSchemaRootAddress<'table' | 'enum' | 'sequence'> | GeneratedPostconditionTableChildAddress<GeneratedPostconditionTableChildKind> | GeneratedPostconditionExtensionAddress;
603
+ declare class GeneratedPostconditionBindingResolutionError extends Error {
604
+ readonly sought: string;
605
+ readonly found: string;
606
+ constructor(input: {
607
+ readonly sought: string;
608
+ readonly found: string;
609
+ }, options?: ErrorOptions);
610
+ }
611
+ /**
612
+ * Narrows a ledger address into the complete topology that a v3 verifier can
613
+ * bind. Ledger addresses are intentionally broader, so this boundary must
614
+ * reject malformed persisted input before it reaches any verifier dispatch.
615
+ */
616
+ declare function toGeneratedPostconditionBindingAddress(address: LedgerAddress): GeneratedPostconditionBindingAddress;
617
+ type IndexProjection = {
618
+ readonly schema: string;
619
+ readonly table: string;
620
+ readonly name: string;
621
+ readonly method: string;
622
+ readonly unique: boolean;
623
+ readonly valid: boolean;
624
+ readonly ready: boolean;
625
+ readonly live: boolean;
626
+ readonly nullsNotDistinct: boolean;
627
+ readonly primary: boolean;
628
+ readonly exclusion: boolean;
629
+ readonly immediate: boolean;
630
+ readonly constraintOwned: boolean;
631
+ readonly keyColumns: readonly (string | null)[];
632
+ readonly keyDefinitions: readonly string[];
633
+ readonly includeColumns: readonly string[];
634
+ readonly opclasses: readonly string[];
635
+ readonly keyOptions: readonly string[];
636
+ readonly reloptions: readonly string[];
637
+ readonly predicate: string | null;
638
+ };
639
+ type CheckProjection = {
640
+ readonly expression: string;
641
+ readonly validated: boolean;
642
+ readonly noInherit: boolean;
643
+ readonly enforced: boolean;
644
+ readonly isLocal: boolean;
645
+ readonly inheritanceCount: number;
646
+ readonly parentId: number;
647
+ };
648
+ type TableColumnProjection = {
649
+ readonly name: string;
650
+ readonly type: string;
651
+ readonly nullable: boolean;
652
+ readonly default: string | undefined;
653
+ /** Ownership and canonical nextval shape read in the same catalogue snapshot. */
654
+ readonly generatedSequenceDefault: boolean;
655
+ readonly collation: string | null;
656
+ readonly identity: 'always' | 'byDefault' | null;
657
+ };
658
+ type TableProjection = {
659
+ readonly columns: readonly TableColumnProjection[];
660
+ };
661
+ type GeneratedColumnProjection = Omit<TableColumnProjection, 'name'>;
662
+ declare class GeneratedPostconditionReplanRequiredError extends Error {
663
+ readonly code = "REPLAN_REQUIRED";
664
+ readonly diagnostic: Readonly<{
665
+ versionSeen: unknown;
666
+ stepIdentity: string | undefined;
667
+ structuralPath: string | undefined;
668
+ }>;
669
+ readonly structuralPath: string | undefined;
670
+ constructor(message: string, versionSeen?: unknown, stepIdentity?: string | undefined, options?: ErrorOptions, structuralPath?: string | undefined);
671
+ }
672
+ /**
673
+ * Decode exactly one postcondition interpretation per version: only v3 is
674
+ * accepted. v1/v2 and every other value are named REPLAN_REQUIRED outcomes.
675
+ */
676
+ declare function decodeGeneratedPostcondition(value: unknown, stepIdentity?: string): GeneratedPostcondition;
677
+ /**
678
+ * The persisted digest is bound to the versioned wire value before decoding.
679
+ * A digest minted for one version cannot authenticate another version body.
680
+ */
681
+ declare function decodeGeneratedPostconditionPayload(payload: {
682
+ readonly value: unknown;
683
+ readonly digest: string;
684
+ }, stepIdentity?: string): GeneratedPostcondition;
685
+ /** Refuse structural lookalikes before any proof or catalogue read. */
686
+ declare function assertGeneratedPostconditionSession(value: unknown): GeneratedPostconditionSession;
687
+ type GeneratedPostconditionCatalogueIdentity = NonNullable<ResourceAddress['catalogueIdentity']>;
688
+ /** Resolves the v3 table binding, then delegates its shared structural proof. */
689
+ declare function verifyGeneratedTablePostcondition(input: {
690
+ readonly session: GeneratedPostconditionSession;
691
+ readonly postcondition: unknown;
692
+ readonly address: GeneratedPostconditionBindingAddress;
693
+ }): Promise<{
694
+ readonly kind: 'table';
695
+ readonly projection: TableProjection;
696
+ readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
697
+ }>;
698
+ /** Resolves the v3 column binding, then delegates its shared structural proof. */
699
+ declare function verifyGeneratedColumnPostcondition(input: {
700
+ readonly session: GeneratedPostconditionSession;
701
+ readonly postcondition: unknown;
702
+ readonly address: GeneratedPostconditionBindingAddress;
703
+ }): Promise<{
704
+ readonly kind: 'column';
705
+ readonly projection: GeneratedColumnProjection;
706
+ readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
707
+ }>;
708
+ /** Resolves the v3 index binding, then delegates its shared structural proof. */
709
+ declare function verifyGeneratedIndexPostcondition(input: {
710
+ readonly session: GeneratedPostconditionSession;
711
+ readonly postcondition: unknown;
712
+ readonly address: GeneratedPostconditionBindingAddress;
713
+ }): Promise<{
714
+ readonly kind: 'index';
715
+ readonly projection: IndexProjection;
716
+ readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
717
+ }>;
718
+ /** Resolves the v3 CHECK binding, then delegates its shared structural proof. */
719
+ declare function verifyGeneratedCheckPostcondition(input: {
720
+ readonly session: GeneratedPostconditionSession;
721
+ readonly postcondition: unknown;
722
+ readonly address: GeneratedPostconditionBindingAddress;
723
+ }): Promise<{
724
+ readonly kind: 'constraint';
725
+ readonly projection: CheckProjection;
726
+ readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
727
+ }>;
728
+ /**
729
+ * Binds the deliberately non-structural v3 kinds under the same rollback-only
730
+ * proof bracket as structural verifiers. The declaration kind is the binding
731
+ * expectation, so a sequence slot can never observe an enum declaration (or
732
+ * vice versa) merely because the address happens to resolve.
733
+ */
734
+ declare function verifyGeneratedIdentityPostcondition(input: {
735
+ readonly session: GeneratedPostconditionSession;
736
+ readonly postcondition: unknown;
737
+ readonly address: GeneratedPostconditionBindingAddress;
738
+ readonly kind: 'constraint' | 'enum' | 'sequence' | 'extension';
739
+ }): Promise<{
740
+ readonly kind: 'constraint' | 'enum' | 'sequence' | 'extension';
741
+ readonly identity: Readonly<{
742
+ readonly relationOid: string;
743
+ readonly objectOid?: string;
744
+ }>;
745
+ readonly catalogueIdentity: GeneratedPostconditionCatalogueIdentity;
746
+ }>;
747
+
748
+ /**
749
+ * PostgreSQL Schema Introspection (ADAPTER-006)
750
+ *
751
+ * Queries information_schema/pg_catalog to build ModelIR
752
+ * from an existing database. Supports:
753
+ * - Table/column/PK discovery
754
+ * - FK → bidirectional relation inference
755
+ * - Hierarchy detection (adjacency + edge-table)
756
+ * - Include/exclude filtering
757
+ *
758
+ * @module introspection
759
+ */
760
+
761
+ /** The minimum every schema-level operation needs: which schema. */
762
+ interface SchemaScopeOptions {
763
+ /** Schema name to operate on (default: 'public') */
764
+ readonly schema?: string;
765
+ }
766
+ /**
767
+ * Introspection additionally chooses WHICH TABLES to read. It is a read-only
768
+ * path, so narrowing it is safe — that is why the table filters live here and
769
+ * nowhere else.
770
+ */
771
+ interface IntrospectionOptions extends SchemaScopeOptions {
772
+ /** Tables to exclude (glob patterns: * matches any chars) */
773
+ readonly exclude?: readonly string[];
774
+ /** Tables to include (default: all). Applied before exclude. */
775
+ readonly include?: readonly string[];
776
+ }
777
+ /** Hierarchy pattern detected during introspection */
778
+ /**
779
+ * Hierarchy pattern detected during introspection.
780
+ * Alias of {@link HierarchyIR} from \@dbsp/types — kept here for
781
+ * public-API backwards compatibility (re-exported from \@dbsp/adapter-pgsql).
782
+ */
783
+ type DetectedHierarchy = HierarchyIR;
784
+ /** Extended ModelIR with hierarchy metadata */
785
+ interface IntrospectedModelIR extends ModelIR {
786
+ readonly hierarchies: readonly DetectedHierarchy[];
787
+ readonly introspectedAt: Date;
788
+ readonly warnings: readonly string[];
789
+ }
790
+ /**
791
+ * Introspect a database through a pool.
792
+ *
793
+ * This does NOT accept a checked-out `PoolClient`, and that is deliberate. A
794
+ * client may be sitting inside a transaction that belongs to its owner, and a
795
+ * catalog query that fails there aborts *their* transaction. Protecting that
796
+ * needs a savepoint, and knowing whether to take one needs the caller to say
797
+ * whose transaction it is — which is what `PgsqlAdapter`'s `borrowedClient`
798
+ * declaration is for. Guessing it from the object's shape is the exact defect
799
+ * this adapter was rewritten to remove.
800
+ *
801
+ * Saying so in a comment is not enough: `CatalogQueryExecutor` is structural, so
802
+ * a `PoolClient` — which has a `query()` — satisfies it, and the prose would have
803
+ * been the only thing standing in the way. It is branded instead, and only the
804
+ * adapter's own protected executor carries the brand. A client cannot be passed
805
+ * here at all.
806
+ *
807
+ * So: hold a client, use `new PgsqlAdapter(client, { borrowedClient: true })`
808
+ * and call `.introspect()` on it.
809
+ */
810
+ declare function introspect(pool: Pool, options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
811
+
812
+ type PgPhysicalModelInput = {
813
+ readonly mode: 'logical';
814
+ readonly model: ModelIR;
815
+ readonly schema: string;
816
+ readonly dbCasing?: DbCasing;
817
+ readonly naming?: NamingPlugin;
818
+ readonly fkAutoIndex?: boolean;
819
+ } | {
820
+ readonly mode: 'physical';
821
+ readonly model: ModelIR;
822
+ readonly schema: string;
823
+ readonly fkAutoIndex?: boolean;
824
+ };
825
+ type PgPhysicalNamespace = 'pg_class' | 'pg_type' | 'column' | 'constraint' | 'policy';
826
+ interface PgPhysicalNameClaim {
827
+ readonly namespace: PgPhysicalNamespace;
828
+ readonly schema: string;
829
+ readonly table?: string;
830
+ readonly physicalName: string;
831
+ readonly logicalOrigin: string;
832
+ }
833
+ interface PgPhysicalNameCollision {
834
+ readonly namespace: PgPhysicalNamespace;
835
+ readonly schema: string;
836
+ readonly table?: string;
837
+ readonly physicalName: string;
838
+ readonly first: PgPhysicalNameClaim;
839
+ readonly second: PgPhysicalNameClaim;
840
+ }
841
+ declare class PgPhysicalNameCollisionError extends Error {
842
+ readonly collision: PgPhysicalNameCollision;
843
+ constructor(collision: PgPhysicalNameCollision);
844
+ get namespace(): PgPhysicalNamespace;
845
+ get schema(): string;
846
+ get table(): string | undefined;
847
+ get physicalName(): string;
848
+ get first(): PgPhysicalNameClaim;
849
+ get second(): PgPhysicalNameClaim;
850
+ }
851
+ /** Refusal raised before a physical model starts inspecting its input model. */
852
+ declare class PgPhysicalModelInputError extends Error {
853
+ readonly reason: 'schema' | 'mode-options';
854
+ constructor(reason: 'schema' | 'mode-options');
855
+ }
856
+ interface PgPhysicalModel {
857
+ readonly mode: 'logical' | 'physical';
858
+ readonly schema: string;
859
+ readonly fkAutoIndex: boolean;
860
+ readonly model: ModelIR;
861
+ readonly inventory: PhysicalNameInventory;
862
+ readonly claims: readonly PgPhysicalNameClaim[];
863
+ }
864
+ /** Builds the sole PostgreSQL physical spelling of one model without rendering SQL. */
865
+ declare function createPgPhysicalModel(input: PgPhysicalModelInput): PgPhysicalModel;
866
+
867
+ type PgsqlTransactionTimeoutParameter = 'lock_timeout' | 'statement_timeout';
868
+
869
+ /**
870
+ * PgsqlAdapter - Implements the Adapter interface for PostgreSQL using native pg driver.
871
+ *
872
+ * This adapter wraps a pg Pool instance and provides the unified
873
+ * adapter interface for the db-semantic-planner ORM.
874
+ *
875
+ * @module pgsql-adapter
876
+ */
877
+
878
+ declare const rollbackOnlyPgsqlScopeBrand: unique symbol;
879
+ /** A scope minted by withScratchScope and guaranteed to roll back on success. */
880
+ type RollbackOnlyPgsqlScope<DB = unknown> = PgsqlAdapter<DB> & {
881
+ readonly [rollbackOnlyPgsqlScopeBrand]: typeof rollbackOnlyPgsqlScopeBrand;
882
+ };
883
+ type PgAdvisoryLockKey = bigint | {
884
+ readonly classId: number;
885
+ readonly objId: number;
886
+ };
887
+ type PgAdvisoryLockResult<T> = {
888
+ readonly acquired: true;
889
+ readonly value: T;
890
+ } | {
891
+ readonly acquired: false;
892
+ };
893
+ declare class PgsqlRawSqlTransactionControlError extends Error {
894
+ readonly dbspRawSqlTransactionControl = true;
895
+ constructor(cause: unknown);
896
+ }
897
+ declare class PgsqlTransactionAbortedCommitError extends Error {
898
+ readonly dbspTransactionAbortedCommit = true;
899
+ constructor(cause: unknown);
900
+ }
901
+ declare class PgsqlTransactionAbortedError extends Error {
902
+ readonly dbspTransactionAborted = true;
903
+ constructor(cause: unknown);
904
+ }
905
+ /**
906
+ * Raised when a pool-owned top-level transaction is aborted through
907
+ * `TransactionOptions.signal`. If the signal aborts while `pool.connect()` is
908
+ * still pending, dbsp honors it only after a client is acquired.
909
+ */
910
+ declare class PgsqlTransactionAbortSignalError extends Error {
911
+ readonly dbspTransactionAbortSignal = true;
912
+ constructor();
913
+ }
914
+ declare class PgsqlPinnedConnectionAbortSignalError extends Error {
915
+ readonly dbspPinnedConnectionAbortSignal = true;
916
+ constructor();
917
+ }
918
+ declare class PgsqlTransactionOptionsError extends Error {
919
+ readonly dbspTransactionOptions = true;
920
+ constructor(message: string);
921
+ }
922
+ declare class PgsqlAdvisoryLockOptionsError extends Error {
923
+ readonly dbspAdvisoryLockOptions = true;
924
+ constructor(message: string);
925
+ }
926
+ /**
927
+ * Raised when a statement inside a dbsp-managed transaction fails with a SQLSTATE
928
+ * that matches a timeout the caller configured for that transaction: `55P03`
929
+ * (`lock_not_available`) when `lockTimeoutMs` was set, or `57014` (`query_canceled`)
930
+ * when `statementTimeoutMs` was set. The original PostgreSQL error is preserved as
931
+ * `cause`.
932
+ *
933
+ * Classification is by SQLSTATE only. PostgreSQL assigns these codes to the OUTCOME,
934
+ * not the cause: `55P03` is also raised by `FOR UPDATE NOWAIT`, and `57014` is also
935
+ * raised by an external cancel (e.g. `pg_cancel_backend`). There is no locale-stable
936
+ * structured field that separates the timeout from the other cause, so the message
937
+ * text is deliberately NOT parsed. dbsp never emits `NOWAIT` itself, so a `55P03`
938
+ * here is the configured `lock_timeout` unless the caller's own raw SQL used
939
+ * `NOWAIT`; a `57014` is the configured `statement_timeout` unless the backend was
940
+ * cancelled from outside. Inspect `cause` when that distinction matters.
941
+ */
942
+ declare class PgsqlTransactionTimeoutError extends Error {
943
+ readonly timeout: PgsqlTransactionTimeoutParameter;
944
+ readonly dbspTransactionTimeout = true;
945
+ constructor(cause: unknown, timeout: PgsqlTransactionTimeoutParameter);
946
+ }
947
+ /**
948
+ * Raised when the single safe unnamed replay after a prepared-statement
949
+ * infrastructure failure also fails. `message` is always the safe constant
950
+ * `Prepared statement recovery replay failed.`; `cause` is the replay error;
951
+ * `infrastructureError` is the original infrastructure error; and
952
+ * `admissionFingerprint` identifies the admitted statement. DBSP-authored
953
+ * messages carry no parameter values; preserved upstream errors, including the
954
+ * standard Error `cause`, are unsanitized.
955
+ */
956
+ declare class PgsqlPreparedStatementReplayError extends Error {
957
+ readonly admissionFingerprint: string;
958
+ readonly infrastructureError: unknown;
959
+ readonly dbspPreparedStatementReplay = true;
960
+ readonly originalInfrastructureError: unknown;
961
+ readonly originalError: unknown;
962
+ constructor(admissionFingerprint: string, infrastructureError: unknown, cause: unknown);
963
+ }
964
+ /**
965
+ * Options for PgsqlAdapter.
966
+ */
967
+ interface PgsqlPreparedStatementsOptions {
968
+ /** Maximum distinct compiled statements admitted per executor (default: 500). */
969
+ readonly maxStatements?: number;
970
+ }
971
+ interface PgsqlAdapterOptions {
972
+ /** Schema name for multi-tenant queries */
973
+ readonly schemaName?: string;
974
+ /**
975
+ * DB column casing convention (intuitive semantics).
976
+ * - `'snake_case'`: DB columns are snake_case → transform to camelCase for JS
977
+ * - `'camelCase'`: DB columns are camelCase → no transformation
978
+ * - `'preserve'`: No transformation
979
+ */
980
+ readonly dbCasing?: DbCasing;
981
+ /** Optional model for WHERE compilation */
982
+ readonly model?: ModelIR;
983
+ /** Optional logger for debug/error messages */
984
+ readonly logger?: AdapterLogger;
985
+ /** Default primary key column name for convention fallbacks (default: 'id') */
986
+ readonly defaultPkColumnName?: string;
987
+ /** Convention for deriving FK column names: (tableName, pkName) => fkColumnName */
988
+ readonly deriveFkColumnName?: FkColumnDerivation;
989
+ /**
990
+ * Opt in to node-postgres named prepared statements for compiled queries with
991
+ * parameters. `true` uses the default statement cap; an object overrides it.
992
+ */
993
+ readonly preparedStatements?: boolean | PgsqlPreparedStatementsOptions;
994
+ }
995
+ interface PgsqlPoolAdapterOptionsBase extends PgsqlAdapterOptions {
996
+ readonly borrowedClient?: false;
997
+ }
998
+ type PgsqlPoolAdapterOptions = (PgsqlPoolAdapterOptionsBase & {
999
+ readonly replayInvalidatedPlans?: false | undefined;
1000
+ }) | (Omit<PgsqlPoolAdapterOptionsBase, 'preparedStatements'> & {
1001
+ readonly preparedStatements: true | PgsqlPreparedStatementsOptions;
1002
+ /**
1003
+ * Enable one unnamed replay after `0A000`/`RevalidateCachedQuery` only when
1004
+ * you assert that your statements do not invoke functions performing
1005
+ * effectful work before nested prepared-statement operations. This requires
1006
+ * `preparedStatements: true` (or a prepared-statements options object).
1007
+ *
1008
+ * Replay snapshots JSON-like values (finite numbers, strings, booleans,
1009
+ * `null`, arrays, plain or null-prototype objects) and clean `Date`/`Buffer`
1010
+ * instances. It excludes non-finite numbers, `undefined`, `bigint`, functions,
1011
+ * proxies, cycles, sparse arrays, accessors, symbol-valued
1012
+ * parameters, symbol keys on plain objects, exotic prototypes, custom built-ins,
1013
+ * and values with their own node-postgres
1014
+ * `toPostgres` behavior.
1015
+ * Serialization-irrelevant symbol metadata on arrays and Buffers is ignored.
1016
+ * The detached snapshot covers later mutations to the supplied value graph,
1017
+ * not built-in prototypes, timezone state, or node-postgres serialization
1018
+ * configuration; a process-global `toPostgres` or `toJSON` installed while
1019
+ * the call is in flight is outside the guarantee. Each capture or replay copy
1020
+ * is independently limited to 64 Ki visited values, 16 MiB of UTF-8 strings,
1021
+ * and 16 MiB of Buffer data. An ineligible or over-budget value still receives
1022
+ * the initial named submission, but disables transparent replay.
1023
+ * These budgets bound copied nodes and payload bytes; enumerating a plain
1024
+ * object's existing property table is proportional to the caller's own object.
1025
+ *
1026
+ * Replay needs the adapter-owned serialized physical client available from a
1027
+ * pool; it is therefore not supported by borrowed or compile-only adapters.
1028
+ */
1029
+ readonly replayInvalidatedPlans: true;
1030
+ });
1031
+ interface PgsqlBorrowedClientAdapterOptions extends PgsqlAdapterOptions {
1032
+ /** Replay is only available to a pool-owned pinned scope. */
1033
+ readonly replayInvalidatedPlans?: never;
1034
+ /** This connection belongs to the caller. dbsp never releases it. */
1035
+ readonly borrowedClient: true;
1036
+ /**
1037
+ * Let dbsp run transactions on your connection, through a savepoint.
1038
+ *
1039
+ * When your connection is already inside a transaction, dbsp creates a
1040
+ * savepoint and rolls back dbsp's changes after that savepoint if the callback
1041
+ * fails. `RELEASE SAVEPOINT` does not commit; it merges the work into your
1042
+ * surrounding transaction, so a callback that succeeded is still undone if you
1043
+ * later roll back. Deferred constraints or triggers can still make your outer
1044
+ * `COMMIT` fail after dbsp has returned. `SET LOCAL` changes inside the callback
1045
+ * remain in effect for the rest of your transaction after the savepoint is
1046
+ * released. `ON COMMIT DROP` and `ON COMMIT DELETE ROWS` fire at your transaction
1047
+ * boundary, not at the savepoint. Sequences are not transactional:
1048
+ * `nextval`/`setval` are not reclaimed by a savepoint rollback. Session-level
1049
+ * advisory locks ignore rollback; transaction-level advisory locks taken by a
1050
+ * successful callback last until your transaction ends.
1051
+ *
1052
+ * Transaction control through raw SQL inside a scope dbsp is managing is
1053
+ * unsupported. `COMMIT`, `ROLLBACK`, and `PREPARE TRANSACTION` end the
1054
+ * transaction dbsp is working inside; dbsp detects that and fails loudly, but
1055
+ * the data is already whatever your statement made it. Raw savepoint control
1056
+ * (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`) can alter the
1057
+ * savepoint stack before dbsp sees the command tag; dbsp poisons the scope, but
1058
+ * it cannot make that command un-run. Manage your transaction outside dbsp's
1059
+ * calls.
1060
+ */
1061
+ readonly managedTransactions?: true;
1062
+ }
1063
+ /** Options for a connectionless adapter, which cannot own replay serialization. */
1064
+ interface PgsqlCompileOnlyAdapterOptions extends PgsqlAdapterOptions {
1065
+ readonly replayInvalidatedPlans?: never;
1066
+ }
1067
+ /**
1068
+ * Adapter implementation for PostgreSQL using native pg driver.
1069
+ *
1070
+ * @typeParam DB - Database schema type
1071
+ *
1072
+ * @example
1073
+ * ```typescript
1074
+ * import { Pool } from 'pg';
1075
+ * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
1076
+ *
1077
+ * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
1078
+ * const adapter = createPgsqlAdapter(pool);
1079
+ * const orm = createOrm({ model, adapter });
1080
+ * ```
1081
+ */
1082
+ declare class PgsqlAdapter<DB = unknown> implements Adapter<DB> {
1083
+ private readonly pool;
1084
+ private readonly client;
1085
+ private readonly borrowedClient;
1086
+ private readonly managedTransactions;
1087
+ private readonly adapterManagedTransaction;
1088
+ private readonly adapterManagedPinnedConnection;
1089
+ private readonly rollbackOnlyScope;
1090
+ private readonly scopeToken;
1091
+ private readonly scopeState;
1092
+ private readonly schemaName;
1093
+ private readonly _dbCasing;
1094
+ private readonly naming;
1095
+ private readonly model;
1096
+ private readonly logger;
1097
+ private readonly replayInvalidatedPlans;
1098
+ private readonly preparedStatements;
1099
+ private readonly preparedStatementRegistry;
1100
+ private readonly _capabilities;
1101
+ private readonly defaultPk;
1102
+ private readonly deriveFk;
1103
+ /**
1104
+ * Create a new PgsqlAdapter.
1105
+ *
1106
+ * Ownership of the connection is **declared**, never inferred. Handing over a
1107
+ * `PoolClient` means nothing on its own — it says the object has a `release()`
1108
+ * method, not that a transaction is open or that the caller owns the lifecycle.
1109
+ * Pass `borrowedClient: true` to say so.
1110
+ *
1111
+ * @param pool - a pg.Pool, a caller-owned pg.PoolClient (with `borrowedClient: true`),
1112
+ * or nothing at all for compile-only mode
1113
+ * @param options - configuration; declares connection ownership
1114
+ */
1115
+ constructor(pool: Pool, options?: PgsqlPoolAdapterOptions);
1116
+ constructor(client: PoolClient, options: PgsqlBorrowedClientAdapterOptions);
1117
+ constructor(pool?: undefined, options?: PgsqlCompileOnlyAdapterOptions);
1118
+ /**
1119
+ * Shared compilation dependencies — built lazily from adapter fields.
1120
+ * Passed to compiler sub-modules instead of `this`.
1121
+ */
1122
+ /**
1123
+ * Return a new PgsqlAdapterOptions that merges current config with overrides.
1124
+ * Ensures that all configuration fields (logger, defaultPkColumnName,
1125
+ * deriveFkColumnName, etc.) are propagated to scoped/transactional adapters.
1126
+ */
1127
+ private cloneOptions;
1128
+ private buildCompileDeps;
1129
+ private requireNqlCompileModel;
1130
+ private assertNqlBindingNamesDisjointFromTables;
1131
+ private compileNqlMutation;
1132
+ private compileNqlBundleLeafEnvelope;
1133
+ private compileNqlBundle;
1134
+ /**
1135
+ * Returns the pool/client executor, or refuses a connectionless adapter.
1136
+ */
1137
+ private requireConnection;
1138
+ /** Adapter capabilities for feature detection */
1139
+ get capabilities(): AdapterCapabilities;
1140
+ /** Per-instance connection state, distinct from PostgreSQL capabilities. */
1141
+ get connectionAvailability(): ConnectionAvailability;
1142
+ /** Side-effect-free execution availability for core feature detection. */
1143
+ executionAvailable(): boolean;
1144
+ /** PostgreSQL dialect capabilities for planner strategy selection */
1145
+ get dialectCapabilities(): DialectCapabilities;
1146
+ /**
1147
+ * DB column casing convention used by this adapter.
1148
+ */
1149
+ get dbCasing(): DbCasing;
1150
+ /**
1151
+ * Get the underlying pg Pool or borrowed PoolClient instance.
1152
+ *
1153
+ * Exposing raw access from a pool-owned dbsp-managed scope permanently taints that
1154
+ * physical client: external callers can queue commands outside dbsp's statement
1155
+ * lock, so replay is disabled and dbsp destroys the client at scope release.
1156
+ * Expect pool churn; session state on that exposed connection does not survive the
1157
+ * release. A borrowed client remains caller-owned: dbsp never releases it, and the
1158
+ * caller decides its fate after raw exposure.
1159
+ */
1160
+ getPoolInstance(): Pool | PoolClient;
1161
+ /**
1162
+ * Compile a plan to executable SQL.
1163
+ *
1164
+ * When passed a direct `CompiledNqlQuery`, the adapter trusts that the bundle
1165
+ * has already been semantically validated by the NQL compiler. This method
1166
+ * still performs adapter-owned SQL safety checks for emitted binding names
1167
+ * before CTE emission.
1168
+ */
1169
+ compile<T = unknown>(plan: PlanReport | CompiledNqlQuery, options?: CompileOptions): CompiledQuery<T>;
1170
+ /**
1171
+ * Compile a plan with includes, returning subquery include metadata (DX-033).
1172
+ */
1173
+ compileWithIncludes<T = unknown>(plan: PlanReport, options?: CompileOptions): CompileResultWithIncludes<T>;
1174
+ /**
1175
+ * Compile a subquery include query for given parent IDs (DX-033).
1176
+ * Generates: SELECT * FROM targetTable WHERE foreignKey IN ($1, $2, ...)
1177
+ *
1178
+ * @param info - Subquery include metadata
1179
+ * @param parentIds - Parent record IDs to fetch related records for
1180
+ * @param options - Compile options
1181
+ * @returns Compiled query for fetching related records
1182
+ */
1183
+ compileSubqueryInclude(info: SubqueryIncludeInfo, parentIds: readonly unknown[], options?: CompileOptions): CompiledQuery;
1184
+ /**
1185
+ * Compile a FROM-less SELECT expression to SQL.
1186
+ *
1187
+ * Produces: SELECT <expr>
1188
+ * Example: SELECT nextval('my_seq')
1189
+ *
1190
+ * @param expr - ExpressionIntent to evaluate
1191
+ * @returns Compiled SQL and parameters
1192
+ */
1193
+ compileSelectExpression<T = unknown>(expr: ExpressionIntent): CompiledQuery<T>;
1194
+ /**
1195
+ * Compile an insert intent to executable SQL.
1196
+ *
1197
+ * Strategy switch (per CompileOptions):
1198
+ * - rows <= batchThreshold (default 50): VALUES ($1,$2),($3,$4),...
1199
+ * - rows > batchThreshold OR batchThreshold === 0: SELECT unnest($1::type[]),...
1200
+ */
1201
+ compileInsert(intent: InsertIntent, options?: CompileOptions): CompiledQuery;
1202
+ /**
1203
+ * Compile an insert-from intent to executable SQL (NQL-ALIGN).
1204
+ * INSERT INTO target (cols) SELECT cols FROM source WHERE ... LIMIT ... RETURNING ...
1205
+ */
1206
+ compileInsertFrom(intent: InsertFromIntent, options?: CompileOptions): CompiledQuery;
1207
+ /**
1208
+ * Compile an update intent to executable SQL.
1209
+ */
1210
+ compileUpdate(intent: UpdateIntent, options?: CompileOptions): CompiledQuery;
1211
+ /**
1212
+ * Compile a batch update intent to executable SQL using unnest FROM strategy (BATCH-001).
1213
+ *
1214
+ * Generates:
1215
+ * UPDATE "table" SET "update_col" = t."update_col" [, "scalar_col" = $N]
1216
+ * FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t("match_col", "update_col")
1217
+ * WHERE "table"."match_col" = t."match_col"
1218
+ * [RETURNING ...]
1219
+ */
1220
+ compileBatchUpdate(intent: BatchUpdateIntent, options?: CompileOptions): CompiledQuery;
1221
+ /**
1222
+ * Compile a delete intent to executable SQL.
1223
+ */
1224
+ compileDelete(intent: DeleteIntent, options?: CompileOptions): CompiledQuery;
1225
+ /**
1226
+ * Compile an upsert intent to executable SQL (DX-026).
1227
+ */
1228
+ compileUpsert(intent: UpsertIntent, options?: CompileOptions): CompiledQuery;
1229
+ /**
1230
+ * Compile an upsert-from intent to executable SQL (NQL-BIND).
1231
+ * INSERT INTO target SELECT ... FROM source ON CONFLICT (cols) DO UPDATE SET ...
1232
+ */
1233
+ compileUpsertFrom(intent: UpsertFromIntent, options?: CompileOptions): CompiledQuery;
1234
+ /**
1235
+ * Compile a recursive CTE plan to executable SQL.
1236
+ * Supports adjacency-list and edge-table traversal modes.
1237
+ */
1238
+ compileRecursive<T = unknown>(report: RecursivePlanReport, model: ModelIR, options?: CompileOptions): CompiledQuery<T>;
1239
+ /**
1240
+ * Compile a CTE query backed by unnest() arrays (BATCH-001 Block 5).
1241
+ *
1242
+ * Strategy: compile CTE nodes to SQL fragments, compile outer query
1243
+ * independently (parameters starting at $1), then renumber outer params
1244
+ * to start after CTE params and prepend WITH clause.
1245
+ */
1246
+ compileCteQuery<T = unknown>(intent: CteQueryIntent, options?: CompileOptions): CompiledQuery<T>;
1247
+ /**
1248
+ * Compile a set operation (UNION / INTERSECT / EXCEPT) to SQL.
1249
+ */
1250
+ compileSetOperation<T = unknown>(intent: SetOperationIntent, model: ModelIR, options?: CompileOptions): CompiledQuery<T>;
1251
+ private compileSetOperationWithBindings;
1252
+ /**
1253
+ * Create a dump for observability.
1254
+ */
1255
+ createDump(plan: PlanReport, query: CompiledQuery, meta?: DumpMeta): Dump;
1256
+ /**
1257
+ * Execute a query and return all results.
1258
+ * Results are transformed to use model naming convention (e.g., snake_case → camelCase)
1259
+ */
1260
+ execute<T>(query: CompiledQuery<T>): Promise<T[]>;
1261
+ /**
1262
+ * Execute a query and return rows plus PostgreSQL result metadata.
1263
+ * Results are transformed to use model naming convention (e.g., snake_case → camelCase)
1264
+ */
1265
+ executeWithMeta(query: CompiledQuery): Promise<{
1266
+ readonly rows: readonly unknown[];
1267
+ readonly rowCount: number;
1268
+ readonly command?: string;
1269
+ }>;
1270
+ /**
1271
+ * Transform result rows from database naming to model naming convention.
1272
+ * For CamelCaseNamingPlugin: price_cents → priceCents
1273
+ */
1274
+ private transformResultRows;
1275
+ /**
1276
+ * Execute a query and return the first result or null.
1277
+ */
1278
+ executeOne<T>(query: CompiledQuery<T>): Promise<T | null>;
1279
+ /**
1280
+ * Execute a query and return the first result or throw.
1281
+ */
1282
+ executeOneOrThrow<T>(query: CompiledQuery<T>): Promise<T>;
1283
+ /**
1284
+ * Stream query results as an async iterable iterator.
1285
+ * Uses PostgreSQL cursors for efficient streaming.
1286
+ *
1287
+ * Note: The cursor must be used within a transaction. If not already
1288
+ * in a transaction, this method wraps the streaming in one.
1289
+ *
1290
+ * @param query - Compiled query to stream
1291
+ * @param options - Stream options (chunkSize)
1292
+ * @returns AsyncIterableIterator that yields rows one by one
1293
+ */
1294
+ stream<T>(query: CompiledQuery<T>, options?: AdapterStreamOptions): AsyncIterableIterator<T>;
1295
+ /** Stream raw SQL directly using the same cursor machinery as stream(). */
1296
+ streamRaw<T = unknown>(sql: string, parameters?: readonly unknown[], options?: AdapterStreamOptions): AsyncIterableIterator<T>;
1297
+ private streamCursor;
1298
+ /**
1299
+ * Internal: Stream with an existing client using cursors.
1300
+ */
1301
+ private streamWithClient;
1302
+ private streamWithManagedClient;
1303
+ private streamWithManagedClientSavepointScope;
1304
+ private streamWithClientTransaction;
1305
+ /**
1306
+ * Introspect the database schema and return a ModelIR.
1307
+ *
1308
+ * @param options - Optional introspection options (schema, include/exclude filters)
1309
+ * @returns IntrospectedModelIR with tables, relations, and hierarchy metadata
1310
+ *
1311
+ * @example
1312
+ * ```typescript
1313
+ * const model = await adapter.introspect();
1314
+ * const model = await adapter.introspect({ schema: 'tenant_1' });
1315
+ * const model = await adapter.introspect({ exclude: ['_prisma*'] });
1316
+ * ```
1317
+ */
1318
+ introspect(options?: IntrospectionOptions): Promise<IntrospectedModelIR>;
1319
+ /**
1320
+ * Acquire an exclusive session-level PostgreSQL advisory lock for the callback.
1321
+ *
1322
+ * The lock, callback, and unlock run on one `withPinnedConnection()` adapter.
1323
+ * dbsp performs one PostgreSQL acquire and one matching unlock per call. It
1324
+ * does not track reentrant depth in v1; PostgreSQL's session-level stacking
1325
+ * still applies when callers deliberately nest on the same pinned adapter.
1326
+ */
1327
+ withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>): Promise<T>;
1328
+ withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>, options: {
1329
+ readonly wait?: 'block';
1330
+ readonly signal?: AbortSignal;
1331
+ }): Promise<T>;
1332
+ withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>, options: {
1333
+ readonly wait: 'try';
1334
+ readonly signal?: AbortSignal;
1335
+ }): Promise<PgAdvisoryLockResult<T>>;
1336
+ withAdvisoryLock<T>(key: PgAdvisoryLockKey, fn: (locked: Adapter<DB>) => Promise<T>, options?: {
1337
+ readonly wait?: 'block' | 'try';
1338
+ readonly signal?: AbortSignal;
1339
+ }): Promise<T | PgAdvisoryLockResult<T>>;
1340
+ private unlockAdvisoryLock;
1341
+ withPinnedConnection<T>(fn: (adapter: Adapter<DB>) => Promise<T>, options?: PinnedConnectionOptions): Promise<T>;
1342
+ private pinnedConnectionReleaseReason;
1343
+ private pinnedConnectionWithClient;
1344
+ /**
1345
+ * Execute a callback within a database transaction.
1346
+ *
1347
+ * ## What this guarantees
1348
+ *
1349
+ * The callback's work commits together or not at all; a statement issued inside
1350
+ * the transaction never executes after its boundary, even if you forget to
1351
+ * `await` it; a nested `transaction()` is a real savepoint; and the connection
1352
+ * never goes back to the pool with a transaction still open on it.
1353
+ *
1354
+ * ## What it cannot guarantee, and you should know before you reach for raw SQL
1355
+ *
1356
+ * **Raw SQL that ends the transaction ends it.** `COMMIT`, `ROLLBACK` and
1357
+ * `PREPARE TRANSACTION` issued through `executeRaw` — or through several commands
1358
+ * in one call — reach PostgreSQL and take effect *before* dbsp is told what they
1359
+ * were: the command tag arrives after the statement has run. dbsp detects it, kills
1360
+ * the scope so nothing else escapes, and throws — but **it cannot un-run what your
1361
+ * statement already did**, and `transaction()` rejecting does not mean nothing was
1362
+ * committed.
1363
+ *
1364
+ * The same holds for session state raw SQL creates: a sequence that advanced stays
1365
+ * advanced, an advisory lock stays held, a `PREPARE` or a `SET` you issued survives
1366
+ * on a pooled connection. dbsp cleans up only what dbsp created.
1367
+ *
1368
+ * This is the contract of an escape hatch, not an oversight — see #327. If you need
1369
+ * transaction control, own the transaction: take a client, `BEGIN` on it yourself,
1370
+ * and hand dbsp a `borrowedClient` **without** `managedTransactions`. dbsp will then
1371
+ * contain its own statements inside *your* transaction instead of the other way round.
1372
+ */
1373
+ transaction<T>(fn: (adapter: Adapter<DB>) => Promise<T>, options?: TransactionOptions): Promise<T>;
1374
+ /**
1375
+ * Execute scratch PostgreSQL work in a scope that always rolls back on success.
1376
+ *
1377
+ * This is intentionally PostgreSQL-adapter-specific. It is used for catalog
1378
+ * shaped scratch DDL such as expression canonicalisation, where the caller
1379
+ * needs PostgreSQL's rendering but must not keep the scratch objects. This
1380
+ * scope has exactly one successful exit: rollback. In a caller transaction,
1381
+ * only this outer savepoint is retained after rollback; nested work releases
1382
+ * normally, so a large canonicalisation run cannot retain one subtransaction
1383
+ * per expression.
1384
+ * Rollback here is cleanup of dbsp-created work, not a sandbox for arbitrary
1385
+ * session effects.
1386
+ */
1387
+ withScratchScope<T>(fn: (adapter: RollbackOnlyPgsqlScope<DB>) => Promise<T>): Promise<T>;
1388
+ private createManagedClientAdapter;
1389
+ private createPinnedConnectionAdapter;
1390
+ private createChildTransactionObserver;
1391
+ private observeChildTransaction;
1392
+ private markChildTransactionObserved;
1393
+ private refreshScopeChildrenFailure;
1394
+ private transactionWithManagedClient;
1395
+ private transactionWithManagedClientSavepointScope;
1396
+ private applyTransactionTimeouts;
1397
+ private captureAndApplySavepointTimeouts;
1398
+ private restoreSavepointTimeouts;
1399
+ private transactionWithClientTransaction;
1400
+ private releaseClient;
1401
+ private rollbackAndReleaseSavepoint;
1402
+ private rollbackSavepoint;
1403
+ private releaseSavepoint;
1404
+ private rollbackTransactionIfOpen;
1405
+ private classifyTransactionStateError;
1406
+ private probeTransactionState;
1407
+ private classifySavepointReleaseFailure;
1408
+ private rollbackSavepointAfterReleaseFailure;
1409
+ private enterTransactionScope;
1410
+ private enterPinnedConnectionScope;
1411
+ private enterSavepointScope;
1412
+ private pushClientScope;
1413
+ private currentClientScope;
1414
+ private managedScopeEndedMessage;
1415
+ private assertCanUseClient;
1416
+ private assertUsableScopeAncestors;
1417
+ private findClientScope;
1418
+ private assertScopeNotPoisoned;
1419
+ private throwIfScopePoisoned;
1420
+ private scopePoisonOutranksError;
1421
+ private poisonScopeState;
1422
+ private poisonClientScope;
1423
+ private poisonClientScopeStack;
1424
+ private runWithScopeStatementLock;
1425
+ private closeScope;
1426
+ private closeScopeAndAssertChildren;
1427
+ private drainScopeStatements;
1428
+ private drainScopeChildren;
1429
+ private assertScopeChildrenSettled;
1430
+ private drainScopeWork;
1431
+ private executeScopeBoundaryStatement;
1432
+ private assertCommitSucceeded;
1433
+ /**
1434
+ * Create a schema-scoped adapter for multi-tenant queries.
1435
+ */
1436
+ withSchema(schemaName: string): Adapter<DB>;
1437
+ /**
1438
+ * Execute raw SQL directly.
1439
+ *
1440
+ * ⚠️ WARNING: Use parameter placeholders ($1, $2, etc.) for all values.
1441
+ *
1442
+ * Transaction control through raw SQL inside a scope dbsp is managing is
1443
+ * unsupported. `COMMIT`, `ROLLBACK`, and `PREPARE TRANSACTION` end the
1444
+ * transaction dbsp is working inside; dbsp detects that and fails loudly, but
1445
+ * the data is already whatever your statement made it. Raw savepoint control
1446
+ * (`SAVEPOINT`, `RELEASE SAVEPOINT`, `ROLLBACK TO SAVEPOINT`) can alter the
1447
+ * savepoint stack before dbsp sees the command tag; dbsp poisons the scope, but
1448
+ * it cannot make that command un-run. Manage your transaction outside dbsp's
1449
+ * calls.
1450
+ */
1451
+ executeRaw<T = unknown>(sql: string, parameters?: readonly unknown[]): Promise<T[]>;
1452
+ /**
1453
+ * Generate DDL statements from the PostgreSQL physical model.
1454
+ *
1455
+ * Uses PostgreSQL AST nodes and pgsql-deparser for consistent SQL generation.
1456
+ * Names are already physical: they were mapped once when the model was built
1457
+ * with `createPgPhysicalModel`, and this method maps none again.
1458
+ *
1459
+ * @param physical - The physical model to generate DDL from; its schema and
1460
+ * `fkAutoIndex` apply
1461
+ * @param overrideOptions - Optional rendering overrides (e.g., includeDropStatements)
1462
+ * @returns Array of DDL statements in dependency order
1463
+ */
1464
+ generateDDL(physical: PgPhysicalModel, overrideOptions?: GenerateDDLOptions): string[];
1465
+ /**
1466
+ * Execute a DDL statement directly (e.g. TRUNCATE, VACUUM, ALTER TABLE, CREATE INDEX).
1467
+ *
1468
+ * @throws Error if called on a compile-only adapter (no pool)
1469
+ * @since DDL-TABLE-001
1470
+ */
1471
+ executeDDL(sql: string): Promise<void>;
1472
+ /**
1473
+ * Whether a transaction is open on this adapter's connection.
1474
+ * This is true for dbsp-managed scopes and for borrowed pg clients whose
1475
+ * ReadyForQuery status says the caller has an open transaction.
1476
+ *
1477
+ * @since DDL-TABLE-001
1478
+ */
1479
+ get inTransaction(): boolean;
1480
+ private adapterManagedScopeIsLive;
1481
+ private shouldProtectBorrowedClientTransaction;
1482
+ /**
1483
+ * An idle ReadyForQuery status says nothing about commands another owner has
1484
+ * already queued on a PoolClient. Only a dbsp-created pinned scope both owns
1485
+ * the checked-out physical client and holds its statement lock across the
1486
+ * failed named execution and any unnamed replay.
1487
+ */
1488
+ private ownsSerializedClientForPreparedStatementReplay;
1489
+ private executeQueryProtectingOpenTransaction;
1490
+ private executeConnectionStatement;
1491
+ private executeConnectionStatementUnlocked;
1492
+ private executeConnectionStatementInSavepoint;
1493
+ private issueConnectionQuery;
1494
+ private assertNoMultiCommandRawCall;
1495
+ private assertNoTransactionControlCommand;
1496
+ private assertPrepareDidNotEndTransaction;
1497
+ /**
1498
+ * Resolve the explicit schema for a catalog read: an explicit argument, else
1499
+ * the adapter's configured schema, else `undefined` (resolve in-query). NOT a
1500
+ * hard-coded 'public' — an unresolved schema is handled by the SQL, which
1501
+ * finds the table's schema search_path-aware, in the SAME session, so a
1502
+ * non-public search_path and a pooled connection both stay correct.
1503
+ */
1504
+ private explicitSchema;
1505
+ /**
1506
+ * List all indexes on a table by querying pg_indexes.
1507
+ *
1508
+ * @param table - Table name
1509
+ * @param schema - Schema name (defaults to the search_path-resolved schema)
1510
+ */
1511
+ listIndexes(table: string, schema?: string, options?: {
1512
+ namePattern?: string;
1513
+ }): Promise<IndexInfo[]>;
1514
+ /**
1515
+ * Check whether an index with the given name exists on a table.
1516
+ *
1517
+ * @param name - Index name
1518
+ * @param table - Table name
1519
+ * @param schema - Schema name (defaults to the search_path-resolved schema)
1520
+ */
1521
+ indexExists(name: string, table: string, schema?: string): Promise<boolean>;
1522
+ /**
1523
+ * Return the total storage size of a table in bytes (includes indexes and TOAST).
1524
+ *
1525
+ * The table name is a SQL identifier — it is double-quoted, not parameterized,
1526
+ * because PostgreSQL does not allow parameterized table names in FROM clauses.
1527
+ * With no known schema the table is left unqualified so ::regclass resolves it
1528
+ * through search_path (the same table an unqualified reference would hit).
1529
+ *
1530
+ * @param table - Table name
1531
+ * @param schema - Schema name (defaults to the search_path-resolved schema)
1532
+ */
1533
+ storageSize(table: string, schema?: string): Promise<number>;
1534
+ /**
1535
+ * Generate SQL for TRUNCATE TABLE.
1536
+ * Implements TableDDLGeneratorAdapter.generateTruncate.
1537
+ */
1538
+ generateTruncate(table: string, schemaName: string, options?: TruncateOptions): string;
1539
+ /**
1540
+ * Generate SQL for VACUUM.
1541
+ * Implements TableDDLGeneratorAdapter.generateVacuum.
1542
+ */
1543
+ generateVacuum(table: string, schemaName: string, options?: VacuumOptions): string;
1544
+ /**
1545
+ * Generate SQL for ALTER TABLE ... ALTER COLUMN.
1546
+ * Implements TableDDLGeneratorAdapter.generateAlterColumn.
1547
+ */
1548
+ generateAlterColumn(table: string, schemaName: string, column: string, options: AlterColumnOptions): string;
1549
+ /**
1550
+ * Generate SQL for CREATE INDEX.
1551
+ * Implements TableDDLGeneratorAdapter.generateCreateIndex.
1552
+ */
1553
+ generateCreateIndex(table: string, schemaName: string, options: CreateIndexOptions): string;
1554
+ /**
1555
+ * Generate SQL for DROP INDEX.
1556
+ * Implements TableDDLGeneratorAdapter.generateDropIndex.
1557
+ */
1558
+ generateDropIndex(name: string, schemaName: string, options?: DropIndexOptions): string;
1559
+ /**
1560
+ * Validate an identifier (table name, column name, schema name).
1561
+ */
1562
+ validateIdentifier(value: string, type: string): void;
1563
+ }
1564
+ /**
1565
+ * Create a PgsqlAdapter from a pg Pool instance.
1566
+ *
1567
+ * @param pool - pg Pool instance
1568
+ * @param options - Optional configuration
1569
+ * @returns A new PgsqlAdapter instance
1570
+ *
1571
+ * @example
1572
+ * ```typescript
1573
+ * import { Pool } from 'pg';
1574
+ * import { createPgsqlAdapter } from '@dbsp/adapter-pgsql';
1575
+ *
1576
+ * const pool = new Pool({ connectionString: process.env.DATABASE_URL });
1577
+ * const adapter = createPgsqlAdapter(pool);
1578
+ *
1579
+ * // With naming convention
1580
+ * const adapter = createPgsqlAdapter(pool, { dbCasing: 'snake_case' });
1581
+ * ```
1582
+ */
1583
+ declare function createPgsqlAdapter<DB = unknown>(pool: Pool, options?: PgsqlPoolAdapterOptions): PgsqlAdapter<DB>;
1584
+ declare function createPgsqlAdapter<DB = unknown>(client: PoolClient, options: PgsqlBorrowedClientAdapterOptions): PgsqlAdapter<DB>;
1585
+ /**
1586
+ * Creates a connectionless PgsqlAdapter for SQL generation without a database connection.
1587
+ *
1588
+ * All compilation methods (compile, compileInsert, etc.), createDump(), and generateDDL()
1589
+ * work normally. The adapter has the full PgsqlAdapter surface; database operations refuse
1590
+ * at runtime until it is constructed with a connection via createPgsqlAdapter(pool).
1591
+ *
1592
+ * @example
1593
+ * ```typescript
1594
+ * import { createPgsqlCompileOnlyAdapter } from '@dbsp/adapter-pgsql';
1595
+ * import { createOrm } from '@dbsp/core';
1596
+ *
1597
+ * const adapter = createPgsqlCompileOnlyAdapter();
1598
+ * const orm = createOrm({ model, adapter });
1599
+ * const dump = await orm.select('users').dump();
1600
+ * console.log(dump.sql);
1601
+ * ```
1602
+ */
1603
+ declare function createPgsqlCompileOnlyAdapter<DB = unknown>(options?: PgsqlCompileOnlyAdapterOptions): PgsqlAdapter<DB>;
1604
+
1605
+ interface CheckConstraintCanonicalizationWarning {
1606
+ readonly table: string;
1607
+ readonly kind: 'check_constraint';
1608
+ readonly name: string;
1609
+ readonly constraint: string;
1610
+ readonly message: string;
1611
+ readonly cause: unknown;
1612
+ }
1613
+ interface ColumnDefaultCanonicalizationWarning {
1614
+ readonly table: string;
1615
+ readonly kind: 'column_default';
1616
+ readonly name: string;
1617
+ readonly message: string;
1618
+ readonly cause: unknown;
1619
+ readonly outcome?: 'unavailable' | 'rejected' | 'refused';
1620
+ /** Whether this warning represents a raw fallback or absent counterpart. */
1621
+ readonly comparison: 'raw' | 'unpaired';
1622
+ /** Present when the default could not be paired with the opposite model side. */
1623
+ readonly side?: 'desired' | 'database';
1624
+ }
1625
+ interface IndexPredicateCanonicalizationWarning {
1626
+ readonly table: string;
1627
+ readonly kind: 'index_predicate';
1628
+ readonly name: string;
1629
+ readonly message: string;
1630
+ readonly cause: unknown;
1631
+ readonly outcome: 'unavailable' | 'rejected' | 'refused';
1632
+ /** Predicate fallback always compares both complete models raw. */
1633
+ readonly comparison: 'raw';
1634
+ readonly side?: 'desired' | 'database';
1635
+ }
1636
+ type ExpressionCanonicalizationWarning = CheckConstraintCanonicalizationWarning | ColumnDefaultCanonicalizationWarning | IndexPredicateCanonicalizationWarning;
1637
+ interface CanonicalizeCheckConstraintsOptions {
1638
+ /** Database schema that owns the target tables and target-scoped enum types. */
1639
+ readonly schemaName?: string;
1640
+ /** Called when PostgreSQL CHECK canonicalisation fails and raw comparison is used. */
1641
+ readonly onWarning?: (warning: CheckConstraintCanonicalizationWarning) => void;
1642
+ /** Throw instead of falling back to raw comparison when canonicalisation fails. */
1643
+ readonly requireCanonicalization?: boolean;
1644
+ /** Skip CHECK scratch work when the caller's dialect does not support CHECK DDL. */
1645
+ readonly canonicalizeCheckConstraints?: boolean;
1646
+ /** Capabilities used to generate the migration this scope is staging for. */
1647
+ readonly dialectCapabilities?: DialectCapabilities;
1648
+ }
1649
+ /** The comparison result for one CHECK owned by an application assertion. */
1650
+ type OwnedCheckState = 'healthy' | 'absent' | 'unrenderable' | 'definition-mismatch' | 'unvalidated';
1651
+ declare class CheckConstraintCanonicalizationError extends Error {
1652
+ readonly table: string;
1653
+ readonly constraints: readonly string[];
1654
+ readonly cause: unknown;
1655
+ constructor(table: string, constraints: readonly string[], cause: unknown);
1656
+ }
1657
+ declare class ColumnDefaultCanonicalizationError extends Error {
1658
+ readonly table: string;
1659
+ readonly column: string;
1660
+ readonly cause: unknown;
1661
+ constructor(table: string, column: string, cause: unknown);
1662
+ }
1663
+ /**
1664
+ * Canonicalise PostgreSQL CHECK constraint expressions in a desired model.
1665
+ */
1666
+ declare function canonicalizeCheckConstraints(adapter: RollbackOnlyPgsqlScope, desired: ModelIR, dbModel: ModelIR, options?: CanonicalizeCheckConstraintsOptions): Promise<ModelIR>;
1667
+
1668
+ interface ComparePgsqlDatabaseSchemaOptions$1 extends CompareSchemataOptions$1, SchemaScopeOptions {
1669
+ /**
1670
+ * Whether to canonicalise PostgreSQL CHECK constraint expressions, column defaults, and predicates on column-keyed
1671
+ * partial indexes before comparing. Defaults to `true`. Expression-keyed
1672
+ * partial-index predicates are reported as unavailable. Set to `false` only for compatibility with
1673
+ * legacy raw-string live diffs.
1674
+ *
1675
+ * Live canonicalisation creates temporary scratch tables inside an adapter
1676
+ * scratch scope whose successful cleanup is rollback. The database role needs
1677
+ * permission to create temporary tables and use the scratch column types. If
1678
+ * PostgreSQL refuses that scratch DDL, non-strict mode warns and falls back to
1679
+ * best-effort raw string comparison for the affected expression surfaces.
1680
+ */
1681
+ readonly canonicalizeExpressions?: boolean;
1682
+ /**
1683
+ * Receives live expression canonicalisation warnings. Defaults to the core logger.
1684
+ */
1685
+ readonly onWarning?: (message: string) => void;
1686
+ /** Receives the identity-bearing canonicalisation warning before its string form. */
1687
+ readonly onExpressionCanonicalizationWarning?: (warning: ExpressionCanonicalizationWarning) => void;
1688
+ /**
1689
+ * Diff that the caller just applied before this live re-diff. Used only when
1690
+ * expression surfaces are compared by raw text to fail loudly if the exact same
1691
+ * expression-surface drift appears again after re-introspection.
1692
+ */
1693
+ readonly previouslyAppliedDiff?: SchemaDiff;
1694
+ /** Internal physical-to-authored sequence provenance for legacy-name refusal. */
1695
+ readonly declaredSequenceNames?: ReadonlyMap<string, string>;
1696
+ }
1697
+ /**
1698
+ * Compare the declared shape of an adopted table against its live PostgreSQL
1699
+ * counterpart. The supplied model is deliberately declaration-scoped: the whole
1700
+ * schema is introspected, so an adopted table's foreign keys to any table are
1701
+ * seen, and the comparison then keeps only the declared physical tables (with
1702
+ * the relations between them), so drift on other tables is not reported.
1703
+ */
1704
+ interface ComparePgsqlDeclaredAdoptionSchemaInput {
1705
+ readonly executor: PgsqlAdoptionComparisonExecutor;
1706
+ readonly model: ModelIR;
1707
+ readonly schema: string;
1708
+ readonly dbCasing: DbCasing;
1709
+ /**
1710
+ * Already-physicalized naming authority for `model`. Callers that own a
1711
+ * snapshot pass it here so comparison never re-applies logical naming.
1712
+ */
1713
+ readonly physical?: PgPhysicalModel;
1714
+ /** Physical [table, index] JSON keys whose drop drift is unmanaged. */
1715
+ readonly externalIndexMask?: ReadonlySet<string>;
1716
+ /** Physical [table, surface] JSON keys maintained by application assertions. */
1717
+ readonly ownershipMask?: PgsqlDeclaredAdoptionOwnershipMask;
1718
+ /** Internal physical-to-authored sequence provenance for legacy-name refusal. */
1719
+ readonly declaredSequenceNames?: ReadonlyMap<string, string>;
1720
+ }
1721
+ /** Internal converge-only declaration mask; public database comparison is unchanged. */
1722
+ interface PgsqlDeclaredAdoptionOwnershipMask {
1723
+ readonly checks: ReadonlySet<string>;
1724
+ readonly columnTypes: ReadonlySet<string>;
1725
+ readonly indexes: ReadonlySet<string>;
1726
+ }
1727
+ /** Minimal pool surface retained so callers can keep their executor opaque. */
1728
+ interface PgsqlAdoptionComparisonExecutor {
1729
+ query(sql: string, parameters?: readonly unknown[]): Promise<{
1730
+ readonly rows: readonly Record<string, unknown>[];
1731
+ }>;
1732
+ }
1733
+ /** Builds the declaration-scoped model used by every adoption shape check. */
1734
+ declare function modelForDeclaredAdoption(table: TableIR): ModelIR;
1735
+ /**
1736
+ * PostgreSQL-aware comparison used to admit a declared table adoption. A
1737
+ * claimed session remains pinned by constructing a borrowed, transaction-aware
1738
+ * adapter from that exact executor.
1739
+ */
1740
+ declare function comparePgsqlDeclaredAdoptionSchema(input: ComparePgsqlDeclaredAdoptionSchemaInput): Promise<SchemaDiff>;
1741
+ type NonConvergentSchemaDiffSurface = {
1742
+ readonly kind: 'check_constraint';
1743
+ readonly table: string;
1744
+ readonly constraint: string;
1745
+ } | {
1746
+ readonly kind: 'column_default';
1747
+ readonly table: string;
1748
+ readonly column: string;
1749
+ };
1750
+ declare class NonConvergentSchemaDiffError extends Error {
1751
+ readonly surface: NonConvergentSchemaDiffSurface;
1752
+ readonly desiredExpressionHash: string;
1753
+ readonly databaseExpressionHash: string;
1754
+ constructor(surface: NonConvergentSchemaDiffSurface, desiredExpressionHash: string, databaseExpressionHash: string);
1755
+ }
1756
+ /** An enum value this diff adds, reported as a candidate cause — never asserted. */
1757
+ interface AddedEnumValue {
1758
+ readonly enumName: string;
1759
+ readonly value: string;
1760
+ }
1761
+ declare class CheckConstraintNewEnumValueError extends Error {
1762
+ readonly table: string;
1763
+ readonly constraint: string;
1764
+ readonly addedEnumValues: readonly AddedEnumValue[];
1765
+ constructor(table: string, constraint: string, addedEnumValues: readonly AddedEnumValue[]);
1766
+ }
1767
+ /** A raw partial-index predicate and added enum values cannot share one migration. */
1768
+ declare class PartialIndexPredicateNewEnumValueError extends Error {
1769
+ readonly addedEnumValues: readonly AddedEnumValue[];
1770
+ constructor(addedEnumValues: readonly AddedEnumValue[]);
1771
+ }
1772
+ /** #454: Predicate canonicalization is not implemented for indexes with expression keys. */
1773
+ declare class ExpressionKeyedIndexPredicateCanonicalizationUnsupportedError extends Error {
1774
+ readonly predicates: readonly {
1775
+ readonly side: 'desired' | 'database';
1776
+ readonly table: string;
1777
+ readonly index: string;
1778
+ }[];
1779
+ constructor(predicates: readonly {
1780
+ readonly side: 'desired' | 'database';
1781
+ readonly table: string;
1782
+ readonly index: string;
1783
+ }[]);
1784
+ }
1785
+ /**
1786
+ * A raw partial-index predicate cannot be proven to converge after PostgreSQL
1787
+ * deparses it, so emitting its CREATE statement is unsafe.
1788
+ */
1789
+ declare class RawIndexPredicateFallbackError extends Error {
1790
+ constructor(cause?: unknown);
1791
+ }
1792
+ declare class IndexPredicateCanonicalizationError extends Error {
1793
+ readonly rejectedPredicates: readonly {
1794
+ readonly side: 'desired' | 'database';
1795
+ readonly table: string;
1796
+ readonly index: string;
1797
+ readonly reason?: unknown;
1798
+ }[];
1799
+ /**
1800
+ * Enum values added by this migration are diagnostic candidates only. They
1801
+ * are collected from the schema diff, never matched to a rejected index.
1802
+ */
1803
+ readonly addedEnumValues: readonly AddedEnumValue[];
1804
+ constructor(rejectedPredicates: readonly {
1805
+ readonly side: 'desired' | 'database';
1806
+ readonly table: string;
1807
+ readonly index: string;
1808
+ readonly reason?: unknown;
1809
+ }[],
1810
+ /**
1811
+ * Enum values added by this migration are diagnostic candidates only. They
1812
+ * are collected from the schema diff, never matched to a rejected index.
1813
+ */
1814
+ addedEnumValues?: readonly AddedEnumValue[]);
1815
+ }
1816
+ /**
1817
+ * Live PostgreSQL schema diff: introspect, canonicalise desired CHECK
1818
+ * constraint expressions, column defaults, and predicates on column-keyed
1819
+ * partial indexes through PostgreSQL, then call the pure synchronous
1820
+ * schema comparator.
1821
+ *
1822
+ * If CHECK canonicalisation falls back while the same diff adds a plausibly
1823
+ * referenced enum value, the diff is refused. dbsp currently applies each
1824
+ * migration in one transaction, and PostgreSQL forbids using a newly added enum
1825
+ * value in that same transaction; emitting the CHECK would produce a migration
1826
+ * that cannot run. Apply the enum addition by itself first, then add or update
1827
+ * the CHECK constraint in a later migration.
1828
+ *
1829
+ * Index expressions are intentionally not canonicalised here; partial-index
1830
+ * predicates on expression-keyed indexes are reported as unavailable and are
1831
+ * therefore rejected by strict mode. They need their own key-shape substrate.
1832
+ */
1833
+ declare function comparePgsqlDatabaseSchema$1(adapter: PgsqlAdapter, desired: ModelIR, options?: ComparePgsqlDatabaseSchemaOptions$1): Promise<SchemaDiff>;
1834
+ declare function assertNoRepeatedExpressionSurfaceDrift(previouslyAppliedDiff: SchemaDiff, currentDiff: SchemaDiff, rawExpressionSurfaces?: ReadonlySet<string>): void;
1835
+
1836
+ /**
1837
+ * Migration SQL Generator (DDL-PROV Block 1)
1838
+ *
1839
+ * Generates ordered SQL statements from a SchemaDiff.
1840
+ * Statements are topologically sorted: DROP constraints → DROP objects → CREATE objects → ADD constraints.
1841
+ *
1842
+ * @module migration-sql
1843
+ */
1844
+
1845
+ interface MigrationSQLOptions$1 {
1846
+ /**
1847
+ * Schema namespace (default: none — unqualified).
1848
+ * Required when emitted migration SQL would otherwise mix non-default
1849
+ * target-scoped custom types/enums with unqualified table SQL.
1850
+ */
1851
+ readonly schemaName?: string;
1852
+ /** Whether to include destructive changes (drops) */
1853
+ readonly includeDestructive?: boolean;
1854
+ /** Automatically create indexes on FK columns for new tables (default: true) */
1855
+ readonly fkAutoIndex?: boolean;
1856
+ /**
1857
+ * Declared model whose FK-index coverage controls automatic index emission.
1858
+ * This lets callers mask generated DDL surfaces without changing the
1859
+ * declaration-level decision to emit an automatic FK index.
1860
+ */
1861
+ readonly fkAutoIndexCoverage?: ModelIR;
1862
+ /** Dialect capabilities — unsupported index features throw during migration SQL generation */
1863
+ readonly dialectCapabilities?: DialectCapabilities;
1864
+ }
1865
+ /**
1866
+ * Generate ordered SQL statements from a SchemaDiff.
1867
+ *
1868
+ * Topological order:
1869
+ * 0. DROP FK/CHECK constraints (must drop before referenced tables)
1870
+ * 1. DROP indexes
1871
+ * 2. DROP columns
1872
+ * 3. DROP primary keys
1873
+ * 4. DROP tables, DROP ENUMs
1874
+ * 5. CREATE ENUMs (must exist before tables that use them)
1875
+ * 6. CREATE tables
1876
+ * 7. ADD columns
1877
+ * 8. ALTER columns (type, nullable, default)
1878
+ * 9. ADD primary keys / column UNIQUE constraints
1879
+ * 10. ADD FK constraints (must add after referenced tables exist)
1880
+ * 11. ALTER FK (drop + re-add)
1881
+ * 12. CREATE indexes
1882
+ * 13. ADD CHECK constraints
1883
+ * 14. ALTER ENUM ADD VALUE (must be last — has transaction visibility caveats in PG)
1884
+ * 15. COMMENT ON TABLE / COLUMN (very last)
1885
+ */
1886
+ declare function generateMigrationSQL$1(diff: SchemaDiff, options?: MigrationSQLOptions$1): readonly string[];
1887
+ /**
1888
+ * Generate ordered DOWN SQL statements from a SchemaDiff.
1889
+ *
1890
+ * Reverses the topological order used in UP migrations:
1891
+ * phases run in descending order (18, 17, ..., 0).
1892
+ *
1893
+ * Irreversible drops with missing or unmanaged metadata produce SQL WARNING
1894
+ * comments instead of reconstructing the dropped object.
1895
+ */
1896
+ declare function generateDownSQL$1(diff: SchemaDiff, options?: MigrationSQLOptions$1): readonly string[];
1897
+
1898
+ /** Public physical-model DDL facade. The rendering engines remain ModelIR-only. */
1899
+
1900
+ interface GenerateDDLOptions extends Omit<GenerateDDLOptions$1, 'schemaName' | 'naming' | 'fkAutoIndex'> {
1901
+ }
1902
+ interface CompareSchemataOptions extends Omit<CompareSchemataOptions$1, 'schema' | 'dbCasing' | 'declaredSequenceNames'> {
1903
+ }
1904
+ interface ComparePgsqlDatabaseSchemaOptions extends Omit<ComparePgsqlDatabaseSchemaOptions$1, 'schema' | 'dbCasing' | 'declaredSequenceNames'> {
1905
+ }
1906
+ interface MigrationSQLOptions extends Omit<MigrationSQLOptions$1, 'schemaName' | 'fkAutoIndex' | 'fkAutoIndexCoverage'> {
1907
+ }
1908
+ interface PgSchemaDiff extends SchemaDiff {
1909
+ readonly physical: Pick<PgPhysicalModel, 'schema' | 'fkAutoIndex'>;
1910
+ }
1911
+ declare function generateDDL(physical: PgPhysicalModel, options?: GenerateDDLOptions): string[];
1912
+ declare function compareSchemata(desired: PgPhysicalModel, database: PgPhysicalModel, options?: CompareSchemataOptions): PgSchemaDiff;
1913
+ declare function comparePgsqlDatabaseSchema(adapter: PgsqlAdapter, desired: PgPhysicalModel, options?: ComparePgsqlDatabaseSchemaOptions): Promise<PgSchemaDiff>;
1914
+ declare function generateMigrationSQL(diff: PgSchemaDiff, options?: MigrationSQLOptions): readonly string[];
1915
+ declare function generateDownSQL(diff: PgSchemaDiff, options?: MigrationSQLOptions): readonly string[];
1916
+
1917
+ /** The intentionally narrow query facade passed to application callbacks. */
1918
+ interface PgApplicationStepTx {
1919
+ query<Row extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<{
1920
+ readonly rows: readonly Row[];
1921
+ }>;
1922
+ }
1923
+ interface PgConvergeApplicationStepBase {
1924
+ readonly id: string;
1925
+ readonly digest: string;
1926
+ readonly scope?: 'schema';
1927
+ readonly phase: 'before-generated-ddl' | 'after-generated-ddl';
1928
+ readonly lockTimeoutMs?: number;
1929
+ readonly statementTimeoutMs?: number;
1930
+ }
1931
+ interface PgConvergeOnceStep extends PgConvergeApplicationStepBase {
1932
+ readonly kind: 'once';
1933
+ readonly apply: (tx: PgApplicationStepTx) => Promise<void> | void;
1934
+ }
1935
+ interface PgConvergeAssertOwnership {
1936
+ readonly checks?: readonly {
1937
+ readonly table: string;
1938
+ readonly name: string;
1939
+ }[];
1940
+ readonly columnTypes?: readonly {
1941
+ readonly table: string;
1942
+ readonly column: string;
1943
+ }[];
1944
+ readonly indexes?: readonly {
1945
+ readonly table: string;
1946
+ readonly name: string;
1947
+ }[];
1948
+ }
1949
+ type PgOwnedCheckState = OwnedCheckState;
1950
+ interface PgApplicationStepOwnedState {
1951
+ readonly checks: readonly {
1952
+ readonly table: string;
1953
+ readonly name: string;
1954
+ readonly physicalTable: string;
1955
+ readonly physicalName: string;
1956
+ readonly state: PgOwnedCheckState;
1957
+ }[];
1958
+ }
1959
+ interface PgConvergeAssertStep extends PgConvergeApplicationStepBase {
1960
+ readonly kind: 'assert';
1961
+ /** Declaration surfaces maintained by this assertion rather than converge. */
1962
+ readonly owns?: PgConvergeAssertOwnership;
1963
+ readonly inspect: (tx: PgApplicationStepTx, owned: PgApplicationStepOwnedState) => Promise<'healthy' | 'unhealthy'> | 'healthy' | 'unhealthy';
1964
+ readonly apply: (tx: PgApplicationStepTx, owned: PgApplicationStepOwnedState) => Promise<void> | void;
1965
+ }
1966
+ type PgConvergeApplicationStep = PgConvergeOnceStep | PgConvergeAssertStep;
1967
+
1968
+ type PgConvergeRefusal = 'invalid-options' | 'unsupported-change' | 'unmanaged-object' | 'unmanaged-parent' | 'concurrent-drift' | 'ledger-absent' | 'incompatible-ledger' | 'unsupported-server' | 'busy' | 'recovery-required' | 'database-read-only' | 'execution-refused' | 'adoption-refused' | 'application-step-changed' | 'application-step-failed' | 'initialization-refused';
1969
+ interface PgConvergeInitializationFailure {
1970
+ readonly home: LedgerHome;
1971
+ readonly code: string;
1972
+ readonly step: string;
1973
+ readonly detail: string;
1974
+ }
1975
+ type PgConvergeRefusalChange = Pick<SchemaChange, 'kind' | 'table' | 'column' | 'details'> & {
1976
+ /**
1977
+ * Present for create_index and drop_index when the index has a name: always
1978
+ * for a live index and for a logical-mode physical model, which names every
1979
+ * index; a physical-mode snapshot passes its own names through as given.
1980
+ */
1981
+ readonly index?: string;
1982
+ };
1983
+ /**
1984
+ * Unsupported-change, ledger and ownership refusals occur before converge commits
1985
+ * managed DDL. An execution refusal may follow a rolled-back transactional DDL
1986
+ * attempt, and comparison may use rollback-only scratch DDL.
1987
+ */
1988
+ declare class PgConvergeRefusalError extends Error {
1989
+ readonly refusal: PgConvergeRefusal;
1990
+ readonly changes: readonly PgConvergeRefusalChange[];
1991
+ readonly detail?: string | undefined;
1992
+ readonly runIds?: readonly string[] | undefined;
1993
+ readonly executionIds?: readonly string[] | undefined;
1994
+ readonly busyRunIds?: readonly string[] | undefined;
1995
+ readonly initialization?: PgConvergeInitializationFailure | undefined;
1996
+ constructor(refusal: PgConvergeRefusal, changes: readonly PgConvergeRefusalChange[], detail?: string | undefined, runIds?: readonly string[] | undefined, executionIds?: readonly string[] | undefined, busyRunIds?: readonly string[] | undefined, initialization?: PgConvergeInitializationFailure | undefined, options?: ErrorOptions);
1997
+ }
1998
+ type PgConvergeResult = {
1999
+ readonly kind: 'no-drift';
2000
+ readonly applied: readonly string[];
2001
+ } | {
2002
+ readonly kind: 'applied';
2003
+ readonly applied: readonly string[];
2004
+ } | {
2005
+ readonly kind: 'partially-applied';
2006
+ readonly completedStepKeys: readonly string[];
2007
+ readonly notStartedStepKeys: readonly string[];
2008
+ readonly detail: string;
2009
+ } | {
2010
+ readonly kind: 'transport-ambiguous';
2011
+ readonly detail: string;
2012
+ };
2013
+ type PgConvergePlannedStep = {
2014
+ readonly stepKey: string;
2015
+ readonly order: number;
2016
+ readonly dependencyOrder: readonly string[];
2017
+ readonly address: NonNullable<NormalizedManagedStep['address']>;
2018
+ readonly kind: SchemaChange['kind'];
2019
+ readonly table: string;
2020
+ readonly column?: string;
2021
+ readonly details: string;
2022
+ } | {
2023
+ readonly stepKey: string;
2024
+ readonly order: number;
2025
+ readonly dependencyOrder: readonly string[];
2026
+ readonly address: NonNullable<NormalizedManagedStep['address']>;
2027
+ readonly kind: 'adopt_table' | 'adopt_sequence';
2028
+ } | {
2029
+ readonly kind: 'application-step';
2030
+ readonly id: string;
2031
+ readonly step: 'once';
2032
+ readonly inspected?: never;
2033
+ readonly stepKey?: never;
2034
+ readonly order?: never;
2035
+ readonly dependencyOrder?: never;
2036
+ readonly address?: never;
2037
+ } | {
2038
+ readonly kind: 'application-step';
2039
+ readonly id: string;
2040
+ readonly step: 'assert';
2041
+ readonly inspected: boolean;
2042
+ readonly stepKey?: never;
2043
+ readonly order?: never;
2044
+ readonly dependencyOrder?: never;
2045
+ readonly address?: never;
2046
+ };
2047
+ type PgConvergeCheckResult = {
2048
+ readonly kind: 'no-drift';
2049
+ } | {
2050
+ readonly kind: 'would-apply';
2051
+ readonly planDigest: string;
2052
+ readonly steps: readonly PgConvergePlannedStep[];
2053
+ };
2054
+ interface ConvergePgBaseOptions {
2055
+ readonly schema?: string;
2056
+ readonly dbCasing?: DbCasing;
2057
+ /** Internal physical-model rendering choice; public callers cannot override it. */
2058
+ readonly fkAutoIndex?: boolean;
2059
+ /** Internal physical-to-authored sequence provenance for legacy-name refusal. */
2060
+ readonly declaredSequenceNames?: ReadonlyMap<string, string>;
2061
+ /**
2062
+ * In apply mode, create a ledger for an absent schema ledger. `pristine`
2063
+ * refuses declared live tables or standalone sequences; `adopt-existing`
2064
+ * also adopts matching declared relations on every converge call. The schema
2065
+ * itself must already exist. Defaults to `never`.
2066
+ */
2067
+ readonly initialize?: 'never' | 'pristine' | 'adopt-existing';
2068
+ /**
2069
+ * Exact physical PostgreSQL index names that converge must leave alone on
2070
+ * declared model tables. Each table name uses the model's naming, while the
2071
+ * index name is used verbatim. Entries are validated before connecting: they
2072
+ * must be distinct, name declared tables, and must not equal the name of an
2073
+ * index listed in any declared table's `indexes`. Converge never drops a
2074
+ * live index named here. It does not check these names against the other
2075
+ * relations the model creates (tables, sequences, primary-key or UNIQUE
2076
+ * constraint indexes); PostgreSQL rejects such a collision when the step
2077
+ * runs, and converge reports it as that step's failure.
2078
+ */
2079
+ readonly externalIndexes?: readonly {
2080
+ readonly table: string;
2081
+ readonly name: string;
2082
+ }[];
2083
+ /**
2084
+ * Transactional application-owned schema work. Recorded runs append
2085
+ * `application-step:<id>` to `applied`, after generated change kinds.
2086
+ * The transaction facade rejects leading transaction-control keywords; it is
2087
+ * a correctness guard, not a security boundary for code in this process.
2088
+ */
2089
+ readonly steps?: readonly PgConvergeApplicationStep[];
2090
+ }
2091
+ interface ConvergePgOptions extends ConvergePgBaseOptions {
2092
+ readonly mode?: 'apply';
2093
+ }
2094
+ interface ConvergePgCheckOptions extends ConvergePgBaseOptions {
2095
+ readonly mode: 'check';
2096
+ }
2097
+ /**
2098
+ * Converges only startup-safe PostgreSQL additions: it creates tables and
2099
+ * sequences, adds nullable columns without defaults and NOT NULL columns with
2100
+ * boolean, finite-number, or non-function-like string literal defaults of a
2101
+ * a PostgreSQL built-in base type or an enum to managed tables, and creates
2102
+ * indexes, CHECK constraints, and foreign keys when their table parents are
2103
+ * created by this same run (for foreign keys, both tables).
2104
+ * Other defaulted original database types are refused.
2105
+ *
2106
+ * Adding a column still takes an ACCESS EXCLUSIVE lock on its table, bounded by
2107
+ * the executor's five-second lock_timeout and held through read-back and the
2108
+ * ledger terminal. A no-rewrite default is therefore not non-blocking.
2109
+ *
2110
+ * Converge mutates only declared additions whose target and existing parent pass
2111
+ * managed admission. It compares the declared tables, sequences, and enums'
2112
+ * structural shape; it does not audit the provenance of an exact-matching child
2113
+ * already present on a managed table.
2114
+ * An assert may own declared CHECKs, column types, and named indexes; those
2115
+ * surfaces are excluded from comparison and generated DDL. Its read-only
2116
+ * `inspect` receives canonical owned-CHECK state, while its callback is
2117
+ * responsible for maintaining them. `externalIndexes` accepts exact physical
2118
+ * index names on logical model tables;
2119
+ * entries are validated before the ledger lock or any query, and converge
2120
+ * never drops a matching live index. A name that collides with another
2121
+ * relation the model creates fails when that step runs.
2122
+ * Before comparison, converge refuses while its target ledger home has a live
2123
+ * reservation: wait for a run that is still executing, reconcile a run whose
2124
+ * lock is free with reconcilePgTransitionRun or `dbsp reconcile --db
2125
+ * <database> <run-id>`, have the ledger owner resolve an unmapped reservation
2126
+ * and the journal owner one whose journal attribution cannot be read, then call
2127
+ * converge again.
2128
+ * Application steps run on the converge session: session-level effects such as
2129
+ * `SET` without `LOCAL`, `SET ROLE`, `LISTEN`, `PREPARE`, temporary tables and
2130
+ * session advisory locks are not part of a step and can affect the rest of the
2131
+ * call. Steps should use `SET LOCAL`.
2132
+ * A declared table with `adopt: true` is taken into management when it exists,
2133
+ * the ledger projects its address as unknown (the only state an adoption claim
2134
+ * opens from), and it matches the declaration exactly after `externalIndexes`
2135
+ * and application ownership masking. A mismatch found while planning refuses
2136
+ * `adoption-refused` before anything is written. A table that changes while
2137
+ * its adoption runs is refused under its claim and the ledger records that
2138
+ * refused adoption; tables adopted earlier in the same call stay adopted.
2139
+ * Tables a run creates and every change on those tables commit together or not
2140
+ * at all. A sequence created by the same run commits on its own and can remain
2141
+ * after a failure. After a transport-ambiguous outcome, the next call observes
2142
+ * whichever state PostgreSQL holds. Converge runs are not journaled. Check mode
2143
+ * returns a point-in-time plan without executing it; it is not a guarantee that
2144
+ * a later apply will succeed, because other sessions can change the database
2145
+ * and execution-time ledger physical-shape integrity, claim-time adoption
2146
+ * re-verification, vacancy, and lock-timeout checks are not reproduced.
2147
+ * `initialize` defaults to `never`. `pristine` creates an absent ledger only
2148
+ * when declared tables and standalone sequences are absent, while
2149
+ * `adopt-existing` creates an absent ledger and adopts matching declared
2150
+ * relations on every call. The target schema must already exist. Application
2151
+ * steps run with `search_path` set to the target schema, `pg_temp`, then the
2152
+ * connection's entries, so `current_schema()` is the target. Lookup goes through
2153
+ * `pg_catalog` first unless those entries name it explicitly, then the target,
2154
+ * `pg_temp` and those entries.
2155
+ */
2156
+ declare function convergePg(pool: Pool, model: ModelIR, options?: ConvergePgOptions): Promise<PgConvergeResult>;
2157
+ declare function convergePg(pool: Pool, model: ModelIR, options: ConvergePgCheckOptions): Promise<PgConvergeCheckResult>;
2158
+
2159
+ type QueryResultLike = {
2160
+ readonly rows: readonly Record<string, unknown>[];
2161
+ };
2162
+ type TransitionJournalQueryable = {
2163
+ query(sql: string, params?: readonly unknown[]): Promise<QueryResultLike>;
2164
+ };
2165
+ /** A copied plan row is not authority for a differently named run. */
2166
+ declare class TransitionRunIdentityMismatchError extends Error {
2167
+ constructor();
2168
+ }
2169
+ declare function renderCreateDbspMetaSchemaSql(): string;
2170
+ declare function renderCreateTransitionRunTableSql(exclusive?: boolean): string;
2171
+ declare function renderCreateTransitionJournalTableSql(exclusive?: boolean): string;
2172
+ declare function renderCreateTransitionRunPlanTableSql(exclusive?: boolean): string;
2173
+ declare function renderCreateTransitionAuthorizationTableSql(exclusive?: boolean): string;
2174
+ declare function ensureTransitionJournal(executor: TransitionJournalQueryable): Promise<void>;
2175
+ declare function createPgTransitionRunPersister(executor: TransitionJournalQueryable): TransitionRunPersister;
2176
+ declare function appendIntentJournal(executor: TransitionJournalQueryable, record: DurableIntentRecord): Promise<void>;
2177
+ /** Append-only run approval, intentionally separate from step attempts. */
2178
+ declare function appendTransitionAuthorization(executor: TransitionJournalQueryable, record: TransitionRunAuthorization): Promise<void>;
2179
+ declare function readTransitionJournal(executor: TransitionJournalQueryable, runId: string, options?: {
2180
+ readonly ensure?: boolean;
2181
+ }): Promise<TransitionRunJournal & {
2182
+ readonly plan: ProvenPlanShape;
2183
+ }>;
2184
+
2185
+ interface PgCatalogueIdentityQueryable {
2186
+ query(sql: string, params?: readonly unknown[]): Promise<{
2187
+ readonly rows: readonly Record<string, unknown>[];
2188
+ }>;
2189
+ }
2190
+ /**
2191
+ * Re-read the PostgreSQL catalogue identity for one managed address. The
2192
+ * adapter deliberately returns absence as undefined; callers decide whether an
2193
+ * absent object is legal for the lifecycle state they are admitting.
2194
+ */
2195
+ declare function readPgCatalogueIdentity(executor: PgCatalogueIdentityQueryable, address: ResourceAddress): Promise<ResourceAddress | undefined>;
2196
+
2197
+ declare const PG_LEDGER_SHAPE_VERSION = 1;
2198
+ declare const ledgerShapeAllowanceBrand: unique symbol;
2199
+ /**
2200
+ * An in-process allowance for one non-ledger trigger observed immediately
2201
+ * after trusted harness setup. Its contents are deliberately not structural:
2202
+ * only the internal factory can register a value in the WeakSet below.
2203
+ */
2204
+ interface PgLedgerShapeAllowance {
2205
+ readonly [ledgerShapeAllowanceBrand]: 'dbsp-ledger-shape-allowance';
2206
+ }
2207
+ type PgLedgerPhysicalShapeOutcome = {
2208
+ readonly kind: 'verified';
2209
+ } | {
2210
+ readonly kind: 'shape-wrong';
2211
+ readonly artefact: string;
2212
+ } | {
2213
+ readonly kind: 'unverifiable';
2214
+ readonly cause: string;
2215
+ } | {
2216
+ readonly kind: 'unsupported-major';
2217
+ readonly major: number | undefined;
2218
+ } | {
2219
+ readonly kind: 'validator-abi-failure';
2220
+ readonly sqlstate: string;
2221
+ };
2222
+ /**
2223
+ * Read-only admission of an existing ledger. A fixture is deliberately a
2224
+ * prerequisite: deparse text is not portable across PostgreSQL majors.
2225
+ */
2226
+ declare function classifyPgLedgerPhysicalShape(executor: TransitionJournalQueryable, target: PgLedgerTarget, allowance?: PgLedgerShapeAllowance): Promise<PgLedgerPhysicalShapeOutcome>;
2227
+ /**
2228
+ * Throwing compatibility façade. Existing mutating callers intentionally keep
2229
+ * their historical contract; outcome-aware consumers use `classify…`.
2230
+ */
2231
+ declare function validatePgLedgerPhysicalShape(executor: TransitionJournalQueryable, target: PgLedgerTarget, allowance?: PgLedgerShapeAllowance): Promise<void>;
2232
+ /**
2233
+ * Mint a one-request allowance for one exact live trigger. This is exported
2234
+ * only from the adapter's `/internal` surface: consumers cannot forge the
2235
+ * WeakMap registration or serialize it into an ordinary recovery request.
2236
+ */
2237
+ declare function createPgLedgerShapeAllowance(executor: TransitionJournalQueryable, target: PgLedgerTarget, triggerName: string): Promise<PgLedgerShapeAllowance>;
2238
+ declare class PgLedgerStorageUnsupportedError extends Error {
2239
+ constructor(observed: unknown);
2240
+ }
2241
+ declare const pgOrderedLedgerLocksBrand: unique symbol;
2242
+ /** Proof returned only after this transaction acquired every home in order. */
2243
+ interface PgOrderedLedgerLocks {
2244
+ readonly homes: readonly PgLedgerTarget[];
2245
+ readonly [pgOrderedLedgerLocksBrand]: 'dbsp-pg-ordered-ledger-locks';
2246
+ }
2247
+ type PgLedgerLockResult = {
2248
+ readonly kind: 'acquired';
2249
+ readonly proof: PgOrderedLedgerLocks;
2250
+ } | {
2251
+ readonly kind: 'busy';
2252
+ readonly ledger: LedgerHome;
2253
+ } | {
2254
+ readonly kind: 'refused';
2255
+ readonly ledger: LedgerHome;
2256
+ readonly error: unknown;
2257
+ };
2258
+ type PgLedgerTarget = LedgerHome;
2259
+ /** Read only reservations explicitly linked to one durable execution/run. */
2260
+ declare function readPgLedgerReservationsForExecution(executor: TransitionJournalQueryable, target: PgLedgerTarget, executionId: string): Promise<readonly LedgerReservationRow[]>;
2261
+ /**
2262
+ * A re-address pair can cross ledger homes. Discover every existing reservation
2263
+ * table before reading the pair so recovery cannot accidentally treat one side
2264
+ * of a cross-schema closure as the entire operation.
2265
+ */
2266
+ type PgLedgerReservationCandidateOutcome = {
2267
+ readonly target: PgLedgerTarget;
2268
+ readonly kind: 'verified';
2269
+ } | {
2270
+ readonly target: PgLedgerTarget;
2271
+ readonly kind: 'not-ledger-shape';
2272
+ } | {
2273
+ readonly target: PgLedgerTarget;
2274
+ readonly kind: 'unverifiable';
2275
+ readonly cause: string;
2276
+ };
2277
+ type PgLedgerReservationsForPair = readonly LedgerReservationRow[] & {
2278
+ readonly candidates: readonly PgLedgerReservationCandidateOutcome[];
2279
+ };
2280
+ declare function readPgLedgerReservationsForPair(executor: TransitionJournalQueryable, pairId: string): Promise<PgLedgerReservationsForPair>;
2281
+ type LedgerWriteMember = Omit<LedgerChainMember, 'controller' | 'recordedAt'>;
2282
+ declare function renderCreateLedgerEventTableSql(target: PgLedgerTarget): string;
2283
+ declare function renderCreateLedgerTerminalMemberIndexSql(target: PgLedgerTarget): string;
2284
+ declare function renderCreateLedgerReservationTableSql(target: PgLedgerTarget): string;
2285
+ declare function renderCreateLedgerIdentityTableSql(target: PgLedgerTarget): string;
2286
+ declare function renderCreateLedgerMarkerTableSql(target: PgLedgerTarget): string;
2287
+ declare function renderCreateLedgerImmutabilityFunctionSql(target: PgLedgerTarget): string;
2288
+ declare function renderCreateLedgerImmutabilityTriggerSql(target: PgLedgerTarget): string;
2289
+ /** Proves the PG 15 requirement before emitting a NULLS NOT DISTINCT table. */
2290
+ declare function ensurePgLedgerStorageVersion(executor: TransitionJournalQueryable): Promise<void>;
2291
+ declare function ensurePgLedger(executor: TransitionJournalQueryable, target: PgLedgerTarget, options?: {
2292
+ readonly writeMarker?: boolean;
2293
+ }): Promise<void>;
2294
+ declare function ensureDbspMetaLedger(executor: TransitionJournalQueryable, options?: {
2295
+ readonly writeMarker?: boolean;
2296
+ }): Promise<void>;
2297
+ /** Records lineage once; a mismatching identity is an admission concern of unit 5. */
2298
+ declare function recordPgLedgerIdentity(executor: TransitionJournalQueryable, target: PgLedgerTarget, identity: LedgerIdentity): Promise<void>;
2299
+ declare function appendPgLedgerProgress(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember): Promise<void>;
2300
+ /**
2301
+ * Appends the root claim and every reservation in one PostgreSQL statement.
2302
+ * Callers can include this statement in a larger DDL transaction, but cannot
2303
+ * accidentally split this claim's append from its durable reservation rows.
2304
+ */
2305
+ declare function appendPgLedgerClaim(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember, reservations: readonly LedgerReservationRow[], reservationRootClaimId?: string): Promise<void>;
2306
+ /**
2307
+ * Appends an entire destructive closure as one ledger group. The caller owns
2308
+ * the surrounding locked transaction; consequently a failed member insert
2309
+ * rolls back the root, every member and every reservation together.
2310
+ */
2311
+ declare function appendPgLedgerClaimGroup(executor: TransitionJournalQueryable, root: LedgerWriteMember, members: readonly LedgerWriteMember[], reservations: readonly LedgerReservationRow[]): Promise<void>;
2312
+ /** Resolves every closure terminal in the caller's one locked transaction. */
2313
+ declare function appendPgLedgerResolutionGroup(executor: TransitionJournalQueryable, rootClaimId: string, members: readonly LedgerWriteMember[], reservations: readonly Pick<LedgerReservationRow, 'address'>[]): Promise<void>;
2314
+ /**
2315
+ * Appends a terminal member and releases the reservations owned by this
2316
+ * append atomically. A group-owned contained member has an intentionally
2317
+ * empty closure because its group's root append already released it.
2318
+ */
2319
+ declare function appendPgLedgerResolution(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember, rootClaimId: string, reservations: readonly Pick<LedgerReservationRow, 'address'>[]): Promise<void>;
2320
+ /**
2321
+ * `released` has no claim spelling in the closed event grammar. It is the
2322
+ * deliberate atomic managed-to-unknown transition, so it must not invent an
2323
+ * empty reservation closure merely to reuse ordinary claim resolution.
2324
+ */
2325
+ declare function appendPgLedgerRelease(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: LedgerWriteMember): Promise<void>;
2326
+ /**
2327
+ * Transaction-scoped, non-waiting locks for one effects closure. The ordering
2328
+ * is dbsp_meta first and then schema name, so opposing closures cannot deadlock.
2329
+ */
2330
+ declare function acquirePgLedgerLocks(executor: TransitionJournalQueryable, homes: readonly LedgerHome[]): Promise<PgLedgerLockResult>;
2331
+
2332
+ type ReinitializePreflightCheckpoint = 'archive' | 'create' | 'grants' | 'journal-create' | 'marker' | 'output';
2333
+ /** Test-only callers can observe real engine progress without changing production flow. */
2334
+ type ReinitializePreflightObserver = (checkpoint: ReinitializePreflightCheckpoint, ledger?: LedgerHome) => Promise<void>;
2335
+ interface PgReinitializePreflightClient extends TransitionJournalQueryable {
2336
+ release?(error?: unknown): void;
2337
+ }
2338
+ interface PgReinitializePreflightPool {
2339
+ connect(): Promise<PgReinitializePreflightClient>;
2340
+ }
2341
+ interface PgReinitializePreflightOptions {
2342
+ readonly pool: PgReinitializePreflightPool;
2343
+ /** Schema names only. `dbsp_meta` is always added as the database ledger. */
2344
+ readonly schemas: readonly string[];
2345
+ readonly declarations: DeclarationSet;
2346
+ readonly writeAdoptionFile: (report: ReinitializePreflightReport) => Promise<void>;
2347
+ readonly observer?: ReinitializePreflightObserver;
2348
+ }
2349
+ /**
2350
+ * Read exactly one ledger shape marker without creating or repairing anything.
2351
+ * Ordinary command surfaces use this to refuse a non-current mutating scope;
2352
+ * inspect deliberately reports the returned value instead.
2353
+ */
2354
+ declare function readPgLedgerMarker(executor: TransitionJournalQueryable, home: LedgerHome): Promise<LedgerMarkerState>;
2355
+ /**
2356
+ * Ordinary mutating commands consume this read-only admission result. It
2357
+ * intentionally delegates equality to the preflight's recorded-vs-live
2358
+ * comparison, keeping that pair as the only ledger lineage comparison.
2359
+ */
2360
+ type PgLedgerScopeCurrency = {
2361
+ readonly kind: 'absent';
2362
+ readonly marker: LedgerMarkerState;
2363
+ } | {
2364
+ readonly kind: 'current';
2365
+ readonly marker: LedgerMarkerState;
2366
+ } | {
2367
+ readonly kind: 'not-current';
2368
+ readonly marker: LedgerMarkerState;
2369
+ readonly reason: 'marker' | 'lineage';
2370
+ };
2371
+ declare function readPgLedgerScopeCurrency(executor: TransitionJournalQueryable, home: LedgerHome): Promise<PgLedgerScopeCurrency>;
2372
+ /**
2373
+ * Pair recovery reads only homes already selected by the durable run. A
2374
+ * same-named user table in another schema is never discovery evidence for a
2375
+ * pair; callers must first establish the finite candidate homes from reviewed
2376
+ * material and then each home is admitted here.
2377
+ */
2378
+ declare function readVerifiedPgLedgerReservationsForPair(executor: TransitionJournalQueryable, pairId: string, homes: readonly LedgerHome[]): Promise<readonly _dbsp_types.LedgerReservationRow[]>;
2379
+ /**
2380
+ * Runs the separately privileged reinitialize-preflight. It never invokes a
2381
+ * ledger append primitive: the only durable writes are additive structure,
2382
+ * archived structure, identity, grants, marker, and the caller-owned output.
2383
+ */
2384
+ declare function runPgReinitializePreflight(options: PgReinitializePreflightOptions): Promise<ReinitializePreflightReport>;
2385
+
2386
+ declare const pgLockedRunBrand: unique symbol;
2387
+ /**
2388
+ * A run identity that was loaded while the caller owns its run lock. This is
2389
+ * deliberately not a structural `{ runId, planDigest }`: callers cannot bind
2390
+ * the digest check to two independently supplied strings.
2391
+ */
2392
+ interface PgLockedRun {
2393
+ readonly runId: string;
2394
+ readonly planDigest: string;
2395
+ readonly [pgLockedRunBrand]: 'dbsp-pg-locked-journal-run';
2396
+ }
2397
+ /**
2398
+ * Adapter-only bridge from the journal-load/run-lock boundary. Keep this
2399
+ * beside the admitted facade; ordinary callers receive a `PgLockedRun`, never
2400
+ * manufacture one from string fields.
2401
+ */
2402
+ declare function lockPgJournalRun(run: DurablyLoadedRun): PgLockedRun;
2403
+ /** A COMMIT write may have reached PostgreSQL even when its acknowledgement did not. */
2404
+ declare class PgCommitAcknowledgementAmbiguousError extends Error {
2405
+ constructor(cause: unknown);
2406
+ }
2407
+ /**
2408
+ * Test-only observation points on the admitted path. Production callers do
2409
+ * not supply an observer, so the helper is inert: it performs no IPC, I/O, or
2410
+ * scheduling work in an ordinary run.
2411
+ */
2412
+ type PgOutcomeCheckpoint = 'post-lock-integrity-before-append' | 'commit-acknowledged' | 'ddl-completed-before-read-back';
2413
+ type PgOutcomeCheckpointObserver = (checkpoint: PgOutcomeCheckpoint) => Promise<void> | void;
2414
+ interface PgOutcomeClaimRequest {
2415
+ readonly plan: OutcomeClaimPlan;
2416
+ readonly reservations: readonly LedgerReservationRow[];
2417
+ readonly lockTimeoutMs?: number;
2418
+ /** Destructive authority is evaluated under these same ledger locks. */
2419
+ readonly destructiveDecision?: (executor: TransitionJournalQueryable, plan: OutcomeClaimPlan) => Promise<DestructiveDecision>;
2420
+ /** Optional E2E observer; absent in all production command paths. */
2421
+ readonly observer?: PgOutcomeCheckpointObserver;
2422
+ }
2423
+ /** One root claim plus its token-free destructive-closure members. */
2424
+ interface PgOutcomeClaimGroupRequest extends PgOutcomeClaimRequest {
2425
+ readonly members: readonly Omit<PgOutcomeClaimRequest, 'destructiveDecision'>[];
2426
+ }
2427
+ interface PgOutcomeClaimGroupAdmission {
2428
+ readonly root: OutcomeClaimAdmission;
2429
+ readonly members: readonly OutcomeClaimAdmission[];
2430
+ }
2431
+ interface PgOutcomeClaimGroupResolution {
2432
+ readonly rootClaimId: string;
2433
+ readonly members: readonly {
2434
+ readonly target: PgLedgerTarget;
2435
+ readonly member: Omit<LedgerChainMember, 'controller' | 'recordedAt'>;
2436
+ }[];
2437
+ readonly reservations: readonly Pick<LedgerReservationRow, 'address'>[];
2438
+ readonly lockTimeoutMs?: number;
2439
+ /** Durable run witness carried from destructive admission to its terminal. */
2440
+ readonly runtimeIntegrityRun?: PgLockedRun;
2441
+ /** Optional E2E observer for this terminal-appending transaction. */
2442
+ readonly observer?: PgOutcomeCheckpointObserver;
2443
+ }
2444
+ interface PgOutcomeResolution {
2445
+ readonly eventId: string;
2446
+ readonly eventKind: Exclude<LedgerEventKind, 'intent' | 'retire-intent' | 'readdress-intent' | 'adopt-intent' | 'executing'>;
2447
+ readonly observed?: LedgerChainMember['observed'];
2448
+ /** Required by the ledger writer when this resolution is `refused`. */
2449
+ readonly refusal?: LedgerChainMember['refusal'];
2450
+ }
2451
+ interface PgOutcomeExecutionRequest {
2452
+ readonly token: ClaimToken;
2453
+ readonly claim: AdmittedOutcomeClaim;
2454
+ readonly statements: readonly ClaimBundleStatement[];
2455
+ }
2456
+ /**
2457
+ * The first admitted-operation shape. Later waves add single and paired
2458
+ * operation variants without reopening the facade's authority boundary.
2459
+ */
2460
+ interface PgSingleAdmittedOperation {
2461
+ readonly kind: 'single-outcome';
2462
+ readonly request: PgOutcomeTransactionalRequest | PgOutcomeNonTransactionalRequest;
2463
+ }
2464
+ /**
2465
+ * The three generated payload roles are intentionally disjoint at the type
2466
+ * boundary. Their runtime serialization remains the ledger's `{ value,
2467
+ * digest }` pair; the discriminant prevents a generic identity observation
2468
+ * from being wired into a declaration or a structural-proof slot.
2469
+ */
2470
+ type GeneratedDeclarationPayload = LedgerPayload & {
2471
+ readonly payloadKind: 'generated-declaration';
2472
+ };
2473
+ type GeneratedIdentityObservation = LedgerPayload & {
2474
+ readonly payloadKind: 'generated-identity-observation';
2475
+ };
2476
+ type GeneratedStructuralObservation = LedgerPayload & {
2477
+ readonly payloadKind: 'generated-structural-observation';
2478
+ };
2479
+ /**
2480
+ * Readdress keeps its catalogue closure discovery in readdress.ts, while this
2481
+ * facade owns the only claim/permit/DDL/terminal path for the resulting pair.
2482
+ */
2483
+ interface PgPairedReaddressOperation {
2484
+ readonly kind: 'paired-readdress';
2485
+ readonly request: {
2486
+ readonly pairId: string;
2487
+ readonly executionId: string;
2488
+ readonly members: readonly {
2489
+ readonly source: LedgerAddress;
2490
+ readonly target: LedgerAddress;
2491
+ readonly sourceClaimId: string;
2492
+ readonly targetClaimId: string;
2493
+ readonly sourceDeclared?: LedgerPayload;
2494
+ readonly targetDeclared: GeneratedDeclarationPayload;
2495
+ readonly targetObserved: GeneratedIdentityObservation;
2496
+ /**
2497
+ * Optional structural proof for a typed table declaration. The paired
2498
+ * protocol invokes it after DDL on its pinned transaction session, so
2499
+ * the observed ledger fact is the catalogue projection it just read.
2500
+ */
2501
+ readonly postDdlReadBack?: (executor: GeneratedPostconditionSession) => Promise<GeneratedStructuralObservation>;
2502
+ /** Verifies a physical relationship that identity alone cannot prove. */
2503
+ readonly postDdlVerify?: (executor: TransitionJournalQueryable) => Promise<void>;
2504
+ }[];
2505
+ readonly reservations: readonly LedgerReservationRow[];
2506
+ readonly statements: readonly ClaimBundleStatement[];
2507
+ /** Digest-covered root material for this paired request; it is never empty. */
2508
+ readonly manifestPlan: OutcomeClaimPlan;
2509
+ /** Re-read closure, source controller/identity and target vacancy under lock. */
2510
+ readonly verifyLiveAdmission: (executor: TransitionJournalQueryable, currentController: ControllerIdentity) => Promise<OutcomeProtocolRefusal | readonly {
2511
+ readonly source: LedgerAddress;
2512
+ readonly target: LedgerAddress;
2513
+ readonly catalogueIdentity: NonNullable<NonNullable<Awaited<ReturnType<typeof readPgCatalogueIdentity>>>['catalogueIdentity']>;
2514
+ }[]>;
2515
+ readonly lockTimeoutMs?: number;
2516
+ /** Optional E2E observer; absent in normal execution. */
2517
+ readonly observer?: PgOutcomeCheckpointObserver;
2518
+ };
2519
+ }
2520
+ interface PgDestructiveAdmittedOperation {
2521
+ readonly kind: 'destructive-outcome';
2522
+ readonly request: PgOutcomeClaimGroupRequest;
2523
+ readonly readBackAndResolve: (executor: TransitionJournalQueryable, claim: AdmittedDestructiveOutcomeClaim) => Promise<PgOutcomeClaimGroupResolution>;
2524
+ }
2525
+ type PgAdmittedOperation = PgSingleAdmittedOperation | PgPairedReaddressOperation | PgDestructiveAdmittedOperation;
2526
+ type PgAdmittedOperationResult = PgOutcomeResult | PgDestructiveOutcomeResult | {
2527
+ readonly kind: 'executed-paired-readdress';
2528
+ readonly pairId: string;
2529
+ } | {
2530
+ readonly kind: 'outcome-transport-ambiguous';
2531
+ readonly reason: string;
2532
+ } | {
2533
+ readonly kind: 'outcome-recovery-required';
2534
+ readonly claimId: string;
2535
+ readonly reason: string;
2536
+ };
2537
+ type PgDestructiveOutcomeResult = {
2538
+ readonly kind: 'executed-destructive-outcome';
2539
+ }
2540
+ /**
2541
+ * SQL was admitted and may have run, but its operation-owned read-back could
2542
+ * not establish a terminal fact. Keep the durable claim open for reconcile;
2543
+ * in particular, never turn this post-executing state into `refused`.
2544
+ */
2545
+ | {
2546
+ readonly kind: 'outcome-protocol-pending';
2547
+ readonly reason: string;
2548
+ } | OutcomeProtocolRefusal | {
2549
+ readonly kind: 'outcome-transport-ambiguous';
2550
+ readonly reason: string;
2551
+ } | {
2552
+ readonly kind: 'outcome-recovery-required';
2553
+ readonly claimId: string;
2554
+ readonly reason: string;
2555
+ };
2556
+ /**
2557
+ * Internal compatibility bridge. Callers must bring the durable run and scoped
2558
+ * approvals that the façade consumes; this bridge never invents either.
2559
+ */
2560
+ declare function executePgDestructiveOutcome(executor: TransitionJournalQueryable, input: {
2561
+ readonly run: PgLockedRun;
2562
+ readonly approval: ScopedApprovalSet;
2563
+ readonly request: PgOutcomeClaimGroupRequest;
2564
+ readonly readBackAndResolve: (executor: TransitionJournalQueryable, claim: AdmittedDestructiveOutcomeClaim) => Promise<PgOutcomeClaimGroupResolution>;
2565
+ }): Promise<PgDestructiveOutcomeResult>;
2566
+ /** Keeps terminal appends and reservation release behind the managed facade. */
2567
+ declare function resolvePgDestructiveOutcome(executor: TransitionJournalQueryable, request: PgOutcomeClaimGroupResolution): Promise<undefined | OutcomeProtocolRefusal>;
2568
+ interface PgOutcomeTransactionalRequest extends PgOutcomeClaimRequest {
2569
+ readonly resolution: PgOutcomeResolution;
2570
+ /** Core has already opened the segment transaction; never nest BEGIN. */
2571
+ readonly transactionOpen?: boolean;
2572
+ /**
2573
+ * Operation-owned terminal read-back; generic catalogue identity is not
2574
+ * evidence. It receives the admitted session so transactional DDL is read
2575
+ * before its terminal ledger fact commits.
2576
+ */
2577
+ readonly readBack?: (executor: GeneratedPostconditionSession) => Promise<LedgerPayload>;
2578
+ /** Required for creations; the reader runs after the claim and before SQL. */
2579
+ readonly vacancy?: (executor: TransitionJournalQueryable, plan: OutcomeClaimPlan) => Promise<OutcomeVacancy>;
2580
+ /** Re-check operation-specific live facts after the claim/reservation opens. */
2581
+ readonly verifyLiveAdmission?: (executor: TransitionJournalQueryable, plan: OutcomeClaimPlan) => Promise<OutcomeProtocolRefusal | undefined>;
2582
+ /** Record the post-DDL catalogue identity on a present terminal member. */
2583
+ readonly recordCatalogueIdentity?: boolean;
2584
+ }
2585
+ interface PgOutcomeNonTransactionalRequest extends PgOutcomeTransactionalRequest {
2586
+ readonly executingEventId: string;
2587
+ /** Observable acknowledgement point after executing has committed, before SQL. */
2588
+ readonly onExecutingCommitted?: () => Promise<void> | void;
2589
+ }
2590
+ /** Builds the canonical read-back payload once catalogue presence is proven. */
2591
+ type PgOutcomeReadBackFactory = (executor: GeneratedPostconditionSession, address: LedgerAddress, catalogueIdentity: NonNullable<Awaited<ReturnType<typeof readPgCatalogueIdentity>>>['catalogueIdentity']) => Promise<LedgerPayload>;
2592
+ /**
2593
+ * A postcondition read owned by the operation itself. Catalogue identity is
2594
+ * still retained when present for the ledger, but effect classification comes
2595
+ * from the operation's value-level observation rather than object presence.
2596
+ */
2597
+ type PgOutcomeOperationReadBackFactory = (executor: TransitionJournalQueryable, address: LedgerAddress, catalogueIdentity: NonNullable<Awaited<ReturnType<typeof readPgCatalogueIdentity>>>['catalogueIdentity'] | undefined) => Promise<{
2598
+ readonly observed: LedgerPayload;
2599
+ readonly effect: OutcomeRecoveryEffect;
2600
+ }>;
2601
+ interface PgOutcomeRecoveryRequest {
2602
+ readonly address: LedgerAddress;
2603
+ readonly reservations: readonly Pick<LedgerReservationRow, 'address'>[];
2604
+ readonly resolutionEventId: string;
2605
+ readonly acceptedExternalDdlExclusion: boolean;
2606
+ /** Durable claim-bound evidence re-matched by reconcile under the run lock. */
2607
+ readonly indeterminateEvidence?: OutcomeIndeterminateRecoveryEvidence;
2608
+ readonly resolveIndeterminate?: boolean;
2609
+ readonly readBack: PgOutcomeReadBackFactory;
2610
+ readonly operationReadBack?: PgOutcomeOperationReadBackFactory;
2611
+ readonly lockTimeoutMs?: number;
2612
+ /** Internal-only, in-memory allowance for one harness-installed trigger. */
2613
+ readonly ledgerShapeAllowance?: PgLedgerShapeAllowance;
2614
+ /** Optional E2E observer for recovery's committing transaction. */
2615
+ readonly observer?: PgOutcomeCheckpointObserver;
2616
+ }
2617
+ type PgOutcomeResolutionAppendResult = {
2618
+ readonly kind: 'appended-outcome-resolution';
2619
+ } | {
2620
+ readonly kind: 'already-appended-outcome-resolution';
2621
+ } | {
2622
+ readonly kind: 'malformed-outcome-resolution';
2623
+ readonly reason: string;
2624
+ };
2625
+ type PgOutcomeRecoveryResult = Exclude<OutcomeRecoveryClassification, {
2626
+ readonly kind: 'outcome-recovery-append';
2627
+ }> | {
2628
+ readonly kind: 'outcome-recovery-appended';
2629
+ readonly classification: Extract<OutcomeRecoveryClassification, {
2630
+ readonly kind: 'outcome-recovery-append';
2631
+ }>;
2632
+ readonly append: Exclude<PgOutcomeResolutionAppendResult, {
2633
+ readonly kind: 'malformed-outcome-resolution';
2634
+ }>;
2635
+ } | {
2636
+ readonly kind: 'outcome-transport-ambiguous';
2637
+ readonly reason: string;
2638
+ } | OutcomeProtocolRefusal;
2639
+ type PgOutcomeResult = {
2640
+ readonly kind: 'executed-outcome-claim';
2641
+ readonly claim: AdmittedOutcomeClaim;
2642
+ } | OutcomeProtocolRefusal | {
2643
+ readonly kind: 'outcome-transport-ambiguous';
2644
+ readonly reason: string;
2645
+ } | {
2646
+ readonly kind: 'outcome-recovery-required';
2647
+ readonly claimId: string;
2648
+ readonly reason: string;
2649
+ };
2650
+ type PgPairedReaddressRecoveryDecision = {
2651
+ readonly kind: 'refused';
2652
+ readonly reason: string;
2653
+ } | {
2654
+ readonly kind: 'pending';
2655
+ readonly reason: string;
2656
+ } | {
2657
+ readonly kind: 'indeterminate';
2658
+ readonly reason: string;
2659
+ } | {
2660
+ readonly kind: 'outcome-transport-ambiguous';
2661
+ readonly reason: string;
2662
+ };
2663
+ /**
2664
+ * Recovery owns its reservation set: it re-reads every durable pair row,
2665
+ * checks currency under the same locks, and appends only under a minted paired
2666
+ * permit. A caller's selected rows are evidence to compare, never authority.
2667
+ */
2668
+ declare function recoverPgAdmittedReaddressPair(executor: TransitionJournalQueryable, request: {
2669
+ readonly pairId: string;
2670
+ readonly executionId: string;
2671
+ readonly reservations: readonly LedgerReservationRow[];
2672
+ readonly assess: (executor: TransitionJournalQueryable, reservations: readonly LedgerReservationRow[]) => Promise<PgPairedReaddressRecoveryDecision>;
2673
+ readonly observer?: PgOutcomeCheckpointObserver;
2674
+ }): Promise<PgPairedReaddressRecoveryDecision>;
2675
+ type RuntimeIntegritySeams = {
2676
+ readonly validateShape: typeof validatePgLedgerPhysicalShape;
2677
+ readonly readCurrency: typeof readPgLedgerScopeCurrency;
2678
+ };
2679
+ /**
2680
+ * The façade's runtime gate: validate the physical ledger and its marker /
2681
+ * lineage currency on the same pinned execution session before it admits DDL.
2682
+ * Callers must still take the ledger locks before claiming; this check avoids a
2683
+ * preflight-only trust decision without widening the ledger DDL grammar.
2684
+ */
2685
+ declare function validatePgLedgerRuntimeIntegrity(executor: TransitionJournalQueryable, homes: readonly PgLedgerTarget[], run?: PgLockedRun, seams?: RuntimeIntegritySeams): Promise<OutcomeProtocolRefusal | undefined>;
2686
+ /**
2687
+ * Appends a resolution once, or treats an already-written equal payload as a
2688
+ * successful retry. A different child cannot be written by PostgreSQL's
2689
+ * one-child constraint and is reported as a fail-closed malformed outcome.
2690
+ */
2691
+ declare function appendPgOutcomeResolution(executor: TransitionJournalQueryable, target: PgLedgerTarget, member: Omit<LedgerChainMember, 'controller' | 'recordedAt'>, rootClaimId: string, reservations: readonly Pick<LedgerReservationRow, 'address'>[]): Promise<PgOutcomeResolutionAppendResult>;
2692
+ /**
2693
+ * Standalone PostgreSQL catalogue read-back. This intentionally does not
2694
+ * issue LOCK TABLE: callers may supply a Pool, and protocol atomicity belongs
2695
+ * to the transaction-bound recovery and observed-resolution paths.
2696
+ */
2697
+ declare function readPgOutcomeRecoveryReadBack(executor: TransitionJournalQueryable, address: LedgerAddress, readBack: PgOutcomeReadBackFactory, operationReadBack?: PgOutcomeOperationReadBackFactory, lockTimeoutMs?: number): Promise<OutcomeRecoveryReadBack>;
2698
+ /** Opens a claim on one connection when supplied a PostgreSQL pool. */
2699
+ declare function openPgOutcomeClaim(executor: TransitionJournalQueryable, request: PgOutcomeClaimRequest, run?: PgLockedRun): Promise<OutcomeClaimAdmission>;
2700
+ /**
2701
+ * Opens a root and all closure claims under globally ordered ledger locks in
2702
+ * one transaction. No child is ever durable before its root group commits.
2703
+ */
2704
+ declare function openPgOutcomeClaimGroup(executor: TransitionJournalQueryable, request: PgOutcomeClaimGroupRequest, run?: PgLockedRun): Promise<PgOutcomeClaimGroupAdmission>;
2705
+ /** Resolves every member terminal atomically under the same ordered locks. */
2706
+ declare function resolvePgOutcomeClaimGroup(executor: TransitionJournalQueryable, request: PgOutcomeClaimGroupResolution): Promise<undefined | OutcomeProtocolRefusal>;
2707
+ /**
2708
+ * The public PostgreSQL admitted-execution boundary. It is intentionally not
2709
+ * used by legacy paths yet: later dispatches bind their persisted runs and
2710
+ * operation shapes here without changing this authority surface.
2711
+ */
2712
+ declare function executePgAdmittedOperation(session: TransitionJournalQueryable, input: {
2713
+ readonly run: PgLockedRun;
2714
+ readonly operation: PgAdmittedOperation;
2715
+ readonly approval: ScopedApprovalSet;
2716
+ /** Branded proof that the operation came from the normalized manifest. */
2717
+ readonly manifest?: ValidatedManagedStepManifest;
2718
+ /** Recomputed from the durable plan while the caller owns its run lock. */
2719
+ readonly recomputedPlanDigest?: string;
2720
+ }): Promise<PgAdmittedOperationResult>;
2721
+ /**
2722
+ * Reads an address's chain and live catalogue in one locked transaction before
2723
+ * appending the core classifier's instruction. It never calls the DDL sink.
2724
+ */
2725
+ declare function recoverPgOutcomeClaim(executor: TransitionJournalQueryable, request: PgOutcomeRecoveryRequest): Promise<PgOutcomeRecoveryResult>;
2726
+
2727
+ export { type PgAdvisoryLockResult as $, type AddedEnumValue as A, GeneratedPostconditionReplanRequiredError as B, type ChangeKind as C, DEFAULT_PK_COLUMN as D, ExpressionCanonicalizationUnavailableError as E, type FkColumnDerivation as F, type GeneratedPostconditionSession as G, GeneratedPostconditionSessionDeactivatedError as H, GeneratedPostconditionWorkInFlightError as I, IdentityNamingPlugin as J, type IndexCapabilityContext as K, IndexFeatureUnsupportedError as L, IndexPredicateCanonicalizationError as M, type NamingPlugin as N, type IndexRenderSpec as O, type PgLockedRun as P, type IntrospectedModelIR as Q, type IntrospectionOptions as R, type MigrationSQLOptions as S, type TransitionJournalQueryable as T, NonConvergentSchemaDiffError as U, type NonConvergentSchemaDiffSurface as V, PG_LEDGER_SHAPE_VERSION as W, PartialIndexPredicateNewEnumValueError as X, type PgAdmittedOperation as Y, type PgAdmittedOperationResult as Z, type PgAdvisoryLockKey as _, type PgOutcomeCheckpointObserver as a, assertCreateIndexesSupported as a$, type PgApplicationStepOwnedState as a0, type PgApplicationStepTx as a1, type PgCatalogueIdentityQueryable as a2, type PgConvergeApplicationStep as a3, type PgConvergeAssertStep as a4, type PgConvergeInitializationFailure as a5, type PgConvergeOnceStep as a6, type PgConvergePlannedStep as a7, type PgConvergeRefusal as a8, type PgConvergeRefusalChange as a9, type PgsqlAdapterOptions as aA, PgsqlAdvisoryLockOptionsError as aB, type PgsqlBorrowedClientAdapterOptions as aC, type PgsqlCompileOnlyAdapterOptions as aD, PgsqlPinnedConnectionAbortSignalError as aE, type PgsqlPoolAdapterOptions as aF, PgsqlPreparedStatementReplayError as aG, type PgsqlPreparedStatementsOptions as aH, PgsqlRawSqlTransactionControlError as aI, PgsqlTransactionAbortSignalError as aJ, PgsqlTransactionAbortedCommitError as aK, PgsqlTransactionAbortedError as aL, PgsqlTransactionOptionsError as aM, PgsqlTransactionTimeoutError as aN, RawIndexPredicateFallbackError as aO, type ReferencedKeyKind as aP, type ReferencedKeyRemovalConflict as aQ, ReferencedKeyRemovalError as aR, type RollbackOnlyPgsqlScope as aS, type SchemaChange as aT, type SchemaDiff as aU, type SchemaScopeOptions as aV, TransitionRunIdentityMismatchError as aW, acquirePgLedgerLocks as aX, appendIntentJournal as aY, appendTransitionAuthorization as aZ, assertCreateIndexSupported as a_, PgConvergeRefusalError as aa, type PgLedgerLockResult as ab, PgLedgerStorageUnsupportedError as ac, type PgLedgerTarget as ad, type PgOutcomeCheckpoint as ae, type PgOutcomeClaimRequest as af, type PgOutcomeExecutionRequest as ag, type PgOutcomeNonTransactionalRequest as ah, type PgOutcomeReadBackFactory as ai, type PgOutcomeRecoveryRequest as aj, type PgOutcomeRecoveryResult as ak, type PgOutcomeResolution as al, type PgOutcomeResolutionAppendResult as am, type PgOutcomeResult as an, type PgOutcomeTransactionalRequest as ao, type PgOwnedCheckState as ap, type PgPhysicalModelInput as aq, PgPhysicalModelInputError as ar, type PgPhysicalNameClaim as as, type PgPhysicalNameCollision as at, PgPhysicalNameCollisionError as au, type PgPhysicalNamespace as av, type PgReinitializePreflightOptions as aw, type PgReinitializePreflightPool as ax, type PgSchemaDiff as ay, PgsqlAdapter as az, type ConvergePgOptions as b, type ComparePgsqlDeclaredAdoptionSchemaInput as b$, assertDeclarableChangeKind as b0, assertGeneratedPostconditionSession as b1, assertNoRepeatedExpressionSurfaceDrift as b2, camelCaseNaming as b3, canGenerateCreateIndex as b4, canonicalizeCheckConstraints as b5, comparePgsqlDatabaseSchema as b6, compareSchemata as b7, createPgPhysicalModel as b8, createPgTransitionRunPersister as b9, recordPgLedgerIdentity as bA, renderCreateDbspMetaSchemaSql as bB, renderCreateIndex as bC, renderCreateLedgerEventTableSql as bD, renderCreateLedgerIdentityTableSql as bE, renderCreateLedgerImmutabilityFunctionSql as bF, renderCreateLedgerImmutabilityTriggerSql as bG, renderCreateLedgerMarkerTableSql as bH, renderCreateLedgerReservationTableSql as bI, renderCreateLedgerTerminalMemberIndexSql as bJ, renderCreateTransitionAuthorizationTableSql as bK, renderCreateTransitionJournalTableSql as bL, renderCreateTransitionRunPlanTableSql as bM, renderCreateTransitionRunTableSql as bN, runPgReinitializePreflight as bO, toGeneratedPostconditionBindingAddress as bP, validatePgLedgerRuntimeIntegrity as bQ, verifyGeneratedCheckPostcondition as bR, verifyGeneratedColumnPostcondition as bS, verifyGeneratedIdentityPostcondition as bT, verifyGeneratedIndexPostcondition as bU, verifyGeneratedTablePostcondition as bV, withGeneratedPostconditionSession as bW, type PgOrderedLedgerLocks as bX, type PgLedgerShapeAllowance as bY, type PgLedgerPhysicalShapeOutcome as bZ, type ComparePgsqlDatabaseSchemaOptions$1 as b_, createPgsqlAdapter as ba, createPgsqlCompileOnlyAdapter as bb, createPgsqlGeneratedManagedStep as bc, decodeGeneratedPostcondition as bd, decodeGeneratedPostconditionPayload as be, defaultFkDerivation as bf, ensureDbspMetaLedger as bg, ensurePgLedger as bh, ensurePgLedgerStorageVersion as bi, ensureTransitionJournal as bj, executePgAdmittedOperation as bk, generateCreateIndex as bl, generateDDL as bm, generateDownSQL as bn, generateMigrationSQL as bo, generatedPostconditionDigest as bp, generatedPostconditionForChange as bq, getNamingPluginForDbCasing as br, identityNaming as bs, introspect as bt, readPgCatalogueIdentity as bu, readPgLedgerMarker as bv, readPgLedgerReservationsForExecution as bw, readPgLedgerScopeCurrency as bx, readPgOutcomeRecoveryReadBack as by, readVerifiedPgLedgerReservationsForPair as bz, type PgPhysicalModel as c, type CompareSchemataOptions$1 as c0, type ConvergePgBaseOptions as c1, type ConvergePgCheckOptions as c2, type GenerateDDLOptions$1 as c3, type MigrationSQLOptions$1 as c4, PgCommitAcknowledgementAmbiguousError as c5, type PgsqlAdoptionComparisonExecutor as c6, appendPgLedgerClaim as c7, appendPgLedgerClaimGroup as c8, appendPgLedgerProgress as c9, resolvePgDestructiveOutcome as cA, resolvePgOutcomeClaimGroup as cB, appendPgLedgerRelease as ca, appendPgLedgerResolution as cb, appendPgLedgerResolutionGroup as cc, appendPgOutcomeResolution as cd, classifyPgLedgerPhysicalShape as ce, collectReferencedKeyRemovalConflicts as cf, comparePgsqlDatabaseSchema$1 as cg, comparePgsqlDeclaredAdoptionSchema as ch, compareSchemata$1 as ci, convergePg as cj, createPgLedgerShapeAllowance as ck, createPgsqlDeclaredAdoptionStep as cl, createPgsqlDeclaredSequenceAdoptionStep as cm, executePgDestructiveOutcome as cn, generateDDL$1 as co, generateDownSQL$1 as cp, generateMigrationSQL$1 as cq, lockPgJournalRun as cr, modelForDeclaredAdoption as cs, openPgOutcomeClaim as ct, openPgOutcomeClaimGroup as cu, pgsqlDeclaredAdoptionDeclaration as cv, pgsqlDeclaredSequenceAdoptionDeclaration as cw, readPgLedgerReservationsForPair as cx, recoverPgAdmittedReaddressPair as cy, recoverPgOutcomeClaim as cz, type PgConvergeResult as d, type PgConvergeCheckResult as e, type PgLedgerScopeCurrency as f, AutoIncrementTransitionUnsupportedError as g, CamelCaseNamingPlugin as h, type CanonicalizeCheckConstraintsOptions as i, CheckConstraintCanonicalizationError as j, type CheckConstraintCanonicalizationWarning as k, CheckConstraintNewEnumValueError as l, ColumnDefaultCanonicalizationError as m, type ColumnDefaultCanonicalizationWarning as n, type ComparePgsqlDatabaseSchemaOptions as o, type CompareSchemataOptions as p, type DetectedHierarchy as q, readTransitionJournal as r, type DiffSummary as s, type ExpressionCanonicalizationWarning as t, ExpressionKeyedIndexPredicateCanonicalizationUnsupportedError as u, type GenerateDDLOptions as v, type GeneratedPostcondition as w, type GeneratedPostconditionBindingAddress as x, GeneratedPostconditionBindingResolutionError as y, GeneratedPostconditionProofInFlightError as z };