@objectstack/objectql 7.3.0 → 7.4.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.mts CHANGED
@@ -4,7 +4,7 @@ import * as _objectstack_metadata_core from '@objectstack/metadata-core';
4
4
  import { MetadataRepository, MetaRef, MetadataItem, PutOptions, PutResult, DeleteOptions, DeleteResult, MetadataWriteIntent, ListFilter, MetadataItemHeader, HistoryOptions, MetadataEvent, WatchFilter } from '@objectstack/metadata-core';
5
5
  import { ObjectStackProtocol, MetadataCacheRequest, MetadataCacheResponse, BatchUpdateRequest, BatchUpdateResponse, UpdateManyDataRequest, DeleteManyDataRequest } from '@objectstack/spec/api';
6
6
  import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext, ObjectKernel } from '@objectstack/core';
7
- import { IFeedService, IRealtimeService } from '@objectstack/spec/contracts';
7
+ import { IFeedService, IRealtimeService, ICryptoProvider } from '@objectstack/spec/contracts';
8
8
 
9
9
  /**
10
10
  * Reserved namespaces that do not get FQN prefix applied.
@@ -138,6 +138,14 @@ declare class SchemaRegistry {
138
138
  private namespaceRegistry;
139
139
  /** Type → Name/ID → MetadataItem */
140
140
  private metadata;
141
+ /**
142
+ * App name → navigation contributions (ADR-0029 D7).
143
+ *
144
+ * Lets packages inject nav items into apps they do not own (the UI analog
145
+ * of object extenders). Merged into the owning app's `navigation` tree on
146
+ * read in {@link getApp} / {@link getAllApps} by group id + priority.
147
+ */
148
+ private appNavContributions;
141
149
  /**
142
150
  * Package ids that must be installed in a DISABLED state. Seeded once at
143
151
  * boot (from persisted state) BEFORE any package registration so that every
@@ -215,6 +223,25 @@ declare class SchemaRegistry {
215
223
  * Get the owner contributor for an object.
216
224
  */
217
225
  getObjectOwner(fqn: string): ObjectContributor | undefined;
226
+ /**
227
+ * ADR-0029 K0 — assert every registered object resolves to exactly one
228
+ * owner.
229
+ *
230
+ * A second `own` from a different package is already rejected eagerly in
231
+ * {@link registerObject} (it throws). This is the install-time backstop
232
+ * called once all packages are registered (kernel bootstrap complete),
233
+ * and it additionally catches the case `registerObject` cannot: an object
234
+ * that has only `extend` contributions and **no owner** — which would
235
+ * otherwise resolve to nothing. Surfacing it here turns a silent
236
+ * "extend a non-existent object" into a clear bootstrap error.
237
+ *
238
+ * This is the invariant the kernel-decomposition (ADR-0029) relies on:
239
+ * the `sys` namespace is shared across many first-party plugins, but each
240
+ * object name has exactly one owner.
241
+ *
242
+ * @throws Error listing every object whose owner count is not exactly 1.
243
+ */
244
+ assertSingleOwnerPerObject(): void;
218
245
  /**
219
246
  * Unregister all objects contributed by a package.
220
247
  *
@@ -259,6 +286,41 @@ declare class SchemaRegistry {
259
286
  registerApp(app: any, packageId?: string): void;
260
287
  getApp(name: string): any;
261
288
  getAllApps(): any[];
289
+ /**
290
+ * Register a navigation contribution — a package injecting nav items into
291
+ * an app it does not own (the UI-layer analog of object `extend`).
292
+ *
293
+ * Contributions are merged into the target app's `navigation` tree lazily
294
+ * on read ({@link getApp} / {@link getAllApps}) by group id + priority, so
295
+ * registration order does not matter and the owning app can be registered
296
+ * before or after its contributors.
297
+ */
298
+ registerAppNavContribution(contribution: {
299
+ app: string;
300
+ group?: string;
301
+ priority?: number;
302
+ items?: any[];
303
+ }, packageId?: string): void;
304
+ /** Contributions registered for an app (empty array when none). */
305
+ getAppNavContributions(appName: string): Array<{
306
+ packageId?: string;
307
+ group?: string;
308
+ priority: number;
309
+ items: any[];
310
+ }>;
311
+ /**
312
+ * Return a copy of `app` with all registered navigation contributions
313
+ * merged into its `navigation` tree. The stored app is never mutated, so
314
+ * repeated reads stay idempotent.
315
+ *
316
+ * Public so the protocol serving path (`getMetaItems` / `getMetaItem` for
317
+ * `app`) can merge contributions the same way `getApp` / `getAllApps` do —
318
+ * the REST app endpoints read through the protocol, not these helpers, so
319
+ * the merge must be reachable from there too (ADR-0029 D7).
320
+ */
321
+ applyNavContributions(app: any): any;
322
+ /** Depth-first search for a `type: 'group'` nav item by id. */
323
+ private findNavGroup;
262
324
  registerPlugin(manifest: ObjectStackManifest): void;
