@objectstack/core 17.0.0-rc.6 → 17.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.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger, LifecycleEventName, IServiceRegistry, IObjectQLEngine } from '@objectstack/spec/contracts';
1
+ import { Logger, LifecycleEventName, IServiceRegistry, AudienceBindingSuggestionFilter, IObjectQLEngine } from '@objectstack/spec/contracts';
2
2
  export { EngineSchemaRegistryView, EngineTransactionInfo, EngineTransactionOptions, IDataDriver, IDataEngine, IHttpRequest, IHttpResponse, IHttpServer, IObjectQLEngine, Logger, Middleware, RouteHandler } from '@objectstack/spec/contracts';
3
3
  import { z } from 'zod';
4
4
  import { LoggerConfig, MigrationOnCrashPolicy, MigrationJournalEvent } from '@objectstack/spec/system';
@@ -883,6 +883,10 @@ declare class HttpTestAdapter implements TestExecutionAdapter {
883
883
  private baseUrl;
884
884
  private authToken?;
885
885
  constructor(baseUrl: string, authToken?: string | undefined);
886
+ /** `{baseUrl}{apiBasePath}{dataPrefix}/{object}` — the collection URL. */
887
+ private collectionUrl;
888
+ /** `{collection}/{id}` — the single-record URL. */
889
+ private recordUrl;
886
890
  execute(action: QA.TestAction, _context: Record<string, unknown>): Promise<unknown>;
887
891
  private createRecord;
888
892
  private updateRecord;
@@ -2312,6 +2316,48 @@ declare function isGrantActive(row: GrantValidityWindow | null | undefined, nowM
2312
2316
  */
2313
2317
  declare function isGrantExpired(row: GrantValidityWindow | null | undefined, nowMs: number): boolean;
2314
2318
 
2319
+ /**
2320
+ * [#7678] The `?status=` vocabulary of the audience-binding suggestion list
2321
+ * (ADR-0090 D5/D9) — ONE owner for a rule that had exactly one implementation
2322
+ * and two seams needing it.
2323
+ *
2324
+ * The predicate was written for the runtime dispatcher's `/security` domain and
2325
+ * lived there, private. The **live** REST route
2326
+ * (`rest-server.ts` → `registerSecurityEndpoints`) is a second seam onto the
2327
+ * same service call and never had it, so `?status=garbage` reached the service,
2328
+ * matched no row, and answered **200 with an empty list** — which reads as
2329
+ * "there are no suggestions", a plausible and actionable-looking answer, rather
2330
+ * than "your filter was not a status". That silent arm is the defect; the two
2331
+ * seams disagreeing about one contract is the cause.
2332
+ *
2333
+ * So this module is the convergence, not a copy: `domains/security.ts` and
2334
+ * `rest-server.ts` both import from here, and the vocabulary — including the
2335
+ * refusal wording — exists once.
2336
+ *
2337
+ * The record is keyed BY the contract type on purpose (carried over from the
2338
+ * original): adding a status to `AudienceBindingSuggestionFilter` leaves a key
2339
+ * missing here and renaming one leaves a key excess, and either way this fails
2340
+ * to compile. A plain `['pending', …]` array would silently drift.
2341
+ */
2342
+
2343
+ /** The `status` arm of {@link AudienceBindingSuggestionFilter}, named. */
2344
+ type AudienceBindingSuggestionStatus = NonNullable<AudienceBindingSuggestionFilter['status']>;
2345
+ /** The accepted `?status=` values, keyed by the contract type (see module note). */
2346
+ declare const AUDIENCE_BINDING_SUGGESTION_STATUSES: Record<AudienceBindingSuggestionStatus, true>;
2347
+ /**
2348
+ * The same vocabulary as a list — for refusal messages, and for tests that must
2349
+ * enumerate every valid value FROM the type rather than hand-picking one.
2350
+ */
2351
+ declare const AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES: readonly AudienceBindingSuggestionStatus[];
2352
+ /**
2353
+ * Is `value` one of the three statuses the contract declares? Case-sensitive on
2354
+ * purpose — the contract's values are lowercase, so `PENDING` is not a status
2355
+ * and gets the same refusal as `garbage`.
2356
+ */
2357
+ declare const isAudienceBindingSuggestionStatus: (value: string) => value is AudienceBindingSuggestionStatus;
2358
+ /** The refusal wording, shared so both seams answer an unknown status identically. */
2359
+ declare const unknownAudienceBindingSuggestionStatusMessage: (value: string) => string;
2360
+
2315
2361
  /**
2316
2362
  * [#7284] The `__` operation-private-key convention — one owner, on the
2317
2363
  * CONSUMER side.
@@ -2333,8 +2379,10 @@ declare function isGrantExpired(row: GrantValidityWindow | null | undefined, now
2333
2379
  * `__delegatorReadScope` / `__delegatorWriteScope`, stamped in place by
2334
2380
  * `security-plugin.ts` (`sc.__readScope = …`);
2335
2381
  * - the engine's internal privilege markers on the same channel —
2336
- * `__expandRead` waives the object-level CRUD check for a lookup expansion,
2337
- * `__referentialFieldClear` the referential-clear write.
2382
+ * `__expandRead` marks a read as a lookup EXPANSION sub-read (it no longer
2383
+ * relaxes any gate — #7626 removed that waiver — but it still travels with
2384
+ * one operation and must not be inherited by another), `__referentialFieldClear`
2385
+ * authorizes the referential-clear write.
2338
2386
  *
2339
2387
  * plugin-security is the PRODUCER of that vocabulary and would be the most
2340
2388
  * honest owner of the rule for consuming it, but none of the three consumers
@@ -2641,6 +2689,30 @@ declare function withTransientRetry<T>(fn: (attempt: number) => Promise<T>, opts
2641
2689
  */
2642
2690
  declare function bulkWrite<TRow, TRecord = any>(rows: TRow[], opts: BulkWriteOptions<TRow, TRecord>): Promise<BulkWriteRowResult<TRecord>[]>;
2643
2691
 
2692
+ /**
2693
+ * Collect the names of fields declared `internal: true` on `schema`.
2694
+ *
2695
+ * Same verdicts as objectql's `collectInternalReadFields` (see the module
2696
+ * header for why it is restated rather than imported): strict `=== true`,
2697
+ * empty result for a missing/field-less schema.
2698
+ */
2699
+ declare function collectInternalWriteResponseFields(schema: unknown): string[];
2700
+ /**
2701
+ * Drop every `internal: true` field from a write response's record(s), in
2702
+ * place. THE single helper every external write mouth goes through — see the
2703
+ * module header; the three tripwires enforce the "every".
2704
+ *
2705
+ * @param schema The registered object schema (`engine.registry.getObject(...)`
2706
+ * / the protocol's own registry view / `metadataService
2707
+ * .getObject(...)`). An unknown object (no schema) strips
2708
+ * nothing — the write itself would have been refused upstream
2709
+ * by the object-existence gate.
2710
+ * @param records A single record, an array of records, or anything a write
2711
+ * mouth hands back where a record could sit (`null`, a count, a
2712
+ * boolean): non-objects are skipped, arrays are walked.
2713
+ */
2714
+ declare function omitInternalFieldsFromWriteResponse(schema: unknown, records: unknown): void;
2715
+
2644
2716
  /**
2645
2717
  * Can this runtime actually roll back? — the ADR-0119 D4 gate, shared.
2646
2718
  *
@@ -2934,6 +3006,59 @@ declare function resolveFilterTokens<T>(filter: T, ctx?: FilterTokenResolutionCo
2934
3006
  */
2935
3007
  declare function filterTokenContextFrom(execCtx: ExecutionContextLike | undefined, now?: Date): FilterTokenResolutionContext;
2936
3008
 
3009
+ /**
3010
+ * [#4435] The 404 a single-record operation answers when the id names no row.
3011
+ *
3012
+ * Extracted so the READ and the two WRITE paths cannot disagree about it. They
3013
+ * did: `getData` answered `404 RECORD_NOT_FOUND` while `updateData` returned
3014
+ * `200 { record: null }` and `deleteData` returned `200 { success: true }` for
3015
+ * any string in the path — so a typo'd id, an already-deleted row and a real
3016
+ * deletion were indistinguishable, and a client PATCHing a concurrently deleted
3017
+ * record was told its write had landed.
3018
+ *
3019
+ * That is the same silent-no-op shape the v17 train removed everywhere else
3020
+ * this window (#4240/#4303/#4315 refuse missing fields, #4169 refuses unknown
3021
+ * params, #4190 stopped dropping filters) — a write that touched zero rows
3022
+ * reporting 200 is that shape one level up, on the verb where it costs the
3023
+ * most.
3024
+ *
3025
+ * [#5138] EXPORTED, for the same "cannot disagree about it" reason one layer
3026
+ * out. `@objectstack/runtime`'s `callData` is protocol-first with an ObjectQL
3027
+ * FALLBACK, and the fallback had reinvented this fact three incompatible ways
3028
+ * (`get` → `null`, `update` → a bare `Error` with no status ⇒ 500, `delete` →
3029
+ * no check at all ⇒ `200 { deleted: true }` for a row that never existed). It
3030
+ * now calls THIS function, so the two paths behind one `callData` answer a
3031
+ * missing id identically — which is the only reason a caller may stop caring
3032
+ * which of them served it. Re-spelling the envelope there would have been a
3033
+ * second not-found envelope; `RECORD_NOT_FOUND` (#5088) is the one this repo
3034
+ * has.
3035
+ *
3036
+ * ── [#7867] Why it lives in `@objectstack/core` and not where it was written ──
3037
+ *
3038
+ * Because the THIRD path that needed it could not reach the second one. An
3039
+ * action body's `ctx.api.object(name).update({ id, … })` traverses neither
3040
+ * `protocol.updateData` nor `callData`: it reaches `ObjectQL.update()`'s by-id
3041
+ * branch directly, which had no existence gate at all, so a ghost id was a
3042
+ * silent no-op that then died on whatever the pipeline complained about first
3043
+ * (a `HookConditionError` 400 on a hooked object, a required-field
3044
+ * `VALIDATION_FAILED` 400 on an unhooked one — the 400 class varied with the
3045
+ * object's declarations; the missing 404 was the constant).
3046
+ *
3047
+ * The gate for that path belongs in the engine, and `packages/objectql` cannot
3048
+ * import `@objectstack/metadata-protocol` where this function was written:
3049
+ * ADR-0076 D2's boundary ratchet (`core-boundary.ratchet.test.ts`) forbids the
3050
+ * whole `@objectstack/objectql/core` closure — `engine.ts` included — from
3051
+ * pulling that package in. So the choice was a FOURTH spelling of the envelope
3052
+ * or one home both layers already depend on. #5138's own sentence rules the
3053
+ * first out, so this is the second: the factory moved down to the lowest
3054
+ * package the three producers share, and `@objectstack/metadata-protocol`
3055
+ * re-exports it unchanged for every existing importer.
3056
+ *
3057
+ * This is the same move `engineCanRollBack` made for the same reason — a fact
3058
+ * two layers must agree on lives in the layer beneath both, not in a copy each.
3059
+ */
3060
+ declare function recordNotFoundError(object: string, id: string | number): Error;
3061
+
2937
3062
  /**
2938
3063
  * In-memory Map-backed cache fallback.
2939
3064
  *
@@ -3069,7 +3194,24 @@ declare function createMemoryI18n(): {
3069
3194
  * not a merge — so deleted items/keys stop resolving on the next sync.
3070
3195
  */
3071
3196
  replaceAuthoredTranslations(byLocale: Record<string, Record<string, unknown>>): void;
3197
+ /**
3198
+ * Report the locales this stack offers.
3199
+ *
3200
+ * [#7679] When the app declared `i18n.supportedLocales`, that declaration
3201
+ * IS the answer — in declared order, and including a declared locale no
3202
+ * bundle was ever loaded for (declared-but-unserved). Reporting the
3203
+ * declaration rather than an intersection is what gives a client the
3204
+ * signal that the locale it is being offered has nothing behind it yet;
3205
+ * quietly dropping it would leave the gap invisible on both sides. It is
3206
+ * also the only answer that does not depend on how much had loaded by the
3207
+ * time this was called.
3208
+ *
3209
+ * With nothing declared, the loaded set — the behaviour every app that
3210
+ * never opted in already has.
3211
+ */
3072
3212
  getLocales(): string[];
3213
+ /** @see II18nService.setSupportedLocales — [#7679] */
3214
+ setSupportedLocales(locales: readonly string[] | undefined): void;
3073
3215
  getDefaultLocale(): string;
3074
3216
  setDefaultLocale(locale: string): void;
3075
3217
  };
@@ -3080,6 +3222,13 @@ declare function createMemoryI18n(): {
3080
3222
  * Implements the IMetadataService contract with a simple Map-of-Maps store.
3081
3223
  * Used by ObjectKernel as an automatic fallback when no real metadata plugin
3082
3224
  * (e.g. MetadataPlugin with file-system persistence) is registered.
3225
+ *
3226
+ * [#7378] Carries the ruled register/read argument contract
3227
+ * (`../metadata-service-contract.ts` — the ruling is quoted there):
3228
+ * `register` refuses a `data.name` that disagrees with the `name` argument and
3229
+ * refuses a non-document `data` (rows 1/3), and every type store is keyed on
3230
+ * the CANONICAL type (row 2), so `register('objects', n, d)` and
3231
+ * `get('object', n)` address one store rather than two.
3083
3232
  */
3084
3233
  declare function createMemoryMetadata(): {
3085
3234
  __serviceInfo: {
@@ -3133,6 +3282,37 @@ declare function wireAuthoredTranslationSync(ctx: MinimalCtx): void;
3133
3282
  */
3134
3283
  declare const CORE_FALLBACK_FACTORIES: Record<string, () => Record<string, any>>;
3135
3284
 
3285
+ /**
3286
+ * The canonical spelling an `IMetadataService` type store is keyed on
3287
+ * (#7378 row 2). Folds a plural manifest spelling to the singular metadata
3288
+ * type name (`'objects'` → `'object'`, `'views'` → `'view'`, …) through the
3289
+ * platform's one plural↔singular map (`PLURAL_TO_SINGULAR`,
3290
+ * `@objectstack/spec/shared`); a name with no plural mapping — which includes
3291
+ * every canonical singular type — passes through unchanged.
3292
+ */
3293
+ declare function canonicalMetadataServiceType(type: string): string;
3294
+ /**
3295
+ * Enforce rows 1 and 3 of the #7378 ruling on a
3296
+ * `register(type, name, data)` payload — call it before the first store write,
3297
+ * so a refusal writes nothing anywhere.
3298
+ *
3299
+ * Refuses, with a locating `VALIDATION_ERROR` (status 400):
3300
+ *
3301
+ * - **a non-document `data`** (row 3): anything that is not a plain object —
3302
+ * primitives, `null`, arrays. The contract declares `data: unknown`, so
3303
+ * this is a runtime refusal, not a type error;
3304
+ * - **a `data.name` that disagrees with the `name` argument** (row 1), in
3305
+ * either direction. A document with NO `name` of its own is fine — the
3306
+ * argument is the key, and there is no disagreement to refuse.
3307
+ *
3308
+ * Deliberately NOT called by `registerInMemory`: that optional member is a
3309
+ * boot-time seeding primitive outside the ruled surface (the ruling names
3310
+ * `register`), and its callers hand it artefacts whose shape source control
3311
+ * owns. It shares the row-2 canonical fold — a store key is a store fact, not
3312
+ * a per-member choice — just not the refusals.
3313
+ */
3314
+ declare function assertMetadataRegisterContract(type: string, name: string, data: unknown): asserts data is Record<string, unknown>;
3315
+
3136
3316
  /**
3137
3317
  * Plugin Health Monitor
3138
3318
  *
@@ -3450,4 +3630,4 @@ declare class NamespaceResolver {
3450
3630
  private suggestAlternative;
3451
3631
  }
3452
3632
 
3453
- export { ANONYMOUS_DENY_BODY, ANONYMOUS_DENY_CODE, ANONYMOUS_DENY_MESSAGE, ANONYMOUS_DENY_STATUS, API_KEY_PREFIX, type AnonymousDenyInput, type ApiKeyPrincipal, type AuthGate, type BucketGranularity, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, ENTRY_EXECUTION_CONTEXT_FIELDS, type EngineWithTransaction, type EntryExecutionContextField, type EntryLocalization, type ExecutionContextAssemblyInput, type ExecutionContextEntryFields, type ExecutionContextLike, type FilterTokenResolutionContext, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, type InterruptedRun, type KernelState, type KeyInput, type LadderPrincipal, type LadderRow, LiteKernel, type MigrationChunk, type MigrationChunkContext, MigrationJournalRefusal, type MigrationPlan, type MigrationPlanProvider, MigrationPlanRegistry, type MigrationPlanStep, type MigrationRunResult, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, type OAuthTokenProvenance, OPERATION_PRIVATE_KEY_PREFIX, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type OrderablePlugin, POSTURE_INJECTION_RULE, POSTURE_LADDER, POSTURE_RANK, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PostureEvidence, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolveUserAuthzGrantsOptions, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, type RunMigrationJournalOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, UnknownFilterTokenError, UnresolvedFilterTokenError, type UserAuthzGrants, type VersionCompatibility, assembleExecutionContext, assembleExecutionContextOrGuest, assertInitServiceRequirements, bucketKeyToCalendarRange, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, counterSignPayload, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, derivePosture, describeInitOrderFault, engineCanRollBack, evaluateAuthGate, extractApiKey, filterTokenContextFrom, findInterruptedRuns, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, hashMigrationPlan, isAuthGateAllowlisted, isExpired, isGrantActive, isGrantExpired, isNode, normalizeAuthGate, parseScopes, parseSignature, planChunks, postureVisibleRows, readAuthoredTranslationLayer, readRunJournal, resolveApiKeyPrincipal, resolveAuthzContext, resolveFilterToken, resolveFilterTokens, resolveLocale, resolveLocalizationContext, resolvePluginOrder, resolveUserAuthzGrants, resumeMigrationJournal, runMigrationJournal, safeExit, shouldDenyAnonymous, signPayload, validateInitServiceContract, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry, withoutOperationPrivateKeys, zonedDateStartToUtcMs };
3633
+ export { ANONYMOUS_DENY_BODY, ANONYMOUS_DENY_CODE, ANONYMOUS_DENY_MESSAGE, ANONYMOUS_DENY_STATUS, API_KEY_PREFIX, AUDIENCE_BINDING_SUGGESTION_STATUSES, AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES, type AnonymousDenyInput, type ApiKeyPrincipal, type AudienceBindingSuggestionStatus, type AuthGate, type BucketGranularity, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, ENTRY_EXECUTION_CONTEXT_FIELDS, type EngineWithTransaction, type EntryExecutionContextField, type EntryLocalization, type ExecutionContextAssemblyInput, type ExecutionContextEntryFields, type ExecutionContextLike, type FilterTokenResolutionContext, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, type InterruptedRun, type KernelState, type KeyInput, type LadderPrincipal, type LadderRow, LiteKernel, type MigrationChunk, type MigrationChunkContext, MigrationJournalRefusal, type MigrationPlan, type MigrationPlanProvider, MigrationPlanRegistry, type MigrationPlanStep, type MigrationRunResult, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, type OAuthTokenProvenance, OPERATION_PRIVATE_KEY_PREFIX, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type OrderablePlugin, POSTURE_INJECTION_RULE, POSTURE_LADDER, POSTURE_RANK, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PostureEvidence, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolveUserAuthzGrantsOptions, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, type RunMigrationJournalOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, UnknownFilterTokenError, UnresolvedFilterTokenError, type UserAuthzGrants, type VersionCompatibility, assembleExecutionContext, assembleExecutionContextOrGuest, assertInitServiceRequirements, assertMetadataRegisterContract, bucketKeyToCalendarRange, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, canonicalMetadataServiceType, collectInternalWriteResponseFields, counterSignPayload, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, derivePosture, describeInitOrderFault, engineCanRollBack, evaluateAuthGate, extractApiKey, filterTokenContextFrom, findInterruptedRuns, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, hashMigrationPlan, isAudienceBindingSuggestionStatus, isAuthGateAllowlisted, isExpired, isGrantActive, isGrantExpired, isNode, normalizeAuthGate, omitInternalFieldsFromWriteResponse, parseScopes, parseSignature, planChunks, postureVisibleRows, readAuthoredTranslationLayer, readRunJournal, recordNotFoundError, resolveApiKeyPrincipal, resolveAuthzContext, resolveFilterToken, resolveFilterTokens, resolveLocale, resolveLocalizationContext, resolvePluginOrder, resolveUserAuthzGrants, resumeMigrationJournal, runMigrationJournal, safeExit, shouldDenyAnonymous, signPayload, unknownAudienceBindingSuggestionStatusMessage, validateInitServiceContract, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry, withoutOperationPrivateKeys, zonedDateStartToUtcMs };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Logger, LifecycleEventName, IServiceRegistry, IObjectQLEngine } from '@objectstack/spec/contracts';
1
+ import { Logger, LifecycleEventName, IServiceRegistry, AudienceBindingSuggestionFilter, IObjectQLEngine } from '@objectstack/spec/contracts';
2
2
  export { EngineSchemaRegistryView, EngineTransactionInfo, EngineTransactionOptions, IDataDriver, IDataEngine, IHttpRequest, IHttpResponse, IHttpServer, IObjectQLEngine, Logger, Middleware, RouteHandler } from '@objectstack/spec/contracts';
3
3
  import { z } from 'zod';
4
4
  import { LoggerConfig, MigrationOnCrashPolicy, MigrationJournalEvent } from '@objectstack/spec/system';
@@ -883,6 +883,10 @@ declare class HttpTestAdapter implements TestExecutionAdapter {
883
883
  private baseUrl;
884
884
  private authToken?;
885
885
  constructor(baseUrl: string, authToken?: string | undefined);
886
+ /** `{baseUrl}{apiBasePath}{dataPrefix}/{object}` — the collection URL. */
887
+ private collectionUrl;
888
+ /** `{collection}/{id}` — the single-record URL. */
889
+ private recordUrl;
886
890
  execute(action: QA.TestAction, _context: Record<string, unknown>): Promise<unknown>;
887
891
  private createRecord;
888
892
  private updateRecord;
@@ -2312,6 +2316,48 @@ declare function isGrantActive(row: GrantValidityWindow | null | undefined, nowM
2312
2316
  */
2313
2317
  declare function isGrantExpired(row: GrantValidityWindow | null | undefined, nowMs: number): boolean;
2314
2318
 
2319
+ /**
2320
+ * [#7678] The `?status=` vocabulary of the audience-binding suggestion list
2321
+ * (ADR-0090 D5/D9) — ONE owner for a rule that had exactly one implementation
2322
+ * and two seams needing it.
2323
+ *
2324
+ * The predicate was written for the runtime dispatcher's `/security` domain and
2325
+ * lived there, private. The **live** REST route
2326
+ * (`rest-server.ts` → `registerSecurityEndpoints`) is a second seam onto the
2327
+ * same service call and never had it, so `?status=garbage` reached the service,
2328
+ * matched no row, and answered **200 with an empty list** — which reads as
2329
+ * "there are no suggestions", a plausible and actionable-looking answer, rather
2330
+ * than "your filter was not a status". That silent arm is the defect; the two
2331
+ * seams disagreeing about one contract is the cause.
2332
+ *
2333
+ * So this module is the convergence, not a copy: `domains/security.ts` and
2334
+ * `rest-server.ts` both import from here, and the vocabulary — including the
2335
+ * refusal wording — exists once.
2336
+ *
2337
+ * The record is keyed BY the contract type on purpose (carried over from the
2338
+ * original): adding a status to `AudienceBindingSuggestionFilter` leaves a key
2339
+ * missing here and renaming one leaves a key excess, and either way this fails
2340
+ * to compile. A plain `['pending', …]` array would silently drift.
2341
+ */
2342
+
2343
+ /** The `status` arm of {@link AudienceBindingSuggestionFilter}, named. */
2344
+ type AudienceBindingSuggestionStatus = NonNullable<AudienceBindingSuggestionFilter['status']>;
2345
+ /** The accepted `?status=` values, keyed by the contract type (see module note). */
2346
+ declare const AUDIENCE_BINDING_SUGGESTION_STATUSES: Record<AudienceBindingSuggestionStatus, true>;
2347
+ /**
2348
+ * The same vocabulary as a list — for refusal messages, and for tests that must
2349
+ * enumerate every valid value FROM the type rather than hand-picking one.
2350
+ */
2351
+ declare const AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES: readonly AudienceBindingSuggestionStatus[];
2352
+ /**
2353
+ * Is `value` one of the three statuses the contract declares? Case-sensitive on
2354
+ * purpose — the contract's values are lowercase, so `PENDING` is not a status
2355
+ * and gets the same refusal as `garbage`.
2356
+ */
2357
+ declare const isAudienceBindingSuggestionStatus: (value: string) => value is AudienceBindingSuggestionStatus;
2358
+ /** The refusal wording, shared so both seams answer an unknown status identically. */
2359
+ declare const unknownAudienceBindingSuggestionStatusMessage: (value: string) => string;
2360
+
2315
2361
  /**
2316
2362
  * [#7284] The `__` operation-private-key convention — one owner, on the
2317
2363
  * CONSUMER side.
@@ -2333,8 +2379,10 @@ declare function isGrantExpired(row: GrantValidityWindow | null | undefined, now
2333
2379
  * `__delegatorReadScope` / `__delegatorWriteScope`, stamped in place by
2334
2380
  * `security-plugin.ts` (`sc.__readScope = …`);
2335
2381
  * - the engine's internal privilege markers on the same channel —
2336
- * `__expandRead` waives the object-level CRUD check for a lookup expansion,
2337
- * `__referentialFieldClear` the referential-clear write.
2382
+ * `__expandRead` marks a read as a lookup EXPANSION sub-read (it no longer
2383
+ * relaxes any gate — #7626 removed that waiver — but it still travels with
2384
+ * one operation and must not be inherited by another), `__referentialFieldClear`
2385
+ * authorizes the referential-clear write.
2338
2386
  *
2339
2387
  * plugin-security is the PRODUCER of that vocabulary and would be the most
2340
2388
  * honest owner of the rule for consuming it, but none of the three consumers
@@ -2641,6 +2689,30 @@ declare function withTransientRetry<T>(fn: (attempt: number) => Promise<T>, opts
2641
2689
  */
2642
2690
  declare function bulkWrite<TRow, TRecord = any>(rows: TRow[], opts: BulkWriteOptions<TRow, TRecord>): Promise<BulkWriteRowResult<TRecord>[]>;
2643
2691
 
2692
+ /**
2693
+ * Collect the names of fields declared `internal: true` on `schema`.
2694
+ *
2695
+ * Same verdicts as objectql's `collectInternalReadFields` (see the module
2696
+ * header for why it is restated rather than imported): strict `=== true`,
2697
+ * empty result for a missing/field-less schema.
2698
+ */
2699
+ declare function collectInternalWriteResponseFields(schema: unknown): string[];
2700
+ /**
2701
+ * Drop every `internal: true` field from a write response's record(s), in
2702
+ * place. THE single helper every external write mouth goes through — see the
2703
+ * module header; the three tripwires enforce the "every".
2704
+ *
2705
+ * @param schema The registered object schema (`engine.registry.getObject(...)`
2706
+ * / the protocol's own registry view / `metadataService
2707
+ * .getObject(...)`). An unknown object (no schema) strips
2708
+ * nothing — the write itself would have been refused upstream
2709
+ * by the object-existence gate.
2710
+ * @param records A single record, an array of records, or anything a write
2711
+ * mouth hands back where a record could sit (`null`, a count, a
2712
+ * boolean): non-objects are skipped, arrays are walked.
2713
+ */
2714
+ declare function omitInternalFieldsFromWriteResponse(schema: unknown, records: unknown): void;
2715
+
2644
2716
  /**
2645
2717
  * Can this runtime actually roll back? — the ADR-0119 D4 gate, shared.
2646
2718
  *
@@ -2934,6 +3006,59 @@ declare function resolveFilterTokens<T>(filter: T, ctx?: FilterTokenResolutionCo
2934
3006
  */
2935
3007
  declare function filterTokenContextFrom(execCtx: ExecutionContextLike | undefined, now?: Date): FilterTokenResolutionContext;
2936
3008
 
3009
+ /**
3010
+ * [#4435] The 404 a single-record operation answers when the id names no row.
3011
+ *
3012
+ * Extracted so the READ and the two WRITE paths cannot disagree about it. They
3013
+ * did: `getData` answered `404 RECORD_NOT_FOUND` while `updateData` returned
3014
+ * `200 { record: null }` and `deleteData` returned `200 { success: true }` for
3015
+ * any string in the path — so a typo'd id, an already-deleted row and a real
3016
+ * deletion were indistinguishable, and a client PATCHing a concurrently deleted
3017
+ * record was told its write had landed.
3018
+ *
3019
+ * That is the same silent-no-op shape the v17 train removed everywhere else
3020
+ * this window (#4240/#4303/#4315 refuse missing fields, #4169 refuses unknown
3021
+ * params, #4190 stopped dropping filters) — a write that touched zero rows
3022
+ * reporting 200 is that shape one level up, on the verb where it costs the
3023
+ * most.
3024
+ *
3025
+ * [#5138] EXPORTED, for the same "cannot disagree about it" reason one layer
3026
+ * out. `@objectstack/runtime`'s `callData` is protocol-first with an ObjectQL
3027
+ * FALLBACK, and the fallback had reinvented this fact three incompatible ways
3028
+ * (`get` → `null`, `update` → a bare `Error` with no status ⇒ 500, `delete` →
3029
+ * no check at all ⇒ `200 { deleted: true }` for a row that never existed). It
3030
+ * now calls THIS function, so the two paths behind one `callData` answer a
3031
+ * missing id identically — which is the only reason a caller may stop caring
3032
+ * which of them served it. Re-spelling the envelope there would have been a
3033
+ * second not-found envelope; `RECORD_NOT_FOUND` (#5088) is the one this repo
3034
+ * has.
3035
+ *
3036
+ * ── [#7867] Why it lives in `@objectstack/core` and not where it was written ──
3037
+ *
3038
+ * Because the THIRD path that needed it could not reach the second one. An
3039
+ * action body's `ctx.api.object(name).update({ id, … })` traverses neither
3040
+ * `protocol.updateData` nor `callData`: it reaches `ObjectQL.update()`'s by-id
3041
+ * branch directly, which had no existence gate at all, so a ghost id was a
3042
+ * silent no-op that then died on whatever the pipeline complained about first
3043
+ * (a `HookConditionError` 400 on a hooked object, a required-field
3044
+ * `VALIDATION_FAILED` 400 on an unhooked one — the 400 class varied with the
3045
+ * object's declarations; the missing 404 was the constant).
3046
+ *
3047
+ * The gate for that path belongs in the engine, and `packages/objectql` cannot
3048
+ * import `@objectstack/metadata-protocol` where this function was written:
3049
+ * ADR-0076 D2's boundary ratchet (`core-boundary.ratchet.test.ts`) forbids the
3050
+ * whole `@objectstack/objectql/core` closure — `engine.ts` included — from
3051
+ * pulling that package in. So the choice was a FOURTH spelling of the envelope
3052
+ * or one home both layers already depend on. #5138's own sentence rules the
3053
+ * first out, so this is the second: the factory moved down to the lowest
3054
+ * package the three producers share, and `@objectstack/metadata-protocol`
3055
+ * re-exports it unchanged for every existing importer.
3056
+ *
3057
+ * This is the same move `engineCanRollBack` made for the same reason — a fact
3058
+ * two layers must agree on lives in the layer beneath both, not in a copy each.
3059
+ */
3060
+ declare function recordNotFoundError(object: string, id: string | number): Error;
3061
+
2937
3062
  /**
2938
3063
  * In-memory Map-backed cache fallback.
2939
3064
  *
@@ -3069,7 +3194,24 @@ declare function createMemoryI18n(): {
3069
3194
  * not a merge — so deleted items/keys stop resolving on the next sync.
3070
3195
  */
3071
3196
  replaceAuthoredTranslations(byLocale: Record<string, Record<string, unknown>>): void;
3197
+ /**
3198
+ * Report the locales this stack offers.
3199
+ *
3200
+ * [#7679] When the app declared `i18n.supportedLocales`, that declaration
3201
+ * IS the answer — in declared order, and including a declared locale no
3202
+ * bundle was ever loaded for (declared-but-unserved). Reporting the
3203
+ * declaration rather than an intersection is what gives a client the
3204
+ * signal that the locale it is being offered has nothing behind it yet;
3205
+ * quietly dropping it would leave the gap invisible on both sides. It is
3206
+ * also the only answer that does not depend on how much had loaded by the
3207
+ * time this was called.
3208
+ *
3209
+ * With nothing declared, the loaded set — the behaviour every app that
3210
+ * never opted in already has.
3211
+ */
3072
3212
  getLocales(): string[];
3213
+ /** @see II18nService.setSupportedLocales — [#7679] */
3214
+ setSupportedLocales(locales: readonly string[] | undefined): void;
3073
3215
  getDefaultLocale(): string;
3074
3216
  setDefaultLocale(locale: string): void;
3075
3217
  };
@@ -3080,6 +3222,13 @@ declare function createMemoryI18n(): {
3080
3222
  * Implements the IMetadataService contract with a simple Map-of-Maps store.
3081
3223
  * Used by ObjectKernel as an automatic fallback when no real metadata plugin
3082
3224
  * (e.g. MetadataPlugin with file-system persistence) is registered.
3225
+ *
3226
+ * [#7378] Carries the ruled register/read argument contract
3227
+ * (`../metadata-service-contract.ts` — the ruling is quoted there):
3228
+ * `register` refuses a `data.name` that disagrees with the `name` argument and
3229
+ * refuses a non-document `data` (rows 1/3), and every type store is keyed on
3230
+ * the CANONICAL type (row 2), so `register('objects', n, d)` and
3231
+ * `get('object', n)` address one store rather than two.
3083
3232
  */
3084
3233
  declare function createMemoryMetadata(): {
3085
3234
  __serviceInfo: {
@@ -3133,6 +3282,37 @@ declare function wireAuthoredTranslationSync(ctx: MinimalCtx): void;
3133
3282
  */
3134
3283
  declare const CORE_FALLBACK_FACTORIES: Record<string, () => Record<string, any>>;
3135
3284
 
3285
+ /**
3286
+ * The canonical spelling an `IMetadataService` type store is keyed on
3287
+ * (#7378 row 2). Folds a plural manifest spelling to the singular metadata
3288
+ * type name (`'objects'` → `'object'`, `'views'` → `'view'`, …) through the
3289
+ * platform's one plural↔singular map (`PLURAL_TO_SINGULAR`,
3290
+ * `@objectstack/spec/shared`); a name with no plural mapping — which includes
3291
+ * every canonical singular type — passes through unchanged.
3292
+ */
3293
+ declare function canonicalMetadataServiceType(type: string): string;
3294
+ /**
3295
+ * Enforce rows 1 and 3 of the #7378 ruling on a
3296
+ * `register(type, name, data)` payload — call it before the first store write,
3297
+ * so a refusal writes nothing anywhere.
3298
+ *
3299
+ * Refuses, with a locating `VALIDATION_ERROR` (status 400):
3300
+ *
3301
+ * - **a non-document `data`** (row 3): anything that is not a plain object —
3302
+ * primitives, `null`, arrays. The contract declares `data: unknown`, so
3303
+ * this is a runtime refusal, not a type error;
3304
+ * - **a `data.name` that disagrees with the `name` argument** (row 1), in
3305
+ * either direction. A document with NO `name` of its own is fine — the
3306
+ * argument is the key, and there is no disagreement to refuse.
3307
+ *
3308
+ * Deliberately NOT called by `registerInMemory`: that optional member is a
3309
+ * boot-time seeding primitive outside the ruled surface (the ruling names
3310
+ * `register`), and its callers hand it artefacts whose shape source control
3311
+ * owns. It shares the row-2 canonical fold — a store key is a store fact, not
3312
+ * a per-member choice — just not the refusals.
3313
+ */
3314
+ declare function assertMetadataRegisterContract(type: string, name: string, data: unknown): asserts data is Record<string, unknown>;
3315
+
3136
3316
  /**
3137
3317
  * Plugin Health Monitor
3138
3318
  *
@@ -3450,4 +3630,4 @@ declare class NamespaceResolver {
3450
3630
  private suggestAlternative;
3451
3631
  }
3452
3632
 
3453
- export { ANONYMOUS_DENY_BODY, ANONYMOUS_DENY_CODE, ANONYMOUS_DENY_MESSAGE, ANONYMOUS_DENY_STATUS, API_KEY_PREFIX, type AnonymousDenyInput, type ApiKeyPrincipal, type AuthGate, type BucketGranularity, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, ENTRY_EXECUTION_CONTEXT_FIELDS, type EngineWithTransaction, type EntryExecutionContextField, type EntryLocalization, type ExecutionContextAssemblyInput, type ExecutionContextEntryFields, type ExecutionContextLike, type FilterTokenResolutionContext, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, type InterruptedRun, type KernelState, type KeyInput, type LadderPrincipal, type LadderRow, LiteKernel, type MigrationChunk, type MigrationChunkContext, MigrationJournalRefusal, type MigrationPlan, type MigrationPlanProvider, MigrationPlanRegistry, type MigrationPlanStep, type MigrationRunResult, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, type OAuthTokenProvenance, OPERATION_PRIVATE_KEY_PREFIX, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type OrderablePlugin, POSTURE_INJECTION_RULE, POSTURE_LADDER, POSTURE_RANK, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PostureEvidence, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolveUserAuthzGrantsOptions, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, type RunMigrationJournalOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, UnknownFilterTokenError, UnresolvedFilterTokenError, type UserAuthzGrants, type VersionCompatibility, assembleExecutionContext, assembleExecutionContextOrGuest, assertInitServiceRequirements, bucketKeyToCalendarRange, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, counterSignPayload, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, derivePosture, describeInitOrderFault, engineCanRollBack, evaluateAuthGate, extractApiKey, filterTokenContextFrom, findInterruptedRuns, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, hashMigrationPlan, isAuthGateAllowlisted, isExpired, isGrantActive, isGrantExpired, isNode, normalizeAuthGate, parseScopes, parseSignature, planChunks, postureVisibleRows, readAuthoredTranslationLayer, readRunJournal, resolveApiKeyPrincipal, resolveAuthzContext, resolveFilterToken, resolveFilterTokens, resolveLocale, resolveLocalizationContext, resolvePluginOrder, resolveUserAuthzGrants, resumeMigrationJournal, runMigrationJournal, safeExit, shouldDenyAnonymous, signPayload, validateInitServiceContract, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry, withoutOperationPrivateKeys, zonedDateStartToUtcMs };
3633
+ export { ANONYMOUS_DENY_BODY, ANONYMOUS_DENY_CODE, ANONYMOUS_DENY_MESSAGE, ANONYMOUS_DENY_STATUS, API_KEY_PREFIX, AUDIENCE_BINDING_SUGGESTION_STATUSES, AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES, type AnonymousDenyInput, type ApiKeyPrincipal, type AudienceBindingSuggestionStatus, type AuthGate, type BucketGranularity, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, ENTRY_EXECUTION_CONTEXT_FIELDS, type EngineWithTransaction, type EntryExecutionContextField, type EntryLocalization, type ExecutionContextAssemblyInput, type ExecutionContextEntryFields, type ExecutionContextLike, type FilterTokenResolutionContext, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, type InterruptedRun, type KernelState, type KeyInput, type LadderPrincipal, type LadderRow, LiteKernel, type MigrationChunk, type MigrationChunkContext, MigrationJournalRefusal, type MigrationPlan, type MigrationPlanProvider, MigrationPlanRegistry, type MigrationPlanStep, type MigrationRunResult, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, type OAuthTokenProvenance, OPERATION_PRIVATE_KEY_PREFIX, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, type OrderablePlugin, POSTURE_INJECTION_RULE, POSTURE_LADDER, POSTURE_RANK, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type Plugin, type PluginArtifactVerifyResult, PluginConfigValidator, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, PluginSecurityScanner, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PostureEvidence, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolveUserAuthzGrantsOptions, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, type RunMigrationJournalOptions, SIGNATURE_ALG, type SandboxContext, type ScanTarget, SecurePluginContext, type SecurityIssue, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, UnknownFilterTokenError, UnresolvedFilterTokenError, type UserAuthzGrants, type VersionCompatibility, assembleExecutionContext, assembleExecutionContextOrGuest, assertInitServiceRequirements, assertMetadataRegisterContract, bucketKeyToCalendarRange, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, canonicalMetadataServiceType, collectInternalWriteResponseFields, counterSignPayload, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginConfigValidator, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, derivePosture, describeInitOrderFault, engineCanRollBack, evaluateAuthGate, extractApiKey, filterTokenContextFrom, findInterruptedRuns, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hashApiKey, hashMigrationPlan, isAudienceBindingSuggestionStatus, isAuthGateAllowlisted, isExpired, isGrantActive, isGrantExpired, isNode, normalizeAuthGate, omitInternalFieldsFromWriteResponse, parseScopes, parseSignature, planChunks, postureVisibleRows, readAuthoredTranslationLayer, readRunJournal, recordNotFoundError, resolveApiKeyPrincipal, resolveAuthzContext, resolveFilterToken, resolveFilterTokens, resolveLocale, resolveLocalizationContext, resolvePluginOrder, resolveUserAuthzGrants, resumeMigrationJournal, runMigrationJournal, safeExit, shouldDenyAnonymous, signPayload, unknownAudienceBindingSuggestionStatusMessage, validateInitServiceContract, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry, withoutOperationPrivateKeys, zonedDateStartToUtcMs };