latticesql 3.4.7 → 4.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.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,15 @@ import { Server } from 'node:http';
8
8
  interface EntityFileManifestInfo {
9
9
  /** SHA-256 hex digest of the rendered content. */
10
10
  hash: string;
11
+ /**
12
+ * SHA-256 of the source entity row at render time (all columns, key-sorted).
13
+ * Reverse-sync compares this against the row's CURRENT version before applying
14
+ * a file edit: a mismatch means the DB row changed since this render, so the
15
+ * edit is rejected as a conflict instead of silently overwriting it. Optional
16
+ * for back-compat — manifests written before this field fall back to applying
17
+ * (the prior behavior) until the next render re-captures it.
18
+ */
19
+ rowVersion?: string;
11
20
  }
12
21
  interface EntityContextManifestEntry {
13
22
  directoryRoot: string;
@@ -15,14 +24,10 @@ interface EntityContextManifestEntry {
15
24
  declaredFiles: string[];
16
25
  protectedFiles: string[];
17
26
  /**
18
- * Key = entity slug.
19
- *
20
- * **v2 format:** value is `Record<string, EntityFileManifestInfo>` (filename → info with hash).
21
- * **v1 format (legacy):** value is `string[]` (bare filename list, no hashes).
22
- *
23
- * Use {@link normalizeEntityFiles} to convert v1 entries.
27
+ * Key = entity slug. Value = `Record<string, EntityFileManifestInfo>`
28
+ * (filename → info with content hash). This is the only shape we WRITE.
24
29
  */
25
- entities: Record<string, Record<string, EntityFileManifestInfo> | string[]>;
30
+ entities: Record<string, Record<string, EntityFileManifestInfo>>;
26
31
  }
27
32
  /**
28
33
  * Monotonic cursor the rendered tree was produced FROM, recorded in the manifest
@@ -69,17 +74,16 @@ interface LatticeManifest {
69
74
  */
70
75
  cursor?: RenderCursor;
71
76
  }
72
- /** Type guard: is the entity files entry in v1 format (string[])? */
73
- declare function isV1EntityFiles(val: unknown): val is string[];
74
- /**
75
- * Convert a v1 entity files entry (string[]) to v2 format (Record with empty hashes).
76
- * Reverse-sync skips entries with empty hashes (no baseline to compare against).
77
- */
78
- declare function normalizeEntityFiles(val: Record<string, EntityFileManifestInfo> | string[]): Record<string, EntityFileManifestInfo>;
79
77
  /**
80
- * Get the filenames from an entity files entry (works for both v1 and v2).
78
+ * Get the filenames from an entity files entry.
79
+ *
80
+ * We only ever WRITE the v2 `Record<filename, info>` shape, but an OLD manifest
81
+ * already on disk may still carry a bare `string[]` entry (the pre-hash format).
82
+ * This accessor tolerates that legacy shape at the read boundary — a stale
83
+ * manifest is upgraded silently on the next render, never crashed over — and
84
+ * still returns the filenames so cleanup can detect orphaned files for it.
81
85
  */
82
- declare function entityFileNames(val: Record<string, EntityFileManifestInfo> | string[]): string[];
86
+ declare function entityFileNames(val: Record<string, EntityFileManifestInfo> | readonly string[]): string[];
83
87
  declare function manifestPath(outputDir: string): string;
84
88
  declare function readManifest(outputDir: string): LatticeManifest | null;
85
89
  declare function writeManifest(outputDir: string, manifest: LatticeManifest): void;
@@ -624,10 +628,33 @@ interface WritebackStateStore {
624
628
  }
625
629
  /**
626
630
  * In-memory state store (default). State is lost on process exit.
631
+ *
632
+ * The seen-set dedupe is UNBOUNDED by default — every key ever marked for a
633
+ * file is retained for the process lifetime, exactly as before. For a
634
+ * long-running daemon tailing an append-only log this grows without limit, so
635
+ * an optional `maxSeenPerFile` cap is available: when set, only the most recent
636
+ * N keys per file are retained (oldest evicted first, by insertion order).
637
+ *
638
+ * The cap is a MEMORY-SAFETY guard for bounded-lifetime processes, NOT a
639
+ * durability substitute: an evicted key has no record, so if that same key
640
+ * reappears in the file later it would be re-processed (re-persisted). For
641
+ * long-running daemons over append-only logs prefer the durable
642
+ * {@link SQLiteStateStore} — its `_lattice_writeback_seen` table is durable and
643
+ * disk-bounded, so dedupe survives restarts without an in-memory ceiling.
627
644
  */