263
325
  getAllPlugins(): ObjectStackManifest[];
264
326
  registerKind(kind: {
@@ -386,13 +448,100 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
386
448
  getMetaTypes(): Promise<{
387
449
  types: string[];
388
450
  entries: {
451
+ actions?: {
452
+ name: string;
453
+ label: string;
454
+ type: "url" | "flow" | "script" | "api" | "form" | "modal";
455
+ refreshAfter: boolean;
456
+ objectName?: string | undefined;
457
+ icon?: string | undefined;
458
+ locations?: ("list_toolbar" | "list_item" | "record_header" | "record_more" | "record_related" | "record_section" | "global_nav")[] | undefined;
459
+ component?: "action:button" | "action:icon" | "action:menu" | "action:group" | undefined;
460
+ target?: string | undefined;
461
+ body?: {
462
+ language: "expression";
463
+ source: string;
464
+ } | {
465
+ language: "js";
466
+ source: string;
467
+ capabilities: ("log" | "api.read" | "api.write" | "crypto.uuid" | "crypto.hash")[];
468
+ timeoutMs?: number | undefined;
469
+ memoryMb?: number | undefined;
470
+ } | undefined;
471
+ execute?: string | undefined;
472
+ params?: {
473
+ required: boolean;
474
+ name?: string | undefined;
475
+ field?: string | undefined;
476
+ objectOverride?: string | undefined;
477
+ label?: string | undefined;
478
+ type?: "number" | "boolean" | "date" | "record" | "file" | "code" | "json" | "url" | "summary" | "datetime" | "color" | "time" | "text" | "textarea" | "email" | "phone" | "password" | "secret" | "markdown" | "html" | "richtext" | "currency" | "percent" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "lookup" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "autonumber" | "composite" | "repeater" | "location" | "address" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "tags" | "vector" | undefined;
479
+ options?: {
480
+ label: string;
481
+ value: string;
482
+ }[] | undefined;
483
+ placeholder?: string | undefined;
484
+ helpText?: string | undefined;
485
+ defaultValue?: unknown;
486
+ defaultFromRow?: boolean | undefined;
487
+ }[] | undefined;
488
+ variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | undefined;
489
+ confirmText?: string | undefined;
490
+ successMessage?: string | undefined;
491
+ resultDialog?: {
492
+ title?: string | undefined;
493
+ description?: string | undefined;
494
+ acknowledge?: string | undefined;
495
+ format?: "json" | "text" | "secret" | "qrcode" | "code-list" | undefined;
496
+ fields?: {
497
+ path: string;
498
+ label?: string | undefined;
499
+ format?: "json" | "text" | "secret" | "qrcode" | "code-list" | undefined;
500
+ }[] | undefined;
501
+ } | undefined;
502
+ visible?: {
503
+ dialect: "cron" | "cel" | "js" | "template";
504
+ source?: string | undefined;
505
+ ast?: unknown;
506
+ meta?: {
507
+ rationale?: string | undefined;
508
+ generatedBy?: string | undefined;
509
+ } | undefined;
510
+ } | undefined;
511
+ disabled?: boolean | {
512
+ dialect: "cron" | "cel" | "js" | "template";
513
+ source?: string | undefined;
514
+ ast?: unknown;
515
+ meta?: {
516
+ rationale?: string | undefined;
517
+ generatedBy?: string | undefined;
518
+ } | undefined;
519
+ } | undefined;
520
+ shortcut?: string | undefined;
521
+ bulkEnabled?: boolean | undefined;
522
+ aiExposed?: boolean | undefined;
523
+ recordIdParam?: string | undefined;
524
+ recordIdField?: string | undefined;
525
+ bodyShape?: "flat" | {
526
+ wrap: string;
527
+ } | undefined;
528
+ method?: "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
529
+ bodyExtra?: Record<string, unknown> | undefined;
530
+ mode?: "custom" | "create" | "delete" | "edit" | undefined;
531
+ timeout?: number | undefined;
532
+ aria?: {
533
+ ariaLabel?: string | undefined;
534
+ ariaDescribedBy?: string | undefined;
535
+ role?: string | undefined;
536
+ } | undefined;
537
+ }[] | undefined;
389
538
  type: string;
390
539
  schemaId: string;
391
540
  allowOrgOverride: boolean;
392
541
  overrideSource: "env" | "registry";
393
542
  schema: Record<string, unknown>;
394
543
  form: {
395
- type: "split" | "modal" | "drawer" | "simple" | "tabbed" | "wizard";
544
+ type: "split" | "drawer" | "modal" | "simple" | "tabbed" | "wizard";
396
545
  data?: {
397
546
  provider: "object";
398
547
  object: string;
@@ -423,7 +572,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
423
572
  sections?: {
424
573
  collapsible: boolean;
425
574
  collapsed: boolean;
426
- columns: 1 | 2 | 3 | 4;
575
+ columns: 1 | 2 | 4 | 3;
427
576
  fields: any[];
428
577
  name?: string | undefined;
429
578
  label?: string | undefined;
@@ -449,7 +598,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
449
598
  groups?: {
450
599
  collapsible: boolean;
451
600
  collapsed: boolean;
452
- columns: 1 | 2 | 3 | 4;
601
+ columns: 1 | 2 | 4 | 3;
453
602
  fields: any[];
454
603
  name?: string | undefined;
455
604
  label?: string | undefined;
@@ -705,7 +854,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
705
854
  label: string | undefined;
706
855
  required: boolean;
707
856
  readonly: boolean;
708
- type: "number" | "boolean" | "tags" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "lookup" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
857
+ type: "number" | "boolean" | "tags" | "date" | "record" | "file" | "code" | "datetime" | "signature" | "progress" | "url" | "currency" | "percent" | "password" | "secret" | "email" | "time" | "text" | "textarea" | "phone" | "markdown" | "html" | "richtext" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "lookup" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "composite" | "repeater" | "location" | "address" | "json" | "color" | "rating" | "slider" | "qrcode" | "vector";
709
858
  colSpan: number;
710
859
  }[];
711
860
  }[];
@@ -861,6 +1010,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
861
1010
  type: string;
862
1011
  name: string;
863
1012
  cacheRequest?: MetadataCacheRequest;
1013
+ locale?: string;
864
1014
  }): Promise<MetadataCacheResponse>;
865
1015
  batchData(request: {
866
1016
  object: string;
@@ -1453,12 +1603,14 @@ declare class ObjectQL implements IDataEngine {
1453
1603
  private logger;
1454
1604
  private datasourceMapping;
1455
1605
  private manifests;
1606
+ private datasourceDefs;
1456
1607
  private hooks;
1457
1608
  private middlewares;
1458
1609
  private actions;
1459
1610
  private functions;
1460
1611
  private hostContext;
1461
1612
  private realtimeService?;
1613
+ private cryptoProvider?;
1462
1614
  private _registry;
1463
1615
  constructor(hostContext?: Record<string, any>);
1464
1616
  /**
@@ -1656,6 +1808,31 @@ declare class ObjectQL implements IDataEngine {
1656
1808
  * Register a new storage driver
1657
1809
  */
1658
1810
  registerDriver(driver: DriverInterface, isDefault?: boolean): void;
1811
+ /**
1812
+ * Register a Datasource *definition* (ADR-0015).
1813
+ *
1814
+ * Distinct from {@link registerDriver}, which registers a live connection.
1815
+ * This captures the declarative `schemaMode` + `external.allowWrites` so the
1816
+ * write gate ({@link assertWriteAllowed}) can enforce external-datasource
1817
+ * ownership. Safe to call repeatedly; last write wins.
1818
+ */
1819
+ registerDatasourceDef(def: {
1820
+ name: string;
1821
+ schemaMode?: string;
1822
+ external?: {
1823
+ allowWrites?: boolean;
1824
+ };
1825
+ }): void;
1826
+ /**
1827
+ * Write gate — Gate 3 of ADR-0015 §5.3.
1828
+ *
1829
+ * Blocks insert/update/delete against a federated datasource
1830
+ * (`schemaMode !== 'managed'`) unless BOTH the datasource opts in
1831
+ * (`external.allowWrites`) AND the object opts in (`external.writable`).
1832
+ * Managed datasources (the common case, including the absence of any
1833
+ * definition) are unaffected.
1834
+ */
1835
+ private assertWriteAllowed;
1659
1836
  /**
1660
1837
  * Set the realtime service for publishing data change events.
1661
1838
  * Should be called after kernel resolves the realtime service.
@@ -1663,6 +1840,54 @@ declare class ObjectQL implements IDataEngine {
1663
1840
  * @param service - An IRealtimeService instance for event publishing
1664
1841
  */
1665
1842
  setRealtimeService(service: IRealtimeService): void;
1843
+ /**
1844
+ * Register the crypto provider that backs `secret`-typed fields.
1845
+ *
1846
+ * When set, the engine encrypts secret fields on write (storing ciphertext in
1847
+ * `sys_secret` and only an opaque ref on the business row) and masks them on
1848
+ * read. When NOT set, writing to an object that declares a secret field is
1849
+ * **fail-closed** — the write throws rather than persist cleartext.
1850
+ *
1851
+ * Mirrors the Settings subsystem's ICryptoProvider wiring; the host (e.g.
1852
+ * `serve`) injects `InMemoryCryptoProvider` in dev and a KMS/Vault-backed
1853
+ * provider in production.
1854
+ */
1855
+ setCryptoProvider(provider: ICryptoProvider): void;
1856
+ /**
1857
+ * Encrypt any `secret`-typed fields on `row` in place before it reaches the
1858
+ * driver. Each plaintext is wrapped by the ICryptoProvider, persisted as a
1859
+ * `sys_secret` row, and replaced on `row` by an opaque ref. Cleartext never
1860
+ * reaches the business table.
1861
+ *
1862
+ * Rules:
1863
+ * - No secret fields on the object ⇒ no-op (fast path, no crypto cost).
1864
+ * - `null`/`undefined` value ⇒ left as-is (clears the secret).
1865
+ * - Value already a ref (re-save of an unchanged ref) ⇒ left as-is.
1866
+ * - Value equal to the read mask ⇒ dropped, so a form round-trip that
1867
+ * echoes the mask does not overwrite the stored secret.
1868
+ * - **Fail-closed:** any other value with no CryptoProvider registered, or
1869
+ * no reachable `sys_secret` store, THROWS — never persists cleartext.
1870
+ */
1871
+ private encryptSecretFields;
1872
+ /**
1873
+ * Mask `secret`-typed fields on read so plaintext never leaves the engine
1874
+ * through the normal query path. A set secret becomes {@link SECRET_MASK};
1875
+ * an unset one stays `null`. Privileged callers that genuinely need the
1876
+ * plaintext use {@link resolveSecret} against the stored ref.
1877
+ */
1878
+ private maskSecretFields;
1879
+ /**
1880
+ * Dereference a stored secret ref back to its plaintext. Intended for
1881
+ * privileged, server-side consumers (e.g. a datasource connection-pool
1882
+ * binder) — NOT exposed through the generic read path, which only ever
1883
+ * returns the mask.
1884
+ *
1885
+ * Fail-closed: throws when no CryptoProvider is registered or the
1886
+ * `sys_secret` row is missing. Returns `null` when `ref` is not a secret ref.
1887
+ */
1888
+ resolveSecret(ref: unknown, opts?: {
1889
+ tenantId?: string;
1890
+ }): Promise<string | null>;
1666
1891
  /**
1667
1892
  * Helper to get object definition
1668
1893
  */
@@ -1798,6 +2023,17 @@ declare class ObjectQL implements IDataEngine {
1798
2023
  * this method directly looks up a driver by its registered name.
1799
2024
  */
1800
2025
  getDriverByName(name: string): DriverInterface | undefined;
2026
+ /**
2027
+ * Introspect a datasource's live remote schema (ADR-0015).
2028
+ *
2029
+ * Resolves the driver registered under `datasource` and delegates to its
2030
+ * `introspectSchema()` capability. Used by the external-datasource service
2031
+ * (and CLI/REST) to list remote tables and validate federated objects.
2032
+ *
2033
+ * @throws if the datasource has no registered driver, or the driver does
2034
+ * not support introspection.
2035
+ */
2036
+ introspectDatasource(datasource: string): Promise<unknown>;
1801
2037
  /**
1802
2038
  * Get the driver responsible for the given object.
1803
2039
  *
@@ -2143,7 +2379,7 @@ declare function wrapDeclarativeHook(meta: Hook, handler: HookHandler, opts?: Wr
2143
2379
 
2144
2380
  interface FieldValidationError {
2145
2381
  field: string;
2146
- code: 'required' | 'min_length' | 'max_length' | 'min_value' | 'max_value' | 'invalid_email' | 'invalid_url' | 'invalid_phone' | 'invalid_number' | 'invalid_boolean' | 'invalid_date' | 'invalid_option';
2382
+ code: 'required' | 'min_length' | 'max_length' | 'min_value' | 'max_value' | 'invalid_email' | 'invalid_url' | 'invalid_phone' | 'invalid_number' | 'invalid_boolean' | 'invalid_date' | 'invalid_option' | 'invalid_transition' | 'rule_violation';
2147
2383
  message: string;
2148
2384
  /** Allowed values for select/multiselect, when applicable. */
2149
2385
  options?: string[];
@@ -2153,7 +2389,7 @@ declare class ValidationError extends Error {
2153
2389
  readonly fields: FieldValidationError[];
2154
2390
  constructor(fields: FieldValidationError[]);
2155
2391
  }
2156
- type Mode = 'insert' | 'update';
2392
+ type Mode$1 = 'insert' | 'update';
2157
2393
  interface FieldDef {
2158
2394
  name?: string;
2159
2395
  type: string;
@@ -2179,7 +2415,45 @@ interface FieldDef {
2179
2415
  */
2180
2416
  declare function validateRecord(objectSchema: {
2181
2417
  fields?: Record<string, FieldDef>;
2182
- } | undefined | null, data: Record<string, unknown> | undefined | null, mode: Mode): void;
2418
+ } | undefined | null, data: Record<string, unknown> | undefined | null, mode: Mode$1): void;
2419
+
2420
+ type Mode = 'insert' | 'update';
2421
+ interface EvaluateRulesOptions {
2422
+ /** Prior persisted record (update only). Absent on insert. */
2423
+ previous?: Record<string, unknown> | null;
2424
+ /** Optional logger for non-blocking diagnostics (broken rules, warnings). */
2425
+ logger?: {
2426
+ warn?: (msg: string, meta?: any) => void;
2427
+ };
2428
+ }
2429
+ /**
2430
+ * Returns true when the object declares at least one validation rule whose
2431
+ * correct evaluation needs the prior record (so the engine knows whether the
2432
+ * extra fetch on the update path is worth it).
2433
+ */
2434
+ declare function needsPriorRecord(objectSchema: {
2435
+ validations?: unknown[];
2436
+ } | undefined | null): boolean;
2437
+ /**
2438
+ * Evaluate an object's declared validation rules against an incoming write.
2439
+ *
2440
+ * Throws `ValidationError` (the same envelope `validateRecord` uses, so REST
2441
+ * surfaces a single `400 VALIDATION_FAILED`) when one or more `error`-severity
2442
+ * rules are violated. Returns void otherwise.
2443
+ */
2444
+ declare function evaluateValidationRules(objectSchema: {
2445
+ validations?: unknown[];
2446
+ } | undefined | null, data: Record<string, unknown> | undefined | null, mode: Mode, opts?: EvaluateRulesOptions): void;
2447
+ /**
2448
+ * Introspection helper (ADR-0020 D3.3): given an object's schema, a state
2449
+ * field, and a current state, return the legal next states declared by the
2450
+ * matching `state_machine` rule. Returns `null` when no such rule exists (so
2451
+ * callers can distinguish "no FSM governs this field" from "a dead-end state
2452
+ * with zero outgoing transitions", which returns `[]`).
2453
+ */
2454
+ declare function legalNextStates(objectSchema: {
2455
+ validations?: unknown[];
2456
+ } | undefined | null, field: string, currentState: string): string[] | null;
2183
2457
 
2184
2458
  /**
2185
2459
  * MetadataFacade
@@ -2410,6 +2684,45 @@ interface ObjectQLKernelOptions {
2410
2684
  */
2411
2685
  declare function createObjectQLKernel(options?: ObjectQLKernelOptions): Promise<ObjectKernel>;
2412
2686
 
2687
+ /**
2688
+ * Secret-field channel — helpers for the `secret` FieldType.
2689
+ *
2690
+ * A `secret` field (DB password, API key, token) is **reversible**: the engine
2691
+ * encrypts it on write via the registered `ICryptoProvider`, persists the
2692
+ * ciphertext as a `sys_secret` row, and stores only an opaque *ref* on the
2693
+ * business row. On read the ref is masked, never the plaintext. This mirrors
2694
+ * the Settings subsystem (`sys_setting.value_enc → sys_secret.id`), generalized
2695
+ * to object fields.
2696
+ *
2697
+ * Contrast with `password` — a one-way hash owned by the auth subsystem, never
2698
+ * decrypted. The two never share a code path.
2699
+ */
2700
+
2701
+ /**
2702
+ * Prefix marking a persisted field value as a `sys_secret` handle ref rather
2703
+ * than cleartext. Chosen to be unambiguous and human-greppable in a DB dump,
2704
+ * while making it obvious that the column holds no plaintext.
2705
+ */
2706
+ declare const SECRET_REF_PREFIX = "secret:";
2707
+ /**
2708
+ * Value returned in place of a secret field on a normal read. Indicates
2709
+ * "a secret is set" without leaking the handle id or the plaintext. A field
2710
+ * with no stored secret resolves to `null` instead.
2711
+ */
2712
+ declare const SECRET_MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
2713
+ /** Wrap a `sys_secret` handle id as the opaque ref persisted on the row. */
2714
+ declare function makeSecretRef(handleId: string): string;
2715
+ /** True when `value` is a secret ref previously produced by {@link makeSecretRef}. */
2716
+ declare function isSecretRef(value: unknown): value is string;
2717
+ /** Extract the `sys_secret` handle id from a ref, or `null` when not a ref. */
2718
+ declare function parseSecretRef(value: unknown): string | null;
2719
+ /**
2720
+ * Collect the names of `secret`-typed fields declared on an object schema.
2721
+ * Returns an empty array when the schema has no fields or no secret fields —
2722
+ * callers can fast-path on `length === 0` to skip all crypto work.
2723
+ */
2724
+ declare function collectSecretFields(schema: ServiceObject | undefined | null): string[];
2725
+
2413
2726
  /**
2414
2727
  * Column metadata from database introspection.
2415
2728
  */
@@ -2497,4 +2810,4 @@ declare function convertIntrospectedSchemaToObjects(introspectedSchema: Introspe
2497
2810
  skipSystemColumns?: boolean;
2498
2811
  }): ServiceObject[];
2499
2812
 
2500
- export { type BindHooksOptions, type BindHooksResult, DEFAULT_EXTENDER_PRIORITY, DEFAULT_OWNER_PRIORITY, type EngineMiddleware, type FieldValidationError, type HookEntry, type HookHandler, type HookMetricLabel, type HookMetricOutcome, type HookMetricsRecorder, type HookSkipReason, InMemoryHookMetricsRecorder, type IntrospectedColumn, type IntrospectedForeignKey, type IntrospectedSchema, type IntrospectedTable, MetadataFacade, type ObjectContributor, ObjectQL, type ObjectQLHostContext, type ObjectQLKernelOptions, ObjectQLPlugin, ObjectRepository, ObjectStackProtocolImplementation, type OperationContext, RESERVED_NAMESPACES, SchemaRegistry, type SchemaRegistryOptions, ScopedContext, type SysMetadataEngine, SysMetadataRepository, type SysMetadataRepositoryOptions, ValidationError, type WrapDeclarativeOptions, applyInMemoryAggregation, applySystemFields, bindHooksToEngine, bucketDateValue, computeFQN, convertIntrospectedSchemaToObjects, createObjectQLKernel, noopHookMetricsRecorder, parseFQN, toTitleCase, validateRecord, wrapDeclarativeHook };
2813
+ export { type BindHooksOptions, type BindHooksResult, DEFAULT_EXTENDER_PRIORITY, DEFAULT_OWNER_PRIORITY, type EngineMiddleware, type EvaluateRulesOptions, type FieldValidationError, type HookEntry, type HookHandler, type HookMetricLabel, type HookMetricOutcome, type HookMetricsRecorder, type HookSkipReason, InMemoryHookMetricsRecorder, type IntrospectedColumn, type IntrospectedForeignKey, type IntrospectedSchema, type IntrospectedTable, MetadataFacade, type ObjectContributor, ObjectQL, type ObjectQLHostContext, type ObjectQLKernelOptions, ObjectQLPlugin, ObjectRepository, ObjectStackProtocolImplementation, type OperationContext, RESERVED_NAMESPACES, SECRET_MASK, SECRET_REF_PREFIX, SchemaRegistry, type SchemaRegistryOptions, ScopedContext, type SysMetadataEngine, SysMetadataRepository, type SysMetadataRepositoryOptions, ValidationError, type WrapDeclarativeOptions, applyInMemoryAggregation, applySystemFields, bindHooksToEngine, bucketDateValue, collectSecretFields, computeFQN, convertIntrospectedSchemaToObjects, createObjectQLKernel, evaluateValidationRules, isSecretRef, legalNextStates, makeSecretRef, needsPriorRecord, noopHookMetricsRecorder, parseFQN, parseSecretRef, toTitleCase, validateRecord, wrapDeclarativeHook };