628
645
  declare class InMemoryStateStore implements WritebackStateStore {
629
646
  private readonly _offsets;
630
647
  private readonly _seen;
648
+ private readonly _maxSeenPerFile;
649
+ /**
650
+ * @param opts.maxSeenPerFile Cap the per-file dedupe set to this many keys
651
+ * (oldest evicted first). Default `Infinity` — unbounded, preserving the
652
+ * original behavior exactly. Set a finite cap only when you understand the
653
+ * re-processing tradeoff documented on the class.
654
+ */
655
+ constructor(opts?: {
656
+ maxSeenPerFile?: number;
657
+ });
631
658
  getOffset(filePath: string): number;
632
659
  getSize(filePath: string): number;
633
660
  setOffset(filePath: string, offset: number, size: number): void;
@@ -1177,6 +1204,34 @@ interface WritebackDefinition {
1177
1204
  entries: unknown[];
1178
1205
  nextOffset: number;
1179
1206
  };
1207
+ /**
1208
+ * Opt into incremental file reads. Default (`undefined` / `false`): the
1209
+ * pipeline reads the WHOLE file every tick with `readFileSync` and calls
1210
+ * `parse(wholeFileContent, absoluteByteOffset)` — byte-for-byte the original
1211
+ * behavior. No change for existing consumers.
1212
+ *
1213
+ * When `true`: each tick the pipeline reads ONLY the bytes at/after the
1214
+ * stored byte offset (one `readSync` of `currentSize - offset` bytes) and
1215
+ * passes that slice as `content` with `fromOffset = 0`. The parser's returned
1216
+ * `nextOffset` is therefore RELATIVE to the slice; the pipeline adds the prior
1217
+ * byte offset back before storing, so the persisted offset is always absolute.
1218
+ * This avoids re-reading the whole file (and re-billing its egress) every tick
1219
+ * on an append-only log.
1220
+ *
1221
+ * HARD PRECONDITION: the parser MUST operate purely on the byte-slice it
1222
+ * receives — it may NOT rely on any bytes before the stored offset (no
1223
+ * back-references into earlier content, no whole-file state). If your parser
1224
+ * needs the full file (e.g. it re-parses a header on every tick), leave this
1225
+ * off.
1226
+ *
1227
+ * Multi-byte safety: the slice is decoded with an incremental UTF-8 decoder
1228
+ * (`StringDecoder`), so a multi-byte codepoint that straddles the slice's
1229
+ * trailing edge is not split into a replacement char — its trailing bytes are
1230
+ * simply not yet consumed and arrive on the next tick once the rest is written.
1231
+ *
1232
+ * @default undefined (false)
1233
+ */
1234
+ incrementalRead?: boolean;
1180
1235
  /** Persist a single parsed entry; called exactly once per unique dedupeKey */
1181
1236
  persist: (entry: unknown, filePath: string) => Promise<void>;
1182
1237
  /** Optional dedup key — if omitted, every entry is processed */
@@ -1491,6 +1546,22 @@ interface ReverseSyncError {
1491
1546
  /** Error description. */
1492
1547
  error: string;
1493
1548
  }
1549
+ /**
1550
+ * A reverse-sync update that was NOT applied because the database row changed
1551
+ * since the render that produced the file's baseline — applying the file edit
1552
+ * would have silently overwritten that concurrent change. Reported (never
1553
+ * applied) so a human can re-resolve; the DB row is left intact.
1554
+ */
1555
+ interface ReverseSyncConflict {
1556
+ /** Entity table the conflicting row belongs to. */
1557
+ table: string;
1558
+ /** Slug of the entity whose file changed. */
1559
+ slug: string;
1560
+ /** The changed file whose write was rejected. */
1561
+ filename: string;
1562
+ /** Why the write was rejected (e.g. the row changed since render). */
1563
+ reason: string;
1564
+ }
1494
1565
  /**
1495
1566
  * Result of the reverse-sync phase in {@link Lattice.reconcile}.
1496
1567
  */
@@ -1503,6 +1574,12 @@ interface ReverseSyncResult {
1503
1574
  updatesApplied: number;
1504
1575
  /** Errors encountered (file-level — other files still processed). */
1505
1576
  errors: ReverseSyncError[];
1577
+ /**
1578
+ * Changed files whose write was REJECTED because the DB row changed since the
1579
+ * render baseline (optimistic-concurrency conflict). Surfaced loudly, never
1580
+ * applied — applying would have clobbered a concurrent DB/cloud edit.
1581
+ */
1582
+ conflicts: ReverseSyncConflict[];
1506
1583
  }
1507
1584
  /**
1508
1585
  * A missing row detected during reconcile: rendered files exist on disk
@@ -1639,6 +1716,32 @@ interface StorageAdapter {
1639
1716
  * natively.
1640
1717
  */
1641
1718
  addColumn(table: string, column: string, typeSpec: string): void;
1719
+ /**
1720
+ * Optional cheap, complete change-probe for the watch-loop render gate.
1721
+ *
1722
+ * Returns a token that is GUARANTEED to differ whenever ANY data change has
1723
+ * been committed to the database since the previous call — by this connection
1724
+ * OR any other connection/process. A caller may safely skip a render only when
1725
+ * two consecutive tokens are strictly equal: equal tokens prove zero
1726
+ * intervening commits, so nothing a render reads could have changed.
1727
+ *
1728
+ * The completeness guarantee is the whole point — a token that misses a class
1729
+ * of writes would let the gate skip a render that was actually needed, leaving
1730
+ * the rendered context stale. An adapter that cannot expose such a complete,
1731
+ * cheap signal MUST leave this undefined; the gate then falls through to a
1732
+ * full render every tick (the default, never-stale behavior).
1733
+ *
1734
+ * Must be O(1) — no table scan. It runs on every watch tick.
1735
+ *
1736
+ * - SQLite: `PRAGMA data_version` (catches other-connection commits) combined
1737
+ * with `total_changes()` (catches this connection's own row mutations) — the
1738
+ * pair is complete because between them they observe every committed row
1739
+ * change regardless of which connection made it. See the SQLite adapter.
1740
+ * - Postgres: there is no equally-cheap GLOBAL complete counter, so the
1741
+ * Postgres adapter does NOT implement this — Postgres watch renders run every
1742
+ * tick, unchanged.
1743
+ */
1744
+ changeProbe?(): string | undefined;
1642
1745
  /** Async equivalent of run(). Returns when the statement has completed. */
1643
1746
  runAsync?(sql: string, params?: unknown[]): Promise<void>;
1644
1747
  /** Async equivalent of get(). */
@@ -1647,6 +1750,16 @@ interface StorageAdapter {
1647
1750
  allAsync?(sql: string, params?: unknown[]): Promise<Row[]>;
1648
1751
  /** Async equivalent of introspectColumns(). Used by the boot-path schema apply. */
1649
1752
  introspectColumnsAsync?(table: string): Promise<string[]>;
1753
+ /**
1754
+ * Introspect columns for MANY tables in one shot (one query on Postgres).
1755
+ *
1756
+ * Collapses the per-table `information_schema` round-trips the boot path
1757
+ * would otherwise issue into a single whole-schema query. Implementations
1758
+ * MUST throw on query failure rather than return a partial/empty map — a
1759
+ * degraded read that silently yields an empty map would make the caller
1760
+ * believe every table is missing.
1761
+ */
1762
+ introspectAllColumns?(tables: string[]): Promise<Map<string, Set<string>>>;
1650
1763
  /** Async equivalent of addColumn(). Used by the boot-path schema apply. */
1651
1764
  addColumnAsync?(table: string, column: string, typeSpec: string): Promise<void>;
1652
1765
  /**
@@ -1725,6 +1838,14 @@ interface TxClient {
1725
1838
  all(sql: string, params?: unknown[]): Promise<Row[]>;
1726
1839
  }
1727
1840
 
1841
+ /** Optional bounds for a list read. Omitting both is the default (no cap). */
1842
+ interface PageOptions {
1843
+ /** Max rows to return. Must be a non-negative integer. */
1844
+ limit?: number;
1845
+ /** Rows to skip (only honored alongside `limit` — SQL OFFSET requires LIMIT). */
1846
+ offset?: number;
1847
+ }
1848
+
1728
1849
  /**
1729
1850
  * Options for {@link ReverseSyncEngine.process}.
1730
1851
  *
@@ -1920,6 +2041,18 @@ declare class ProgressThrottle {
1920
2041
  force(event: RenderProgress): void;
1921
2042
  }
1922
2043
 
2044
+ /**
2045
+ * Thrown by Lattice.seed when onUnresolvedLink: 'throw' is set and one or more
2046
+ * junction links could not be created because their target rows did not
2047
+ * resolve. (Moved here from lattice.ts; re-exported from lattice.ts to
2048
+ * preserve the public export name.)
2049
+ */
2050
+ declare class SeedReconciliationError extends Error {
2051
+ readonly table: string;
2052
+ readonly unresolvedLinks: UnresolvedLink[];
2053
+ constructor(table: string, unresolvedLinks: UnresolvedLink[]);
2054
+ }
2055
+
1923
2056
  /**
1924
2057
  * Initialise Lattice from a YAML config file instead of an explicit path.
1925
2058
  *
@@ -1945,7 +2078,10 @@ type PkLookup = string | Record<string, unknown>;
1945
2078
  declare class Lattice {
1946
2079
  private readonly _adapter;
1947
2080
  private _changelogService?;
2081
+ private _changelogWriterInstance?;
1948
2082
  private _reportBuilder?;
2083
+ private _queryCoreInstance?;
2084
+ private _seedEngine?;
1949
2085
  private readonly _schema;
1950
2086
  private readonly _sanitizer;
1951
2087
  private readonly _render;
@@ -1955,34 +2091,19 @@ declare class Lattice {
1955
2091
  private readonly _writeback;
1956
2092
  private _initialized;
1957
2093
  /**
1958
- * When set, insert/update/delete debounce-trigger a re-render into this dir.
1959
- * Configured by {@link enableAutoRender} / {@link Lattice.openWorkspace}.
1960
- * Undefined = inert: a bare `new Lattice(dbPath)` pays zero overhead and its
1961
- * behavior is unchanged.
1962
- */
1963
- private _autoRenderDir;
1964
- private _autoRenderTimer;
1965
- private _autoRenderPending;
1966
- private _autoRenderInFlight;
1967
- private _autoRenderDebounceMs;
1968
- /**
1969
- * Incremental auto-render scope, accumulated between debounced renders. A write
1970
- * or a remote (cloud) change records the AFFECTED table here, so the next
1971
- * auto-render re-renders only that entity (+ its cross-table dependents) instead
1972
- * of the whole tree. `_pendingRenderAll` forces a full render (the initial
1973
- * render, or a change with no known table). Captured + reset when a render
1974
- * starts, so changes during a render re-accumulate and re-trigger.
1975
- */
1976
- private _pendingRenderTables;
1977
- private _pendingRenderAll;
2094
+ * The debounce + single-flight auto-render scheduler (see
2095
+ * {@link AutoRenderScheduler}). Lazily constructed by the {@link _autoRender}
2096
+ * getter and configured by {@link enableAutoRender} / {@link Lattice.openWorkspace}.
2097
+ * Undefined = inert: a bare `new Lattice(dbPath)` never constructs the
2098
+ * scheduler and pays zero overhead, so its behavior is unchanged.
2099
+ */
2100
+ private _autoRenderScheduler?;
1978
2101
  /** Cache of actual table columns (from PRAGMA), populated after init(). */
1979
2102
  private readonly _columnCache;
1980
- /** Derived encryption key (from options.encryptionKey via scrypt). */
1981
- private _encryptionKey?;
1982
- /** Map of table → set of column names that should be encrypted at rest. */
1983
- private readonly _encryptedTableColumns;
1984
2103
  /** Raw encryption key passphrase from constructor options. */
1985
2104
  private readonly _encryptionKeyRaw?;
2105
+ /** Lazily-constructed column-encryption layer (see {@link _encryption}). */
2106
+ private _encryptionLayer?;
1986
2107
  /** Changelog retention options. */
1987
2108
  private readonly _changelogOptions?;
1988
2109
  /** Set of table names that have changelog: true. */
@@ -2189,33 +2310,11 @@ declare class Lattice {
2189
2310
  /** Return the current task context string. */
2190
2311
  getTaskContext(): string;
2191
2312
  /**
2192
- * Throw-only validation of encryption-key configuration. Runs in the
2193
- * synchronous prefix of `init()` so `expect(() => db.init()).toThrow(...)`
2194
- * still observes the throw moving this check into the async tail would
2195
- * convert the throw into a rejected Promise and break those tests.
2196
- * Column resolution happens later in {@link _finalizeEncryptionSetup} once
2197
- * the schema has been applied.
2198
- */
2199
- private _validateEncryptionConfig;
2200
- /**
2201
- * Resolve which columns to encrypt per table, using introspectColumns to
2202
- * see the post-migration schema. Runs in the async tail of init() after
2203
- * applySchema/applyMigrationsAsync.
2204
- */
2205
- private _finalizeEncryptionSetup;
2206
- /**
2207
- * Shared helper: derive the encryption key on first use, introspect the
2208
- * table's current columns, resolve which to encrypt, and record the set
2209
- * in `_encryptedTableColumns`. Called from both `_finalizeEncryptionSetup`
2210
- * (boot path) and `defineLate` (post-init table registration).
2313
+ * Lazily-constructed column-encryption layer. Field-backed `??= new` getter
2314
+ * mirrors `_report`/`_changelog`; the layer defers its scrypt key derivation
2315
+ * to the first column registration, so merely touching this getter is cheap.
2211
2316
  */
2212
- private _registerEncryptedColumns;
2213
- /** Encrypt applicable columns in a row before writing. Returns a new row. */
2214
- private _encryptRow;
2215
- /** Decrypt applicable columns in a row after reading. Mutates in place. */
2216
- private _decryptRow;
2217
- /** Decrypt applicable columns in multiple rows. Mutates in place. */
2218
- private _decryptRows;
2317
+ private get _encryption();
2219
2318
  /**
2220
2319
  * Defense-in-depth: validate a table (and any dynamic column) identifier
2221
2320
  * before it is interpolated into a SQL string. The library's threat model is
@@ -2329,7 +2428,7 @@ declare class Lattice {
2329
2428
  * Get all non-deleted rows from a table, ordered by the given column.
2330
2429
  * Works on any table, not just defined ones.
2331
2430
  */
2332
- getActive(table: string, orderBy?: string): Promise<Row[]>;
2431
+ getActive(table: string, orderBy?: string, opts?: PageOptions): Promise<Row[]>;
2333
2432
  /**
2334
2433
  * Count non-deleted rows in a table.
2335
2434
  */
@@ -2353,6 +2452,8 @@ declare class Lattice {
2353
2452
  * and optionally soft-deletes records no longer in the data set.
2354
2453
  */
2355
2454
  seed(config: SeedConfig): Promise<SeedResult>;
2455
+ /** Lazily-constructed seeding collaborator (see src/crud/seed-engine.ts). */
2456
+ private get _seed();
2356
2457
  /** Infer FK column name from table name (e.g., 'rule' → 'rule_id'). */
2357
2458
  private _inferFk;
2358
2459
  /**
@@ -2362,6 +2463,12 @@ declare class Lattice {
2362
2463
  buildReport(config: ReportConfig): Promise<ReportResult>;
2363
2464
  /** Lazily-constructed report-generation collaborator (see src/report/builder.ts). */
2364
2465
  private get _report();
2466
+ /** Lazily-constructed generic-read collaborator (see src/query/core.ts). The
2467
+ * decrypt deps are wired through `_encryption`, so the query/get decryption
2468
+ * asymmetry is preserved: only query/get invoke them. */
2469
+ private get _queryCore();
2470
+ /** Lazily-constructed auto-render scheduler (see src/render/auto-render.ts). */
2471
+ private get _autoRender();
2365
2472
  /**
2366
2473
  * Update reward scores for a row. The total reward is recalculated as
2367
2474
  * the running average across all reward calls. Requires `rewardTracking`
@@ -2385,12 +2492,12 @@ declare class Lattice {
2385
2492
  * Render into `outputDir` through the shared single-flight guard, intended to
2386
2493
  * be called fire-and-forget (e.g. the GUI's instant-open background render).
2387
2494
  *
2388
- * The guard ({@link _renderGuarded}) holds {@link _autoRenderInFlight} for the
2389
- * render's duration, so a data mutation that lands while this render is in
2390
- * flight is deferred by {@link _runAutoRender} and coalesced — when this
2391
- * render settles, `finally` clears the flag and re-arms exactly one follow-up
2392
- * render via {@link _rearmAutoRenderIfPending}. Net invariant: at most one
2393
- * render to a given dir at a time.
2495
+ * The guard ({@link AutoRenderScheduler.runGuarded}) holds the scheduler's
2496
+ * in-flight flag for the render's duration, so a data mutation that lands while
2497
+ * this render is in flight is deferred by the debounced auto-render path and
2498
+ * coalesced — when this render settles, `finally` clears the flag and re-arms
2499
+ * exactly one follow-up render. Net invariant: at most one render to a given
2500
+ * dir at a time.
2394
2501
  *
2395
2502
  * Errors propagate to the caller (the GUI surfaces them, never silently swallowed); they are
2396
2503
  * not swallowed here.
@@ -2537,7 +2644,6 @@ declare class Lattice {
2537
2644
  * - `Record` → matches every PK column; all must be present in the object.
2538
2645
  */
2539
2646
  private _pkWhere;
2540
- private static readonly _PK_SEP;
2541
2647
  /**
2542
2648
  * The primary-key columns of `table` that PHYSICALLY exist, in declared
2543
2649
  * order. Empty when the table has no Lattice-addressable key — e.g. a table
@@ -2546,7 +2652,7 @@ declare class Lattice {
2546
2652
  * ACL is possible, so the row-perm SQL must not reference a pk column).
2547
2653
  */
2548
2654
  private _resolvedPkCols;
2549
- /** Canonical ACL / change-log `pk` string for a row. Matches {@link _pkSqlExpr}. */
2655
+ /** Canonical ACL / change-log `pk` string for a row. Matches `db/pk.ts` `pkSqlExpr`. */
2550
2656
  private _serializeRowPk;
2551
2657
  /**
2552
2658
  * Canonical `pk` string for a {@link PkLookup} used by update/delete, so a
@@ -2554,19 +2660,6 @@ declare class Lattice {
2554
2660
  * {@link _serializeRowPk} keyed it at insert time.
2555
2661
  */
2556
2662
  private _serializePkLookup;
2557
- /**
2558
- * SQL expression reconstructing {@link _serializeRowPk} from a row aliased
2559
- * `t`. Returns null when the table is unkeyable (no pk columns present) — the
2560
- * caller must then avoid referencing a pk column at all. Dialect-aware tab
2561
- * separator: SQLite `char(9)`, Postgres `chr(9)` (both = U+0009), matching
2562
- * {@link _PK_SEP}.
2563
- */
2564
- private _pkSqlExpr;
2565
- /**
2566
- * Convert Filter objects into SQL clause strings and bound params.
2567
- * An `in` filter with an empty array is silently ignored (produces no clause).
2568
- */
2569
- private _buildFilters;
2570
2663
  /** Returns a rejected Promise if not initialized; null if ready. */
2571
2664
  private _fireWriteHooks;
2572
2665
  /**
@@ -2581,24 +2674,6 @@ declare class Lattice {
2581
2674
  }): this;
2582
2675
  /** Turn off automatic rendering and cancel any pending render. */
2583
2676
  disableAutoRender(): this;
2584
- private _scheduleAutoRender;
2585
- /** Arm the debounce timer if not already armed. Does NOT change the render
2586
- * scope — used both by `_scheduleAutoRender` and the post-render re-arm so a
2587
- * re-arm never escalates a pending incremental render to a full one. */
2588
- private _armAutoRenderTimer;
2589
- /**
2590
- * Shared single-flight render path used by {@link renderInBackground}.
2591
- *
2592
- * Holds {@link _autoRenderInFlight} for the render's duration so the
2593
- * mutation-driven {@link _runAutoRender} defers while this render runs (it
2594
- * sees the flag and marks itself pending instead of starting a second,
2595
- * overlapping render). On settle, `finally` clears the flag and re-arms a
2596
- * single coalesced follow-up render if any mutation arrived mid-flight.
2597
- * Errors propagate to the caller; the flag is always cleared.
2598
- */
2599
- private _renderGuarded;
2600
- private _runAutoRender;
2601
- private _rearmAutoRenderIfPending;
2602
2677
  /**
2603
2678
  * Update or remove the embedding for a row.
2604
2679
  * No-op if the table doesn't have `embeddings` configured.
@@ -2638,6 +2713,8 @@ declare class Lattice {
2638
2713
  /** Parse a raw changelog DB row into a ChangeEntry. */
2639
2714
  /** Lazily-constructed changelog read/replay collaborator (see src/changelog/service.ts). */
2640
2715
  private get _changelog();
2716
+ /** Lazily-constructed changelog write/DDL collaborator (see src/changelog/writer.js). */
2717
+ private get _changelogWriter();
2641
2718
  /**
2642
2719
  * Get change history for a specific row, newest first.
2643
2720
  */
@@ -2689,18 +2766,6 @@ declare class Lattice {
2689
2766
  private _invalidColumnError;
2690
2767
  private _assertNotInit;
2691
2768
  }
2692
- /**
2693
- * Thrown by {@link Lattice.seed} when `onUnresolvedLink: 'throw'` is set and
2694
- * one or more junction links could not be created because their target rows
2695
- * did not resolve. Carries the full list so the caller can report or
2696
- * reconcile every missing target at once rather than discovering them one
2697
- * silent drop at a time.
2698
- */
2699
- declare class SeedReconciliationError extends Error {
2700
- readonly table: string;
2701
- readonly unresolvedLinks: UnresolvedLink[];
2702
- constructor(table: string, unresolvedLinks: UnresolvedLink[]);
2703
- }
2704
2769
 
2705
2770
  /**
2706
2771
  * Scalar types recognised in `lattice.config.yml` field definitions.
@@ -2728,7 +2793,7 @@ type LatticeFieldType = 'uuid' | 'text' | 'integer' | 'int' | 'real' | 'float' |
2728
2793
  * id: { type: uuid, primaryKey: true }
2729
2794
  * title: { type: text, required: true }
2730
2795
  * status: { type: text, default: open }
2731
- * assignee_id: { type: uuid, ref: user }
2796
+ * assignee_id: { type: uuid }
2732
2797
  * score: { type: integer, default: 0 }
2733
2798
  * ```
2734
2799
  */
@@ -2741,13 +2806,6 @@ interface LatticeFieldDef {
2741
2806
  required?: boolean;
2742
2807
  /** SQL DEFAULT value */
2743
2808
  default?: string | number | boolean;
2744
- /**
2745
- * Foreign-key reference to another entity (table name).
2746
- * Creates a `belongsTo` relation automatically.
2747
- * The relation name is derived from the field name — `_id` suffix is stripped
2748
- * (e.g. `assignee_id: { ref: user }` → relation name `assignee`).
2749
- */
2750
- ref?: string;
2751
2809
  /**
2752
2810
  * Per-column audience (Stage-0 scaffolding for the per-viewer enrichment
2753
2811
  * model). Names who may see this column's value in a cloud. Omitted ⇒
@@ -2757,6 +2815,15 @@ interface LatticeFieldDef {
2757
2815
  * cell-masking view from it; Stage-0 only records the metadata.
2758
2816
  */
2759
2817
  audience?: string;
2818
+ /**
2819
+ * DEPRECATED (3.x) per-field foreign-key shorthand: `ref: <targetTable>` declared
2820
+ * a `belongsTo` whose relation name is the field name with a trailing `_id`
2821
+ * stripped. Superseded by the explicit entity-level `relations:` block. 4.0 still
2822
+ * PARSES it (converted to a `belongsTo` in-memory) so existing 3.0+ configs keep
2823
+ * working, and the GUI silently rewrites it to `relations:` on open so configs
2824
+ * migrate forward. A future major may drop this once configs have upgraded.
2825
+ */
2826
+ ref?: string;
2760
2827
  }
2761
2828
  /**
2762
2829
  * Inline render spec inside YAML — a flat object alternative to `TemplateRenderSpec`.
@@ -2779,8 +2846,14 @@ interface LatticeEntityRenderSpec {
2779
2846
  * ```yaml
2780
2847
  * ticket:
2781
2848
  * fields:
2782
- * id: { type: uuid, primaryKey: true }
2783
- * title: { type: text, required: true }
2849
+ * id: { type: uuid, primaryKey: true }
2850
+ * title: { type: text, required: true }
2851
+ * assignee_id: { type: uuid }
2852
+ * relations:
2853
+ * assignee:
2854
+ * type: belongsTo
2855
+ * table: user
2856
+ * foreignKey: assignee_id
2784
2857
  * render: default-list
2785
2858
  * outputFile: context/TICKETS.md
2786
2859
  * ```
@@ -2788,6 +2861,27 @@ interface LatticeEntityRenderSpec {
2788
2861
  interface LatticeEntityDef {
2789
2862
  /** Column definitions */
2790
2863
  fields: Record<string, LatticeFieldDef>;
2864
+ /**
2865
+ * Explicit `belongsTo` relations for this entity, keyed by relation name.
2866
+ *
2867
+ * Each entry declares a foreign key on THIS entity pointing at another
2868
+ * table: `{ type: belongsTo, table, foreignKey, references? }`. The
2869
+ * `foreignKey` names a plain field on this entity; `references` is the
2870
+ * column on the related table (defaults to its primary key). The relation
2871
+ * name (the map key) is whatever you choose — it is not derived from the
2872
+ * field name.
2873
+ *
2874
+ * @example
2875
+ * ```yaml
2876
+ * relations:
2877
+ * assignee:
2878
+ * type: belongsTo
2879
+ * table: user
2880
+ * foreignKey: assignee_id
2881
+ * # references: id # optional; defaults to the target's primary key
2882
+ * ```
2883
+ */
2884
+ relations?: Record<string, BelongsToRelation>;
2791
2885
  /**
2792
2886
  * How to render rows into context text.
2793
2887
  * Accepts the same forms as `TableDefinition.render`:
@@ -3275,10 +3369,36 @@ declare class SQLiteAdapter implements StorageAdapter {
3275
3369
  * cannot add those via ALTER, and if the table exists it has its own PK.
3276
3370
  */
3277
3371
  addColumn(table: string, column: string, typeSpec: string): void;
3372
+ /**
3373
+ * Complete, O(1) change-probe for the watch-loop render gate (see
3374
+ * `StorageAdapter.changeProbe`). Composes the two SQLite counters that, taken
3375
+ * together, observe EVERY committed row change regardless of origin:
3376
+ *
3377
+ * - `PRAGMA data_version`: a counter SQLite bumps whenever ANOTHER
3378
+ * connection (or process) commits a change to the database. It is
3379
+ * intentionally NOT bumped by commits on this same connection — so on its
3380
+ * own it would miss our own writes.
3381
+ * - `total_changes()` (`sqlite3_total_changes`): the cumulative count of
3382
+ * rows inserted/updated/deleted on THIS connection since it was opened,
3383
+ * INCLUDING rows changed indirectly by triggers and ON DELETE CASCADE. It
3384
+ * covers exactly the gap `data_version` leaves — our own connection's
3385
+ * writes.
3386
+ *
3387
+ * Neither counter moves on a no-op statement (an UPDATE matching zero rows,
3388
+ * a bare SELECT), so an idle DB yields a stable token. The pair is therefore
3389
+ * complete: the composite token changes if and only if at least one row was
3390
+ * committed somewhere since the prior read. Both reads are single-value
3391
+ * pragma/function lookups — no table scan, safe to call every tick.
3392
+ *
3393
+ * (DDL alone is not a watch-loop concern — the schema is fixed before watch
3394
+ * starts — and any DATA a migration writes is counted by `total_changes()`.)
3395
+ */
3396
+ changeProbe(): string;
3278
3397
  runAsync(sql: string, params?: unknown[]): Promise<void>;
3279
3398
  getAsync(sql: string, params?: unknown[]): Promise<Row | undefined>;
3280
3399
  allAsync(sql: string, params?: unknown[]): Promise<Row[]>;
3281
3400
  introspectColumnsAsync(table: string): Promise<string[]>;
3401
+ introspectAllColumns(tables: string[]): Promise<Map<string, Set<string>>>;
3282
3402
  addColumnAsync(table: string, column: string, typeSpec: string): Promise<void>;
3283
3403
  /**
3284
3404
  * Run `fn` inside a BEGIN/COMMIT block on the single SQLite connection.
@@ -3382,6 +3502,19 @@ declare class PostgresAdapter implements StorageAdapter {
3382
3502
  */
3383
3503
  prepareAsync(sql: string): PreparedStatementAsync;
3384
3504
  introspectColumnsAsync(table: string): Promise<string[]>;
3505
+ /**
3506
+ * Whole-schema column introspection in a single query — the batched
3507
+ * equivalent of {@link introspectColumnsAsync}. The boot path uses this to
3508
+ * collapse one `information_schema` round-trip per declared table into one,
3509
+ * which on a high-RTT cloud is the difference between ~hundreds of serial
3510
+ * round-trips and a single query.
3511
+ *
3512
+ * `tables` is accepted for interface symmetry but ignored: querying the
3513
+ * whole `current_schema()` once is cheaper than constraining to a list, and
3514
+ * the caller folds out tables it doesn't care about. Throws on query failure
3515
+ * — a degraded read must never masquerade as "every table is missing".
3516
+ */
3517
+ introspectAllColumns(_tables: string[]): Promise<Map<string, Set<string>>>;
3385
3518
  addColumnAsync(table: string, column: string, typeSpec: string): Promise<void>;
3386
3519
  /**
3387
3520
  * Run `fn` against a single checked-out pool client wrapped in BEGIN/COMMIT.
@@ -3426,10 +3559,10 @@ declare class PostgresAdapter implements StorageAdapter {
3426
3559
  * file repository) that should not require every consumer to re-derive
3427
3560
  * the column shape from scratch.
3428
3561
  *
3429
- * Columns are deliberately a *superset* of any earlier ad-hoc shapes
3430
- * (e.g. older fixtures defined `files` with `path` + `kind` only). New
3431
- * code should prefer the content-addressed columns (`sha256`, `blob_path`)
3432
- * for files; legacy columns remain for backwards-compatibility.
3562
+ * Columns are deliberately a *superset* of any earlier ad-hoc shapes. New
3563
+ * code uses the content-addressed columns (`sha256`, `blob_path`) for owned
3564
+ * bytes and the reference model (`ref_kind` / `ref_uri`) for files that live
3565
+ * elsewhere.
3433
3566
  *
3434
3567
  * `secrets.value` is encrypted at rest. Registering native entities on a
3435
3568
  * Lattice without an `encryptionKey` configured will throw at init time
@@ -3969,7 +4102,6 @@ interface FilesRow {
3969
4102
  ref_uri?: string | null;
3970
4103
  ref_provider?: string | null;
3971
4104
  blob_path?: string | null;
3972
- path?: string | null;
3973
4105
  original_name?: string | null;
3974
4106
  mime?: string | null;
3975
4107
  size_bytes?: number | null;
@@ -4143,6 +4275,18 @@ interface MigrationProgress {
4143
4275
  interface MigrationResult {
4144
4276
  tablesCopied: string[];
4145
4277
  rowsCopied: number;
4278
+ /**
4279
+ * Count of copied `files` rows whose canonical bytes are OWNED-LOCAL
4280
+ * (under `<source-root>/data/blobs/` or a machine-local absolute path)
4281
+ * and were therefore NOT migrated — only the row (the pointer) was
4282
+ * copied. After the source SQLite is archived those bytes are
4283
+ * unreachable from the active cloud config, so the cloud `files` rows
4284
+ * are dangling references. Present (and > 0) only when such rows exist;
4285
+ * the caller surfaces it as an operator warning. Migrating the bytes
4286
+ * themselves (S3 upload) is a deferred follow-up. Omitted (undefined)
4287
+ * when every file is already cloud_ref or there are no files.
4288
+ */
4289
+ blobsNotMigrated?: number;
4146
4290
  }
4147
4291
  interface MigrationOptions {
4148
4292
  /** Rows copied per upsert batch. Default 500. */
@@ -4168,6 +4312,15 @@ interface MigrationOptions {
4168
4312
  * differ, encrypted values land on the target as plaintext-of-the-
4169
4313
  * source-ciphertext (i.e. unreadable). Callers are expected to thread
4170
4314
  * the same key through to both sides.
4315
+ *
4316
+ * After each table copy, re-counts the target with the same unfiltered
4317
+ * (soft-delete-consistent) semantic as the source read and throws on
4318
+ * mismatch — defensive insurance against a future write path that
4319
+ * swallows partial failures (the throw lands before the caller archives
4320
+ * the source, so a mismatch leaves the operator on the original local
4321
+ * DB). Reports `blobsNotMigrated` counting copied `files` rows whose
4322
+ * owned-local bytes were not migrated; the bytes themselves are NOT
4323
+ * uploaded — that is a deferred follow-up.
4171
4324
  */
4172
4325
  declare function migrateLatticeData(source: Lattice, target: Lattice, options?: MigrationOptions): Promise<MigrationResult>;
4173
4326
  /**
@@ -4276,7 +4429,14 @@ declare function isPostgresUrl(url: string): boolean;
4276
4429
  * filters rows per individual login role (`session_user`). The group grants
4277
4430
  * *access*, never *visibility*.
4278
4431
  */
4279
- declare const MEMBER_GROUP = "lattice_members";
4432
+ /**
4433
+ * The role name a PRE-per-cloud-group cloud used for its member group. Postgres
4434
+ * roles are cluster-global, so this single name was SHARED by every cloud on one
4435
+ * Postgres cluster. Retained only so a legacy cloud can be recognized + migrated
4436
+ * (see docs/MIGRATING-4.0.md) — never used to grant access on the live paths.
4437
+ */
4438
+ declare const LEGACY_MEMBER_GROUP = "lattice_members";
4439
+ declare function memberGroupFor(db: Lattice): Promise<string>;
4280
4440
  /** Install the cloud RLS bootstrap (bookkeeping + helper functions). No-op on SQLite. */
4281
4441
  declare function installCloudRls(db: Lattice): Promise<void>;
4282
4442
  /**
@@ -4429,7 +4589,7 @@ declare function tableNeedsAudienceView(columnAudience: Record<string, string>):
4429
4589
  * Idempotent. `columns` is the table's full column list (stable order); `pkCols`
4430
4590
  * its primary key, so the row filter matches the RLS policy's pk serialization.
4431
4591
  */
4432
- declare function audienceViewSql(table: string, columns: readonly string[], pkCols: readonly string[], columnAudience: Record<string, string>): string;
4592
+ declare function audienceViewSql(table: string, columns: readonly string[], pkCols: readonly string[], columnAudience: Record<string, string>, group: string): string;
4433
4593
  /**
4434
4594
  * Generate + install a table's cell-masking view (Postgres only; no-op on SQLite
4435
4595
  * and on a table with no audience columns). Versioned by a content hash of the
@@ -5090,4 +5250,4 @@ declare class FileSourceKeyStore implements SourceKeyStore {
5090
5250
  private encodeFile;
5091
5251
  }
5092
5252
 
5093
- export { type AddWorkspaceOptions, type AdoptNativeOptions, type AdoptResult, type ApplyWriteResult, type AudienceRowCtx, type AuditEvent, type AutoUpdateResult, type BelongsToRelation, type BelongsToSource, type BlobMetadata, type BuiltinTemplateName, CLOUD_SETTING_SYSTEM_PROMPT, CLOUD_SETTING_WORKSPACE_LOGO, CLOUD_SETTING_WORKSPACE_LOGO_ETAG, CONFIG_SUBDIR, type CatalogEntity, type CatalogRecord, type ChangeEntry, type ChangelogOptions, type ClassifyMatch, type CleanupOptions, type CleanupResult, type CloudProbeResult, type CountOptions, type CrawlOptions, type CrawlResult, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type DiscoveredTable, type EmbeddingsConfig, type EnrichOptions, type EnrichResult, type EnrichedSource, type EnrichmentLookup, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type ExtractedObject, FileSourceKeyStore, type FileSourceKeyStoreOptions, type FilesRow, type Filter, type FilterOp, FoldCache, type FtsConfig, type FtsGroup, type FtsHit, type FtsOptions, type FtsResult, type GuiServerHandle, type HasManyRelation, type HasManySource, InMemorySourceKeyStore, InMemoryStateStore, type InitOptions, LOCAL_DB_RELPATH, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type LlmClient, type LlmMessage, MEMBER_GROUP, type ManyToManySource, type MarkdownTableColumn, type MigrateResult, type Migration, type MigrationOptions, type MigrationProgress, type MigrationResult, type MultiTableDefinition, NATIVE_ENTITY_DEFS, NATIVE_ENTITY_NAMES, NATIVE_REGISTRY_TABLE, type Observation, type OrderBySpec, type OrganizeOptions, type OrganizeResult, type OrganizedCreation, type OrganizedLink, type ParseError, type ParseResult, type ParsedConfig, type PdfOptions, type PdfSenderInput, type PkLookup, PostgresAdapter, type PostgresAdapterOptions, type PreparedStatement, type PrimaryKey, ProgressThrottle, type QueryOptions, READ_ONLY_HEADER, ROOT_DIRNAME, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type RefKind, type RefProvider, type ReferenceMetadata, ReferenceUnavailableError, type Relation, type RemoteBlobStore, type RenderHooks, type RenderOptions, type RenderProgress, type RenderProgressCallback, type RenderProgressKind, type RenderResult, type RenderSpec, type ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ResolveOptions, type ReverseSeedDetection, type ReverseSeedResult, type ReverseSeedTableResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type RewardScores, type Row, type RowVisibilityDefault, type S3Config, type S3StoreConfig, S3UnavailableError, SQLiteAdapter, type SchemaEntity, type SearchOptions, type SearchResult, type SecurityOptions, type SeedConfig, type SeedLinkSpec, SeedReconciliationError, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceHandle, type SourceKeyStore, type SourceMetadata, type SourceQueryOptions, SourceShreddedError, type StartGuiServerOptions, type StopFn, type StorageAdapter, type SyncResult, type TableDefinition, type TablePolicy, type TemplateRenderSpec, type TurnParams, type TurnResult, type UnresolvedLink, type UpsertByNaturalKeyOptions, type UserIdentity, type UserPreferences, type Viewer, type VisionOptions, type VisionSenderInput, WORKSPACES_SUBDIR, type WatchOptions, type WorkspacePaths, type WorkspaceRecord, type WorkspaceRegistry, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, type WritebackValidationResult, activeWorkspaceLabel, addWorkspace, adoptNativeEntities, analyticsEnabled, applyTokenBudget, applyWriteEntry, archiveLocalSqlite, assertSafeUrl, attachBlob, audiencePredicate, audienceViewSql, autoFtsColumns, autoUpdate, backfillOwnership, canManageRoles, classifyLinks, cloudRlsInstalled, configDir, contentHash, crawlUrl, createReadOnlyHeader, createS3Store, createSQLiteStateStore, decrypt, defaultWorkspaceYaml, deleteDbCredential, deleteToken, deriveCanonicalContexts, deriveKey, describeImage, describePdf, discoverCloudTables, enableAudienceView, enableChangelogRls, enableRlsForTable, encrypt, enrichKnowledge, ensureFtsIndex, ensureLatticeRoot, entityFileNames, estimateTokens, extractObjects, findLatticeRoot, fixSchemaConflicts, foldEntity, frontmatter, ftsTableName, fullTextSearch, generateEntryId, generateMemberPassword, generateWriteEntryId, getActiveWorkspace, getCloudSetting, getDbCredential, getOrCreateMasterKey, getTablePolicy, getWorkspace, hasFtsIndex, hashFile, importLegacyUserConfig, installCloudRls, installCloudSettings, isEncrypted, isNativeEntity, isPostgresUrl, isPrivateIp, isRowAudience, isV1EntityFiles, listDbCredentials, listNativeBindings, listTokens, listWorkspaces, loadColumnPolicy, manifestPath, markdownTable, memberRoleName, migrateLatticeData, normalizeEntityFiles, observationVisible, observationsFromChange, openTargetLatticeForMigration, openUnderSource, organizeSource, parseConfigFile, parseConfigString, parseMarkdownEntries, parseMatches, parseObjects, parseSessionMD, parseSessionWrites, probeCloud, providerForUrl, provisionMemberRole, readIdentity, readManifest, readPreferences, readRegistry, readToken, referenceLocalFile, referenceUrl, regenerateAudienceViewFromDb, registerNativeEntities, registryPath, resolveActiveS3Config, resolveLatticeRoot, resolveSource, resolveWorkspacePaths, revokeMemberRole, rootConfigDir, s3Key, saveDbCredential, saveDbCredentialForTeam, sealUnderSource, secureCloud, seedColumnPolicyFromYaml, setActiveWorkspace, setCloudSetting, setColumnAudience, setRowVisibility, setTableDefaultVisibility, setTableNeverShare, shredSource, slugify, startGuiServer, summarizeText, tableNeedsAudienceView, toSafeDirName, truncate, validateEntryId, workspaceBlobsDir, workspaceConfigPath, workspaceContextDir, workspaceDataDir, workspaceDbPath, workspaceDir, workspacesDir, writeIdentity, writeManifest, writePreferences, writeRegistry, writeToken };
5253
+ export { type AddWorkspaceOptions, type AdoptNativeOptions, type AdoptResult, type ApplyWriteResult, type AudienceRowCtx, type AuditEvent, type AutoUpdateResult, type BelongsToRelation, type BelongsToSource, type BlobMetadata, type BuiltinTemplateName, CLOUD_SETTING_SYSTEM_PROMPT, CLOUD_SETTING_WORKSPACE_LOGO, CLOUD_SETTING_WORKSPACE_LOGO_ETAG, CONFIG_SUBDIR, type CatalogEntity, type CatalogRecord, type ChangeEntry, type ChangelogOptions, type ClassifyMatch, type CleanupOptions, type CleanupResult, type CloudProbeResult, type CountOptions, type CrawlOptions, type CrawlResult, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type DiscoveredTable, type EmbeddingsConfig, type EnrichOptions, type EnrichResult, type EnrichedSource, type EnrichmentLookup, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type ExtractedObject, FileSourceKeyStore, type FileSourceKeyStoreOptions, type FilesRow, type Filter, type FilterOp, FoldCache, type FtsConfig, type FtsGroup, type FtsHit, type FtsOptions, type FtsResult, type GuiServerHandle, type HasManyRelation, type HasManySource, InMemorySourceKeyStore, InMemoryStateStore, type InitOptions, LEGACY_MEMBER_GROUP, LOCAL_DB_RELPATH, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type LlmClient, type LlmMessage, type ManyToManySource, type MarkdownTableColumn, type MigrateResult, type Migration, type MigrationOptions, type MigrationProgress, type MigrationResult, type MultiTableDefinition, NATIVE_ENTITY_DEFS, NATIVE_ENTITY_NAMES, NATIVE_REGISTRY_TABLE, type Observation, type OrderBySpec, type OrganizeOptions, type OrganizeResult, type OrganizedCreation, type OrganizedLink, type ParseError, type ParseResult, type ParsedConfig, type PdfOptions, type PdfSenderInput, type PkLookup, PostgresAdapter, type PostgresAdapterOptions, type PreparedStatement, type PrimaryKey, ProgressThrottle, type QueryOptions, READ_ONLY_HEADER, ROOT_DIRNAME, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type RefKind, type RefProvider, type ReferenceMetadata, ReferenceUnavailableError, type Relation, type RemoteBlobStore, type RenderHooks, type RenderOptions, type RenderProgress, type RenderProgressCallback, type RenderProgressKind, type RenderResult, type RenderSpec, type ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ResolveOptions, type ReverseSeedDetection, type ReverseSeedResult, type ReverseSeedTableResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type RewardScores, type Row, type RowVisibilityDefault, type S3Config, type S3StoreConfig, S3UnavailableError, SQLiteAdapter, type SchemaEntity, type SearchOptions, type SearchResult, type SecurityOptions, type SeedConfig, type SeedLinkSpec, SeedReconciliationError, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceHandle, type SourceKeyStore, type SourceMetadata, type SourceQueryOptions, SourceShreddedError, type StartGuiServerOptions, type StopFn, type StorageAdapter, type SyncResult, type TableDefinition, type TablePolicy, type TemplateRenderSpec, type TurnParams, type TurnResult, type UnresolvedLink, type UpsertByNaturalKeyOptions, type UserIdentity, type UserPreferences, type Viewer, type VisionOptions, type VisionSenderInput, WORKSPACES_SUBDIR, type WatchOptions, type WorkspacePaths, type WorkspaceRecord, type WorkspaceRegistry, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, type WritebackValidationResult, activeWorkspaceLabel, addWorkspace, adoptNativeEntities, analyticsEnabled, applyTokenBudget, applyWriteEntry, archiveLocalSqlite, assertSafeUrl, attachBlob, audiencePredicate, audienceViewSql, autoFtsColumns, autoUpdate, backfillOwnership, canManageRoles, classifyLinks, cloudRlsInstalled, configDir, contentHash, crawlUrl, createReadOnlyHeader, createS3Store, createSQLiteStateStore, decrypt, defaultWorkspaceYaml, deleteDbCredential, deleteToken, deriveCanonicalContexts, deriveKey, describeImage, describePdf, discoverCloudTables, enableAudienceView, enableChangelogRls, enableRlsForTable, encrypt, enrichKnowledge, ensureFtsIndex, ensureLatticeRoot, entityFileNames, estimateTokens, extractObjects, findLatticeRoot, fixSchemaConflicts, foldEntity, frontmatter, ftsTableName, fullTextSearch, generateEntryId, generateMemberPassword, generateWriteEntryId, getActiveWorkspace, getCloudSetting, getDbCredential, getOrCreateMasterKey, getTablePolicy, getWorkspace, hasFtsIndex, hashFile, importLegacyUserConfig, installCloudRls, installCloudSettings, isEncrypted, isNativeEntity, isPostgresUrl, isPrivateIp, isRowAudience, listDbCredentials, listNativeBindings, listTokens, listWorkspaces, loadColumnPolicy, manifestPath, markdownTable, memberGroupFor, memberRoleName, migrateLatticeData, observationVisible, observationsFromChange, openTargetLatticeForMigration, openUnderSource, organizeSource, parseConfigFile, parseConfigString, parseMarkdownEntries, parseMatches, parseObjects, parseSessionMD, parseSessionWrites, probeCloud, providerForUrl, provisionMemberRole, readIdentity, readManifest, readPreferences, readRegistry, readToken, referenceLocalFile, referenceUrl, regenerateAudienceViewFromDb, registerNativeEntities, registryPath, resolveActiveS3Config, resolveLatticeRoot, resolveSource, resolveWorkspacePaths, revokeMemberRole, rootConfigDir, s3Key, saveDbCredential, saveDbCredentialForTeam, sealUnderSource, secureCloud, seedColumnPolicyFromYaml, setActiveWorkspace, setCloudSetting, setColumnAudience, setRowVisibility, setTableDefaultVisibility, setTableNeverShare, shredSource, slugify, startGuiServer, summarizeText, tableNeedsAudienceView, toSafeDirName, truncate, validateEntryId, workspaceBlobsDir, workspaceConfigPath, workspaceContextDir, workspaceDataDir, workspaceDbPath, workspaceDir, workspacesDir, writeIdentity, writeManifest, writePreferences, writeRegistry, writeToken };