@ionite/server 0.0.23-beta.20260812.6 → 0.0.23-beta.20260820.2

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +250 -189
  2. package/dist/index.js +12114 -1
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ConfigChangeCallback, ConfigSource as ConfigSource9, FrameworkConfigInput, FrameworkStores as FrameworkStores2, Ionite as Ionite5, ModifiableFrameworkConfig, RemoteConfig as RemoteConfig2, RemoteConfigRetryHook, RemoteConfigRetryOptions, RoutingOptions as RoutingOptions2 } from "@ionite/core";
2
- import { ApplicationValidators, BaseTenant, CreateTenantRequest, Ionite, TenantStore, TenantValidators, UpdateTenantRequest, Workload } from "@ionite/core";
1
+ import { ConfigChangeCallback, ConfigSource as ConfigSource9, FrameworkConfigInput, FrameworkStores as FrameworkStores2, Ionite as Ionite6, ModifiableFrameworkConfig, RemoteConfig as RemoteConfig3, RemoteConfigRetryHook, RemoteConfigRetryOptions, RoutingOptions as RoutingOptions2 } from "@ionite/core";
2
+ import { ApplicationValidators, BaseTenant as BaseTenant2, CreateTenantRequest, Ionite as Ionite2, TenantStore as TenantStore2, TenantValidators, UpdateTenantRequest, Workload } from "@ionite/core";
3
3
  import { CapabilityEndpointUrls } from "@ionite/core";
4
4
  /**
5
5
  * Deterministic set of ionite endpoint paths derived from a single `basePath`.
@@ -13,14 +13,47 @@ type UrlMap = CapabilityEndpointUrls;
13
13
  * by module construction, the router, the readiness endpoint, and tenant-manager responses.
14
14
  */
15
15
  declare function deriveIonUrls(basePath: string): UrlMap;
16
+ import { BaseTenant, ConfigLocator, Ionite, LfvCallbackKind, Logger, RemoteConfig as RemoteConfig2, Secret, SecretsSource, TenantStore } from "@ionite/core";
17
+ type TenantMirrorHooks<TTenant extends BaseTenant = BaseTenant> = {
18
+ onRemoteConfigChange?(tenant: TTenant, config: RemoteConfig2, secret: Secret<Record<string, unknown>>): void | Promise<void>;
19
+ onRemoteConfigRevoke?(tenant: TTenant): void | Promise<void>;
20
+ };
21
+ type TenantMirrorOptions<TTenant extends BaseTenant = BaseTenant> = {
22
+ store: TenantStore<TTenant>;
23
+ /** App-owned durable mirror destination. */
24
+ to: SecretsSource;
25
+ /** Resolve a unique destination path for each tenant. */
26
+ path: (tenant: TTenant) => string;
27
+ hooks?: TenantMirrorHooks<TTenant>;
28
+ /** Overrides the root ion logger for tenant mirror operations. */
29
+ logger?: Logger;
30
+ /** Optional source factory for non-LFV locators. */
31
+ sourceFromLocator?: (locator: ConfigLocator, tenant: TTenant) => SecretsSource;
32
+ };
33
+ type TenantMirror = {
34
+ /**
35
+ * Blocks until the first mirror for this tenant lands. With no timeout it waits indefinitely;
36
+ * pass `timeout > 0` to reject after that many milliseconds.
37
+ */
38
+ ensure(tenantId: string, timeout?: number): Promise<void>;
39
+ handleCallback(tenantId: string, kind: LfvCallbackKind, request: Request): Promise<Response>;
40
+ purge(tenantId: string): Promise<void>;
41
+ close(): Promise<void>;
42
+ };
43
+ /**
44
+ * Maintains per-tenant RemoteConfig mirrors. Tenant records own the upstream locators; app code owns
45
+ * the destination source and path mapping.
46
+ */
47
+ declare function tenantMirror<TTenant extends BaseTenant = BaseTenant>(ion: Ionite, options: TenantMirrorOptions<TTenant>): TenantMirror;
16
48
  type TenantManagerOptions<
17
49
  TCreateTenantRequest extends CreateTenantRequest = CreateTenantRequest,
18
50
  TUpdateTenantRequest extends UpdateTenantRequest = UpdateTenantRequest,
19
- TTenant extends BaseTenant = BaseTenant
51
+ TTenant extends BaseTenant2 = BaseTenant2
20
52
  > = {
21
53
  validators: ApplicationValidators<TenantValidators<TCreateTenantRequest, TUpdateTenantRequest>>;
22
54
  basePath: string;
23
- store: TenantStore<TTenant>;
55
+ store: TenantStore2<TTenant>;
56
+ mirror?: Pick<TenantMirror, "purge">;
24
57
  workloadAuth?: Workload;
25
58
  /**
26
59
  * Resolve the ionite `basePath` for a given tenant (e.g. `/api/${tenant.id}/ionite`).
@@ -35,20 +68,20 @@ type TenantIonUrls = {
35
68
  callbackUrl: string;
36
69
  ionUrls: UrlMap;
37
70
  };
38
- type TenantManager<TTenant extends BaseTenant = BaseTenant> = {
71
+ type TenantManager<TTenant extends BaseTenant2 = BaseTenant2> = {
39
72
  handler(request: Request): Promise<Response>;
40
73
  getTenant(id: string): Promise<TTenant | undefined>;
41
74
  };
42
75
  declare function tenantManager<
43
76
  TCreateTenantRequest extends CreateTenantRequest = CreateTenantRequest,
44
77
  TUpdateTenantRequest extends UpdateTenantRequest = UpdateTenantRequest,
45
- TTenant extends BaseTenant = BaseTenant
46
- >(ion: Ionite, options: TenantManagerOptions<TCreateTenantRequest, TUpdateTenantRequest, TTenant>): TenantManager<TTenant>;
78
+ TTenant extends BaseTenant2 = BaseTenant2
79
+ >(ion: Ionite2, options: TenantManagerOptions<TCreateTenantRequest, TUpdateTenantRequest, TTenant>): TenantManager<TTenant>;
47
80
  import { CapabilityKey as CapabilityKey2 } from "@ionite/core";
48
81
  export * from "@ionite/core";
49
82
  import { AccessCheckReason, AccessCheckResult, CreateTenantRequest as CreateTenantRequest2, EnvironmentType, FrameworkOtelConfig, FrameworkStores as FrameworkStores3, generateULID, IoniteError, IoniteErrorOptions, listGenerator, Otel, OtelConfig, OtelLevels, OtelLogLevel, OtelLogRecord, OtelMetricsSignalConfig, OtelOAuthClientCredentialsConfig, OtelProviderType, OtelSignalConfig, SubjectScope, SubjectType as SubjectType3, TenantResponse, TenantStatus, TenantValidators as TenantValidators2, TenantWebhookPayload, UpdateTenantRequest as UpdateTenantRequest2 } from "@ionite/core";
50
83
  import { AfterLoginContext, AfterLoginHook, AfterLogoutContext, AfterLogoutHook, BeforeLoginContext, BeforeLoginHook, BeforeLogoutContext, BeforeLogoutHook, CatalogView, ReconcileStores, RedirectContext, RedirectPolicy, RedirectResult, RedirectRule, RedirectRuleContext, RedirectVerdict, ReferencedDefinitions } from "@ionite/core/server";
51
- import { allowHosts, allowOrigins, allowRelativePaths, allowSameOrigin, blockDangerousUrls, CatalogAdjacencyCache, callback, captureRedirect, ciam, collectReferencedDefinitions, defaultRedirectPolicies, discoverSessionRecords, discoverSessions, expandRoot, getCustomer, getUser, has, hasAll as hasAll2, hasAllScope, hasAny as hasAny2, hasAnyScope, hasGroup as hasGroup2, hasPermission as hasPermission2, hasRole as hasRole2, hasScope, InMemoryTenantStore, iam, initiateLogin, isRedirectAllowed, listSsoClientIdsFromCookies, reconcileSubjectAccess, resolveAfterRedirect, resolveCapturedRedirect, resolveRedirect, SessionDiscoveryOptions, SessionResponse, sameOriginRedirectRules, sendTenantWebhook, sso, VerifyUserOptions, verifyUser, withDefaultExternalId, withSetCookies } from "@ionite/core/server";
84
+ import { allowHosts, allowOrigins, allowRelativePaths, allowSameOrigin, blockDangerousUrls, CatalogAdjacencyCache, callback, captureRedirect, ciam, collectReferencedDefinitions, defaultRedirectPolicies, discoverSessionRecords, discoverSessions, expandRoot, getCustomer, getUser, has, hasAll as hasAll2, hasAllScope, hasAny as hasAny2, hasAnyScope, hasGroup as hasGroup2, hasPermission as hasPermission2, hasRole as hasRole2, hasScope, InMemoryTenantStore, iam, initiateLogin, isRedirectAllowed, listSsoClientIdsFromCookies, reconcileSubjectAccess, resolveAfterRedirect, resolveCapturedRedirect, resolveRedirect, SessionDiscoveryOptions, SessionResponse, sameOriginRedirectRules, sendTenantWebhook, sso, VerifyUserOptions, verifyUser, withSetCookies } from "@ionite/core/server";
52
85
  import { AccessAssignmentStore as AccessAssignmentStore2, AccessChange, ListOptions, ListResult, OaaAccessTargetType, SubjectType } from "@ionite/core";
53
86
  /**
54
87
  * In-memory store of granted access **roots** (source of truth). Roots are keyed by their
@@ -90,23 +123,14 @@ declare class InMemoryAccessCatalogStore implements AccessCatalogStore2 {
90
123
  * Writable, in-memory {@link ResourceProvider} for zero-DB quickstarts, dev tools, and validation.
91
124
  * Real applications should implement `ResourceProvider` directly over their own database/ORM (the
92
125
  * resources already live there) — this store exists so an app with no database yet can still model
93
- * resources and resource-derived entitlements without one.
126
+ * resources without one.
94
127
  *
95
128
  * `set`/`delete` emit the `changed` signal the SDK subscribes to (adjacency-cache invalidation,
96
- * targeted reconcile, incremental OAA projection). Provide `deriveEntitlements` (plus its reverse
97
- * resolver `resolveEntitlement`) to expose resource-derived entitlement Groups through this provider.
129
+ * targeted reconcile, incremental OAA projection).
98
130
  */
99
131
  declare class InMemoryResourceStore implements ResourceProvider2 {
100
132
  private readonly items;
101
133
  private readonly listeners;
102
- constructor(options?: {
103
- /** Pure derivation of a resource's requestable entitlement Groups (see {@link ResourceProvider.entitlements}). */
104
- deriveEntitlements?: (resource: Resource) => Group[];
105
- /** Reverse resolution of a resource-derived entitlement id (see {@link ResourceProvider.entitlement}). */
106
- resolveEntitlement?: (id: string, get: (resourceId: string) => Resource | undefined) => Group | undefined;
107
- });
108
- entitlements?: (resource: Resource) => Group[];
109
- entitlement?: (id: string) => Promise<Group | undefined>;
110
134
  get(id: string): Promise<Resource | undefined>;
111
135
  list(options?: ListOptions2): Promise<ListResult2<Resource>>;
112
136
  children(id: string): Promise<Resource[]>;
@@ -163,9 +187,9 @@ declare class InMemoryAccessIndex implements AccessIndex2 {
163
187
  private dropEdge;
164
188
  private removeFromSet;
165
189
  }
166
- import { AwsSecretsConfig, ConfigSource, SecretsSource } from "@ionite/core";
190
+ import { AwsSecretsConfig, ConfigSource, SecretsSource as SecretsSource2 } from "@ionite/core";
167
191
  type AwsConfigSourceOptions = Omit<AwsSecretsConfig, "type"> & {
168
- vault?: SecretsSource;
192
+ vault?: SecretsSource2;
169
193
  ttl?: number;
170
194
  };
171
195
  /**
@@ -176,9 +200,9 @@ type AwsConfigSourceOptions = Omit<AwsSecretsConfig, "type"> & {
176
200
  * then throwing at first config access.
177
201
  */
178
202
  declare function awsConfig(_config: AwsConfigSourceOptions): ConfigSource;
179
- import { AzureSecretsConfig, ConfigSource as ConfigSource2, SecretsSource as SecretsSource2 } from "@ionite/core";
203
+ import { AzureSecretsConfig, ConfigSource as ConfigSource2, SecretsSource as SecretsSource3 } from "@ionite/core";
180
204
  type AzureConfigSourceOptions = Omit<AzureSecretsConfig, "type"> & {
181
- vault?: SecretsSource2;
205
+ vault?: SecretsSource3;
182
206
  path?: string;
183
207
  };
184
208
  /**
@@ -187,22 +211,51 @@ type AzureConfigSourceOptions = Omit<AzureSecretsConfig, "type"> & {
187
211
  * If ttl is set, the vault is polled every ttl milliseconds (minimum 10 minutes) and onConfig is called when config changes.
188
212
  */
189
213
  declare function azureConfig(config: AzureConfigSourceOptions): ConfigSource2;
190
- import { ConfigLocator, ConfigSource as ConfigSource3, ConfigSourceEnv, ConfigSourceType } from "@ionite/core";
214
+ import { ConfigLocator as ConfigLocator2, ConfigSource as ConfigSource3, SecretsSource as SecretsSource4 } from "@ionite/core";
215
+ /**
216
+ * Materialize a runtime {@link ConfigSource} from a full, self-contained {@link ConfigLocator}. This
217
+ * is the ROOT/bootstrap path (env vars via `envConfig()`, or a bootstrap secret via
218
+ * `secretConfigSource()`): the locator carries the connection details/credentials needed to build a
219
+ * fresh source. To reuse a source already connected on an Ionite instance, see
220
+ * {@link configFromSource}.
221
+ */
222
+ declare function configSourceFromLocator(locator: ConfigLocator2): ConfigSource3;
223
+ /** Optional knobs for {@link configFromSource}. */
224
+ type ConfigFromSourceOptions = {
225
+ /** Polling interval fallback when the source has no native subscription support. */
226
+ ttl?: number;
227
+ };
228
+ /**
229
+ * Materialize a ConfigSource for the RemoteConfig document at `path`, read through an
230
+ * already-connected {@link SecretsSource} — typically the root default client (`ion.secret`) or a
231
+ * named source (`ion.secrets.getSecretsSource('name')`), which may point at a completely different
232
+ * vault than the one serving the root config. Unlike {@link configSourceFromLocator}, this carries
233
+ * no connection details or credentials, and every caller shares the source's live client (one
234
+ * vault socket for N tenants). The document at `path` is the RemoteConfig itself; for a path that
235
+ * stores a `ConfigLocator` pointer instead, use `secretConfigSource`.
236
+ *
237
+ * Canonical tenant-runtime constructor: direct/internal apps map the stored vault locator's
238
+ * `vaultPath`/`vaultTtl`; OEM mirror apps pass their app-derived mirror path. INVARIANT: each tenant
239
+ * MUST resolve to a distinct backing path — two tenants sharing a path would cross-load each
240
+ * other's RemoteConfig.
241
+ */
242
+ declare function configFromSource(source: SecretsSource4, path: string, options?: ConfigFromSourceOptions): ConfigSource3;
243
+ import { ConfigLocator as ConfigLocator3, ConfigSource as ConfigSource4, ConfigSourceEnv, ConfigSourceType } from "@ionite/core";
191
244
  type EnvConfigOptions = {
192
245
  /** Override config source type (default: ION_CONFIG_TYPE from env). */
193
246
  type?: ConfigSourceType;
194
247
  };
195
- declare function configLocatorFromEnvValues(env: Partial<ConfigSourceEnv>, options?: EnvConfigOptions): ConfigLocator;
248
+ declare function configLocatorFromEnvValues(env: Partial<ConfigSourceEnv>, options?: EnvConfigOptions): ConfigLocator3;
196
249
  /**
197
250
  * Creates a ConfigSource from environment variables.
198
251
  * Reads ION_CONFIG_TYPE to choose the source.
199
252
  * For each supported type, it merges the options with available environment variables.
200
253
  */
201
- declare function configSourceFromEnvValues(env: Partial<ConfigSourceEnv>, options?: EnvConfigOptions): ConfigSource3;
202
- declare function envConfig(options?: EnvConfigOptions): ConfigSource3;
203
- import { ConfigSource as ConfigSource4, GcpSecretsConfig, SecretsSource as SecretsSource3 } from "@ionite/core";
254
+ declare function configSourceFromEnvValues(env: Partial<ConfigSourceEnv>, options?: EnvConfigOptions): ConfigSource4;
255
+ declare function envConfig(options?: EnvConfigOptions): ConfigSource4;
256
+ import { ConfigSource as ConfigSource5, GcpSecretsConfig, SecretsSource as SecretsSource5 } from "@ionite/core";
204
257
  type GcpConfigSourceOptions = Omit<GcpSecretsConfig, "type"> & {
205
- vault?: SecretsSource3;
258
+ vault?: SecretsSource5;
206
259
  ttl?: number;
207
260
  };
208
261
  /**
@@ -212,8 +265,53 @@ type GcpConfigSourceOptions = Omit<GcpSecretsConfig, "type"> & {
212
265
  * startup) so a `type: 'gcp'` locator fails fast with a clear error rather than type-checking and
213
266
  * then throwing at first config access.
214
267
  */
215
- declare function gcpConfig(_config: GcpConfigSourceOptions): ConfigSource4;
216
- import { ConfigSource as ConfigSource5, SecretsSource as SecretsSource4 } from "@ionite/core";
268
+ declare function gcpConfig(_config: GcpConfigSourceOptions): ConfigSource5;
269
+ import { ConfigLocator as ConfigLocator4, ConfigSource as ConfigSource6, LfvCallbackKind as LfvCallbackKind2, Logger as Logger3, SecretsSource as SecretsSource7 } from "@ionite/core";
270
+ import { Logger as Logger2, Secret as Secret2, SecretEvent, SecretsSource as SecretsSource6, SecretsSubscriptionOptions } from "@ionite/core";
271
+ type MirrorSecretsOptions = {
272
+ from: SecretsSource6;
273
+ to: SecretsSource6;
274
+ paths: readonly string[];
275
+ mapPath: (path: string) => string;
276
+ /** Optional admission check. Rejected values are ignored without changing the current mirror. */
277
+ accept?: (secret: Secret2<Record<string, unknown>>, sourcePath: string) => boolean;
278
+ subscription?: SecretsSubscriptionOptions;
279
+ logger?: Logger2;
280
+ /** Receives every source lifecycle event after the mirror schedules its required state change. */
281
+ onEvent?: (event: SecretEvent) => void;
282
+ };
283
+ type SecretsMirror = {
284
+ isReady(): boolean;
285
+ ready(timeout?: number): Promise<void>;
286
+ isAvailable(): boolean;
287
+ /** Delete all configured target values. Explicit tenant-offboarding action. */
288
+ purge(): Promise<void>;
289
+ close(): Promise<void>;
290
+ };
291
+ /**
292
+ * Mirrors explicit secret paths from a source into a receiver-owned vault. Designed for OEM
293
+ * topologies: customer values arrive over LFV, then are durably re-stored under tenant-isolated
294
+ * paths before the receiver fans them out internally.
295
+ */
296
+ declare function mirrorSecrets(options: MirrorSecretsOptions): SecretsMirror;
297
+ type MirroredConfigOptions = {
298
+ from: ConfigLocator4 | SecretsSource7;
299
+ fromPath?: string;
300
+ to: ConfigLocator4 | SecretsSource7;
301
+ path: string;
302
+ logger?: Logger3;
303
+ ttl?: number;
304
+ };
305
+ type MirroredConfigSource = ConfigSource6 & {
306
+ handleCallback(kind: LfvCallbackKind2, request: Request): Promise<Response>;
307
+ mirror: SecretsMirror;
308
+ };
309
+ /**
310
+ * Mirrors one authoritative RemoteConfig into an App-owned secrets source, then exposes a
311
+ * ConfigSource which reads only that durable mirror.
312
+ */
313
+ declare function mirroredConfig(options: MirroredConfigOptions): MirroredConfigSource;
314
+ import { ConfigSource as ConfigSource7, SecretsSource as SecretsSource8 } from "@ionite/core";
217
315
  /**
218
316
  * Creates a ConfigSource from a SecretsSource path that stores a ConfigLocator.
219
317
  * The returned source rebinds subscriptions when the bootstrap secret changes.
@@ -224,10 +322,10 @@ import { ConfigSource as ConfigSource5, SecretsSource as SecretsSource4 } from "
224
322
  * bootstrap actually changes, the superseded inner source is disposed (its `secret.close()` is
225
323
  * invoked) before the new one is built, so config churn cannot leak duplicate connections.
226
324
  */
227
- declare function secretConfigSource(source: SecretsSource4, path: string): ConfigSource5;
228
- import { ConfigSource as ConfigSource6, SecretsSource as SecretsSource5, VaultSecretsConfig } from "@ionite/core";
325
+ declare function secretConfigSource(source: SecretsSource8, path: string): ConfigSource7;
326
+ import { ConfigSource as ConfigSource8, SecretsSource as SecretsSource9, VaultSecretsConfig } from "@ionite/core";
229
327
  type VaultConfigSourceOptions = Omit<VaultSecretsConfig, "type"> & {
230
- vault?: SecretsSource5;
328
+ vault?: SecretsSource9;
231
329
  path?: string;
232
330
  };
233
331
  declare class VaultConfigWaitingForSecretError extends Error {
@@ -256,7 +354,7 @@ declare function isVaultConfigInvalidPayloadError(error: unknown): error is Vaul
256
354
  * If ttl is set, the vault will be polled every ttl milliseconds (minimum 10 minutes) and onConfig will be called when the config changes.
257
355
  * When a custom vault client is provided, ttl is still honored for config subscription polling if the client does not support native subscribe().
258
356
  */
259
- declare function vaultConfig(config: VaultConfigSourceOptions): ConfigSource6;
357
+ declare function vaultConfig(config: VaultConfigSourceOptions): ConfigSource8;
260
358
  import { BaseCustomer, CustomerStore, ListOptions as ListOptions3, ListResult as ListResult3 } from "@ionite/core";
261
359
  /**
262
360
  * In-memory customer store implementation using Maps.
@@ -272,7 +370,7 @@ declare class InMemoryCustomerStore<TExtended = Record<string, never>> implement
272
370
  delete(id: string): Promise<number>;
273
371
  list(options?: ListOptions3): Promise<ListResult3<BaseCustomer<TExtended>>>;
274
372
  }
275
- import { AccessCatalogStore as AccessCatalogStore3, IamDeltaEmitter, IamDeltaIdMapStore as IamDeltaIdMapStore2, IamDeltaMode, Logger, ResourceProvider as ResourceProvider3, UserStore, Workload as Workload2 } from "@ionite/core";
373
+ import { AccessAssignmentStore as AccessAssignmentStore3, AccessCatalogStore as AccessCatalogStore3, BaseUser as BaseUser2, CodeCatalog as CodeCatalog2, IamDeltaEmitter, IamDeltaMode, Logger as Logger4, ScimUser, UserStore, Workload as Workload2, WorkloadIdentityStore as WorkloadIdentityStore2 } from "@ionite/core";
276
374
  type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
277
375
  /** RemoteConfig-derived destination descriptor for IAM delta egress. */
278
376
  type IamDeltaConfig = {
@@ -281,18 +379,18 @@ type IamDeltaConfig = {
281
379
  url?: string;
282
380
  /** Outgoing workload client name used to authenticate pushes (`IAMConfig.deltaAudience`). */
283
381
  audience?: string;
284
- /** Tenant scope for the mapping cache. */
285
- tenantId?: string;
286
382
  };
287
383
  /** Runtime capabilities the emitter binds to (resolved from the merged config/stores in buildES). */
288
384
  type IamDeltaDeps = {
289
385
  workload?: Workload2;
386
+ workloadIdentityStore?: WorkloadIdentityStore2;
290
387
  userStore?: UserStore;
388
+ accessStore?: AccessAssignmentStore3;
291
389
  catalogStore?: AccessCatalogStore3;
292
- /** Read-through provider for derived-entitlement resolution (externalId lookup on delta egress). */
293
- resources?: ResourceProvider3;
294
- /** `externalId -> provider id` mapping cache for outbound SCIM (defaults to in-memory). */
295
- idMapStore?: IamDeltaIdMapStore2;
390
+ /** Normalized code templates merged over persisted rows for outbound definitions. */
391
+ codeCatalog?: CodeCatalog2;
392
+ /** Optional app mapper shared with the inbound IAM Users read surface. */
393
+ mapUserToScim?: (stored: BaseUser2) => ScimUser | Promise<ScimUser>;
296
394
  /** Injectable fetch (defaults to global fetch); enables testing the patch path in-process. */
297
395
  fetchImpl?: FetchLike;
298
396
  };
@@ -301,32 +399,15 @@ type IamDeltaDeps = {
301
399
  * {@link IamDeltaEmitter} whose readiness promise is stable across RemoteConfig applies;
302
400
  * `update(config, deps)` reconfigures the destination/capabilities in place.
303
401
  *
304
- * `'patch'` emits externalId-only outbound SCIM into the IAM tool at the access-mutation
305
- * chokepoint (needs `url` + workload + an `idMapStore`, which defaults to in-memory). Every push is
402
+ * `'patch'` emits outbound SCIM into the IAM tool at the access-mutation
403
+ * chokepoint. Destination receipts are persisted directly on UserStore/AccessCatalogStore rows. Every push is
306
404
  * authenticated with the outgoing workload client, which the destination treats as the verified
307
405
  * origin. See the README "IAM delta egress" section.
308
406
  */
309
- declare function createManagedIamDelta(log: Logger): {
407
+ declare function createManagedIamDelta(log: Logger4): {
310
408
  update(config: IamDeltaConfig, deps: IamDeltaDeps): IamDeltaEmitter;
409
+ handle(): IamDeltaEmitter;
311
410
  };
312
- import { IamDeltaIdMapKey, IamDeltaIdMapStore as IamDeltaIdMapStore3 } from "@ionite/core";
313
- /**
314
- * Stable string key for an {@link IamDeltaIdMapKey}. Scoped by tenant + destination so the same
315
- * `externalId` can map to different provider ids across IAM tools and tenants. Shared by the
316
- * in-memory and Redis implementations to keep keying identical.
317
- */
318
- declare function iamDeltaIdMapKey(key: IamDeltaIdMapKey): string;
319
- /**
320
- * In-memory {@link IamDeltaIdMapStore}. Suitable for single-process apps and tests. Production
321
- * deployments should use a durable implementation (e.g. `RedisIamDeltaIdMapStore` or a SQL-backed
322
- * store) so the externalId -> provider-id cache survives restarts and is shared across instances.
323
- */
324
- declare class InMemoryIamDeltaIdMapStore implements IamDeltaIdMapStore3 {
325
- private readonly map;
326
- get(key: IamDeltaIdMapKey): Promise<string | undefined>;
327
- set(key: IamDeltaIdMapKey, providerId: string): Promise<void>;
328
- delete(key: IamDeltaIdMapKey): Promise<void>;
329
- }
330
411
  import { CapabilityKey, ModuleName } from "@ionite/core";
331
412
  /**
332
413
  * Version of the stable capability vocabulary emitted by capabilitiez and used by ECV result IDs.
@@ -419,7 +500,7 @@ declare class InMemoryMagicLinkStore<TExtended = Record<string, never>> implemen
419
500
  getAndDelete(token: string): Promise<MagicLink<TExtended> | null>;
420
501
  delete(token: string): Promise<void>;
421
502
  }
422
- import { Ionite as Ionite2, ResolvedRoute, RoutingOptions } from "@ionite/core";
503
+ import { Ionite as Ionite3, ResolvedRoute, RoutingOptions } from "@ionite/core";
423
504
  /**
424
505
  * Deny-by-default authorization gate for a resolved SDK route. Returns the 401/403 `Response` to
425
506
  * short-circuit with when the caller is not authorized, or `undefined` to proceed. Enforcement reuses
@@ -427,23 +508,23 @@ import { Ionite as Ionite2, ResolvedRoute, RoutingOptions } from "@ionite/core";
427
508
  * `RemoteConfig.authz.scopesAsEntitlements` is enabled) satisfies the gate; the `response()` already
428
509
  * logs the denial server-side without leaking the missing permission to the caller.
429
510
  */
430
- declare function enforceEndpointAuthz(request: Request, ion: Ionite2, required: NonNullable<ResolvedRoute["requiredPermission"]>): Promise<Response | undefined>;
511
+ declare function enforceEndpointAuthz(request: Request, ion: Ionite3, required: NonNullable<ResolvedRoute["requiredPermission"]>): Promise<Response | undefined>;
431
512
  /**
432
513
  * Resolve the default route for a request using the deterministic, basePath-derived endpoint paths.
433
514
  * Endpoint URLs are no longer read from per-module config; they are computed from `basePath`.
434
515
  */
435
- declare function resolveDefaultRoute(request: Request, ion: Ionite2, urls: UrlMap, pathname?: string): ResolvedRoute | undefined;
436
- declare function routeRequest(request: Request, ion: Ionite2, routing?: RoutingOptions, urls?: UrlMap): Promise<Response>;
437
- import { IamDeltaIdMapStore as IamDeltaIdMapStore4, IamDeltaResourceType, Logger as Logger2 } from "@ionite/core";
516
+ declare function resolveDefaultRoute(request: Request, ion: Ionite3, urls: UrlMap, pathname?: string): ResolvedRoute | undefined;
517
+ declare function routeRequest(request: Request, ion: Ionite3, routing?: RoutingOptions, urls?: UrlMap): Promise<Response>;
518
+ import { DestinationReference, GroupResource, IamDeltaResourceType, Logger as Logger5, ScimUser as ScimUser2 } from "@ionite/core";
438
519
  type FetchLike2 = (input: string, init?: RequestInit) => Promise<Response>;
439
520
  /**
440
- * Outcome of an outbound membership patch:
521
+ * Outcome of an outbound IAM delta operation:
441
522
  * - `'pushed'` — the destination accepted the mutation (2xx).
442
523
  * - `'skipped'` — the mutation was not attempted (subject/target not resolvable at the destination).
443
524
  * - `'error'` — the destination rejected the mutation (non-2xx); the caller surfaces this as a
444
525
  * degraded egress / reconcile error so it is never mistaken for success (§4.8/§19.1).
445
526
  */
446
- type ScimPatchOutcome = "pushed" | "skipped" | "error";
527
+ type ScimOutboundOutcome = "pushed" | "skipped" | "error";
447
528
  /**
448
529
  * Result of resolving a destination provider id. A lookup/create HTTP failure is `'error'`, NOT
449
530
  * `'absent'`: conflating the two would let a transient 401/500 masquerade as "no such resource",
@@ -454,24 +535,43 @@ type ScimPatchOutcome = "pushed" | "skipped" | "error";
454
535
  */
455
536
  type ProviderIdResolution = {
456
537
  found: string;
538
+ requestUrl?: string;
539
+ created?: true;
457
540
  } | "absent" | "error";
458
- /** Minimal create payload used only when the destination has no resource for an `externalId`. */
459
- type ScimOutboundCreate = {
460
- /** SCIM `userName` (required for Users) or unused for Groups. */
461
- userName?: string;
462
- /** SCIM `displayName` (required for Groups; optional for Users). */
463
- displayName?: string;
541
+ /** Full IAM-visible SCIM body used for create-on-empty and entity upsert. */
542
+ type ScimOutboundResource = ScimUser2 | GroupResource | (Record<string, unknown> & {
543
+ schemas?: string[];
544
+ id?: string;
545
+ externalId?: string;
546
+ meta?: unknown;
547
+ });
548
+ type ScimGroupMembershipPatch = {
549
+ groupExternalId: string;
550
+ userExternalId: string;
551
+ op: "add" | "remove";
552
+ groupCreate?: ScimOutboundResource;
553
+ userCreate?: ScimOutboundResource;
554
+ /** SCIM member kind; Workload is the ionite extension used by full IAM aggregation. */
555
+ memberType?: "User" | "Workload";
556
+ };
557
+ /**
558
+ * Row-backed receipt callbacks supplied by IAM delta. Group receipts are persisted on
559
+ * AccessCatalogStore rows and User receipts on UserStore rows; the outbound client has no separate
560
+ * destination-qualified mapping store.
561
+ */
562
+ type ScimOutboundReceiptCallbacks = {
563
+ read(resourceType: IamDeltaResourceType, externalId: string): Promise<DestinationReference | undefined>;
564
+ write(resourceType: IamDeltaResourceType, externalId: string, reference: DestinationReference): Promise<void>;
565
+ clear(resourceType: IamDeltaResourceType, externalId: string): Promise<void>;
464
566
  };
465
567
  type ScimOutboundClientOptions = {
466
568
  /** Destination SCIM base URL (e.g. https://iam.example.com/scim/v2). */
467
569
  baseUrl: string;
468
570
  /** Mints a bearer token for the destination audience (workload outgoing client). */
469
571
  getToken: () => Promise<string>;
470
- /** Durable externalId -> provider-id cache (required). */
471
- idMapStore: IamDeltaIdMapStore4;
472
- /** Tenant scope for the mapping cache. */
473
- tenantId?: string;
474
- log: Logger2;
572
+ /** Reads and writes destination receipts on the source User/AccessCatalogStore rows. */
573
+ receipts: ScimOutboundReceiptCallbacks;
574
+ log: Logger5;
475
575
  /** Injectable fetch (defaults to global fetch); enables testing against a mock SCIM server. */
476
576
  fetchImpl?: FetchLike2;
477
577
  };
@@ -484,54 +584,72 @@ type ScimOutboundClientOptions = {
484
584
  */
485
585
  declare function escapeScimFilterValue(value: string): string;
486
586
  /**
487
- * externalId-only outbound SCIM client for IAM delta `'patch'` egress.
587
+ * Outbound SCIM client for IAM delta `'patch'` egress. Its correlation argument is always written
588
+ * to SCIM `externalId` (a catalog `id` for entitlements or a User `externalId` for users).
488
589
  *
489
590
  * Resolves a destination provider id for a resource STRICTLY by `externalId` (never email,
490
- * employeeId, samAccountName, or any custom attribute), backed by a durable mapping cache:
591
+ * employeeId, samAccountName, or any custom attribute), backed by row receipts plus a process memo:
491
592
  *
492
593
  * - cache hit -> use the stored provider id
493
594
  * - miss -> `GET /{Resource}?filter=externalId eq "..."` -> store + use the returned id
494
- * - empty -> `POST /{Resource}` (create) -> store + use the returned id
595
+ * - empty -> `POST /{Resource}` with the full body -> store + use the returned id
596
+ * - known -> `PUT`, membership `PATCH`, or `DELETE`
495
597
  * - stale (404/410 on a subsequent write) -> drop the mapping, re-resolve, retry once
496
598
  *
497
- * Concurrent resolutions for the same `(destination, resourceType, externalId)` are single-flighted.
599
+ * Concurrent resolutions for the same `(resourceType, externalId)` are single-flighted.
498
600
  */
499
601
  declare class ScimOutboundClient {
500
602
  private readonly baseUrl;
501
603
  private readonly getToken;
502
- private readonly idMapStore;
503
- private readonly tenantId?;
604
+ private readonly receipts;
504
605
  private readonly log;
505
606
  private readonly fetchImpl;
506
607
  private readonly inflight;
608
+ private readonly memo;
609
+ private readonly writes;
507
610
  constructor(options: ScimOutboundClientOptions);
508
611
  private headers;
509
612
  private inflightKey;
613
+ private receiptKey;
614
+ private serializeWrite;
510
615
  /**
511
616
  * Resolve (or create) the destination provider id for a resource identified by `externalId`.
512
617
  * Returns a discriminated {@link ProviderIdResolution}: a confirmed id, `'absent'` (destination has
513
618
  * no such resource and no `create` was supplied/succeeded), or `'error'` (lookup/create failed).
514
619
  */
515
- resolveProviderId(resourceType: IamDeltaResourceType, externalId: string, create?: ScimOutboundCreate): Promise<ProviderIdResolution>;
620
+ resolveProviderId(resourceType: IamDeltaResourceType, externalId: string, create?: ScimOutboundResource): Promise<ProviderIdResolution>;
516
621
  private resolveUncached;
517
622
  private filterByExternalId;
518
623
  private create;
624
+ private requestUrl;
625
+ private captureResponseReference;
519
626
  /** Drop a possibly-stale mapping so the next resolve re-filters the destination. */
520
627
  private invalidate;
628
+ /** Remove provider-owned fields and force the externalId-only correlation key into a write body. */
629
+ private writeBody;
630
+ /**
631
+ * Create or replace one full SCIM User/Group strictly by externalId. A stale cached provider id is
632
+ * invalidated and resolved once; a confirmed absence creates the resource with the full body.
633
+ */
634
+ upsertResource(resourceType: IamDeltaResourceType, externalId: string, resource: ScimOutboundResource): Promise<ScimOutboundOutcome>;
635
+ private upsertResourceNow;
636
+ /**
637
+ * Delete one destination SCIM resource strictly by externalId. Confirmed absence and destination
638
+ * 404/410 are idempotent success; lookup/auth failures remain degraded egress.
639
+ */
640
+ deleteResource(resourceType: IamDeltaResourceType, externalId: string): Promise<ScimOutboundOutcome>;
641
+ private deleteResourceNow;
521
642
  /**
522
643
  * Add or remove a user (by `userExternalId`) from a group (by `groupExternalId`) at the destination.
523
644
  * Resolves both ids by externalId, issues a SCIM PATCH, and self-heals once on a stale group id.
524
645
  */
525
- patchGroupMembership(args: {
526
- groupExternalId: string;
527
- userExternalId: string;
528
- op: "add" | "remove";
529
- groupCreate?: ScimOutboundCreate;
530
- userCreate?: ScimOutboundCreate;
531
- }): Promise<ScimPatchOutcome>;
646
+ patchGroupMembership(args: ScimGroupMembershipPatch): Promise<ScimOutboundOutcome>;
647
+ private patchGroupMembershipNow;
532
648
  }
533
- import { LfvCallbackTransport, SecretsSource as SecretsSource6, VaultLfvSecretsConfig } from "@ionite/core";
534
- type LfvSecretsSource = SecretsSource6 & {
649
+ import { LfvCallbackTransport, Secret as Secret3, SecretsSource as SecretsSource10, VaultLfvSecretsConfig } from "@ionite/core";
650
+ type LfvSecretsSource = SecretsSource10 & {
651
+ /** Register for callback-delivered values without issuing an initial read request. */
652
+ subscribePassive<T>(path: string, onChange: (fullSecret: Secret3<T>) => void): Promise<() => void>;
535
653
  isDeliveryRequest(request: Request): boolean;
536
654
  isEventsRequest(request: Request): boolean;
537
655
  handleDelivery(request: Request): Promise<Response>;
@@ -545,33 +663,9 @@ type LfvSecretsSource = SecretsSource6 & {
545
663
  /** Stable identity of this source's verify JWKS trust material (undefined when unconfigured). */
546
664
  readonly trustId?: string;
547
665
  };
548
- declare function lfvVault(config: VaultLfvSecretsConfig, callbackTransport?: LfvCallbackTransport): LfvSecretsSource;
549
- import { Logger as Logger3, SecretEvent, SecretsSource as SecretsSource7, SecretsSubscriptionOptions } from "@ionite/core";
550
- type MirrorSecretsOptions = {
551
- from: SecretsSource7;
552
- to: SecretsSource7;
553
- paths: readonly string[];
554
- mapPath: (path: string) => string;
555
- sourceId?: string;
556
- subscription?: SecretsSubscriptionOptions;
557
- logger?: Logger3;
558
- /** Receives every source lifecycle event after the mirror schedules its required state change. */
559
- onEvent?: (event: SecretEvent) => void;
560
- };
561
- type SecretsMirror = {
562
- isReady(): boolean;
563
- ready(timeout?: number): Promise<void>;
564
- isAvailable(): boolean;
565
- /** Delete all configured target values and provenance sidecars. Explicit tenant-offboarding action. */
566
- purge(): Promise<void>;
567
- close(): Promise<void>;
568
- };
569
- /**
570
- * Mirrors explicit secret paths from a source into a receiver-owned vault. Designed for OEM
571
- * topologies: customer values arrive over LFV, then are durably re-stored under tenant-isolated
572
- * paths before the receiver fans them out internally.
573
- */
574
- declare function mirrorSecrets(options: MirrorSecretsOptions): SecretsMirror;
666
+ declare function lfvVault(config: VaultLfvSecretsConfig, callbackTransport?: LfvCallbackTransport, options?: {
667
+ selfRedeemReads?: boolean;
668
+ }): LfvSecretsSource;
575
669
  import { SessionStore } from "@ionite/core";
576
670
  /**
577
671
  * Options for {@link createSessionReadCache}. Values are the already-clamped internal (ms/count)
@@ -622,42 +716,7 @@ declare class InMemorySessionStore<TExtended = Record<string, never>> implements
622
716
  update(sid: string, data: Partial<Session<TExtended>>): Promise<void>;
623
717
  delete(sid: string): Promise<void>;
624
718
  }
625
- import { ConfigSource as ConfigSource8, ConfigSourceResolver as ConfigSourceResolver2, TenantConfigLocator as TenantConfigLocator2 } from "@ionite/core";
626
- import { ConfigLocator as ConfigLocator2, ConfigSource as ConfigSource7 } from "@ionite/core";
627
- /**
628
- * Materialize a runtime {@link ConfigSource} from a full, self-contained {@link ConfigLocator}. This
629
- * is the ROOT/bootstrap path (env vars via `envConfig()`, or a bootstrap secret via
630
- * `secretConfigSource()`): the locator carries the connection details/credentials needed to build a
631
- * fresh source. Tenants do NOT use this path — see {@link tenantConfigSourceFromResolver}.
632
- */
633
- declare function configSourceFromLocator(locator: ConfigLocator2): ConfigSource7;
634
- /**
635
- * Context threaded into tenant config-source validation so a locator can be checked against the tenant
636
- * that owns it. INVARIANT: each tenant MUST resolve to a DISTINCT backing config path (e.g. a unique
637
- * vault path). Two tenants sharing a config path would cross-load each other's RemoteConfig.
638
- */
639
- type ConfigLocatorContext = {
640
- tenantId?: string;
641
- };
642
- /**
643
- * Optional validation hook invoked before a tenant's locator is materialized. Implementations should
644
- * throw when a locator is not valid (e.g. a shared/duplicate config path). The shared source client
645
- * may still be reused across tenants; only the resolved path must differ per tenant.
646
- */
647
- type ConfigLocatorAssert = (input: {
648
- locator: TenantConfigLocator2;
649
- }) => void;
650
- declare function registerConfigLocatorAssert(assert: ConfigLocatorAssert | undefined): void;
651
- /**
652
- * Materialize a tenant's {@link ConfigSource} from its {@link TenantConfigLocator}, resolving against
653
- * the root Ionite (`ion.secret` / `ion.secrets`). Pass the root `ion` (or any {@link ConfigSourceResolver}).
654
- *
655
- * This lives in `@ionite/server` (not core) so the materialization can reference the
656
- * server-only source implementations directly, with no import-time registration side effect — keeping
657
- * every published package truthfully `sideEffects: false`.
658
- */
659
- declare function tenantConfigSource(locator: TenantConfigLocator2, ion: ConfigSourceResolver2): ConfigSource8;
660
- import { Ionite as Ionite3, TenantPathNamespace, TenantRoutingStrategy } from "@ionite/core";
719
+ import { Ionite as Ionite4, TenantPathNamespace, TenantRoutingStrategy } from "@ionite/core";
661
720
  type MaybePromise<T> = Promise<T> | T;
662
721
  type TenantResolutionContext = {
663
722
  namespace: "api" | "ui";
@@ -676,23 +735,23 @@ type ResolveTenantFromRequestOptions = {
676
735
  };
677
736
  type CreateTenantIonResolverOptions = {
678
737
  store: {
679
- getIon(id: string): Promise<Ionite3 | undefined>;
738
+ getIon(id: string): Promise<Ionite4 | undefined>;
680
739
  };
681
740
  getIon?: never;
682
741
  } | {
683
742
  store?: never;
684
- getIon: (id: string) => Promise<Ionite3 | null | undefined>;
743
+ getIon: (id: string) => Promise<Ionite4 | null | undefined>;
685
744
  };
686
- type TenantIonResolver = (id: string) => Promise<Ionite3 | undefined>;
745
+ type TenantIonResolver = (id: string) => Promise<Ionite4 | undefined>;
687
746
  type CreateTenantIonHandlerOptions = {
688
- getIon: (id: string, request: Request) => MaybePromise<Ionite3 | null | undefined>;
747
+ getIon: (id: string, request: Request) => MaybePromise<Ionite4 | null | undefined>;
689
748
  resolveTenant?: (request: Request) => MaybePromise<{
690
749
  id: string;
691
750
  context?: TenantResolutionContext;
692
751
  } | string | null | undefined>;
693
752
  rewriteRequest?: (request: Request, details: {
694
753
  id: string;
695
- ion: Ionite3;
754
+ ion: Ionite4;
696
755
  context?: TenantResolutionContext;
697
756
  }) => MaybePromise<Request>;
698
757
  onMissingTenant?: (request: Request) => MaybePromise<Response>;
@@ -708,20 +767,22 @@ declare function rewriteRequestForTenantPath(request: Request, id: string, sourc
708
767
  declare function rewriteRequestForDefaultTenantApi(request: Request, id: string, targetNamespace?: TenantPathNamespace): Request;
709
768
  declare function rewriteRequestForDefaultTenantUi(request: Request, id: string, targetNamespace?: TenantPathNamespace): Request;
710
769
  declare function createTenantIonHandler(options: CreateTenantIonHandlerOptions): (request: Request) => Promise<Response>;
711
- import { BaseUser as BaseUser2, ListOptions as ListOptions4, ListResult as ListResult4, UserStore as UserStore2 } from "@ionite/core";
770
+ import { BaseUser as BaseUser3, ListOptions as ListOptions4, ListResult as ListResult4, UserStore as UserStore2 } from "@ionite/core";
712
771
  /**
713
772
  * In-memory user store implementation using Maps.
714
773
  */
715
774
  declare class InMemoryUserStore<TExtended = Record<string, never>> implements UserStore2<TExtended> {
716
775
  private users;
717
776
  private userNameIndex;
718
- get(id: string): Promise<BaseUser2<TExtended> | undefined>;
719
- lookup(user: BaseUser2<TExtended>): Promise<BaseUser2<TExtended> | undefined>;
720
- upsert(user: BaseUser2<TExtended>): Promise<BaseUser2<TExtended>>;
777
+ private externalIdIndex;
778
+ get(id: string): Promise<BaseUser3<TExtended> | undefined>;
779
+ getByExternalId(externalId: string): Promise<BaseUser3<TExtended> | undefined>;
780
+ lookup(user: BaseUser3<TExtended>): Promise<BaseUser3<TExtended> | undefined>;
781
+ upsert(user: BaseUser3<TExtended>): Promise<BaseUser3<TExtended>>;
721
782
  delete(sub: string): Promise<number>;
722
- list(options?: ListOptions4): Promise<ListResult4<BaseUser2<TExtended>>>;
783
+ list(options?: ListOptions4): Promise<ListResult4<BaseUser3<TExtended>>>;
723
784
  }
724
- import { LfvCallbackTransport as LfvCallbackTransport2, Secret, SecretsSource as SecretsSource8, SecretsSubscriptionOptions as SecretsSubscriptionOptions2, VaultSecretsConfig as VaultSecretsConfig2 } from "@ionite/core";
785
+ import { LfvCallbackTransport as LfvCallbackTransport2, Secret as Secret4, SecretsSource as SecretsSource11, SecretsSubscriptionOptions as SecretsSubscriptionOptions2, VaultSecretsConfig as VaultSecretsConfig2 } from "@ionite/core";
725
786
  declare class VaultSubscribeNotSupportedError extends Error {
726
787
  readonly sourceType: string;
727
788
  readonly path: string;
@@ -739,8 +800,8 @@ type HttpPollingHooks = {
739
800
  * a slow/failing upstream (no `setInterval` storm). The returned unsubscribe sets a `closed` flag and
740
801
  * cancels any pending timer/sleep, so teardown halts all activity immediately even mid-outage.
741
802
  */
742
- declare function subscribeSecretPathWithHttpPolling<T>(source: Pick<SecretsSource8, "getFullSecret">, path: string, onChange: (fullSecret: Secret<T>) => void, ttl: number, log?: VaultSecretsConfig2["log"], options?: SecretsSubscriptionOptions2, hooks?: HttpPollingHooks): Promise<() => void>;
743
- declare function vault(config: VaultSecretsConfig2, callbackTransport?: LfvCallbackTransport2): SecretsSource8;
803
+ declare function subscribeSecretPathWithHttpPolling<T>(source: Pick<SecretsSource11, "getFullSecret">, path: string, onChange: (fullSecret: Secret4<T>) => void, ttl: number, log?: VaultSecretsConfig2["log"], options?: SecretsSubscriptionOptions2, hooks?: HttpPollingHooks): Promise<() => void>;
804
+ declare function vault(config: VaultSecretsConfig2, callbackTransport?: LfvCallbackTransport2): SecretsSource11;
744
805
  /**
745
806
  * Override the per-command websocket timeout (ms). Primarily a diagnostic/test knob; production code
746
807
  * should leave the 30s default in place.
@@ -759,8 +820,8 @@ declare function closeAllVaultSockets(): void;
759
820
  *
760
821
  * Keep this synchronized with packages/server/package.json via publish.ts.
761
822
  */
762
- declare const ION_SDK_VERSION = "0.0.23-beta.20260812.6";
763
- import { Workload as CoreWorkload, FrameworkWorkloadConfig, Ionite as Ionite4, JWTAssertionClaims, Logger as Logger5, TokenValidationResult, TrustedIdp, WorkloadConfigMap, WorkloadGetToken, WorkloadIdentityStore as WorkloadIdentityStore2, WorkloadIncomingOutgoing, WorkloadTokenResponse, WorkloadTokenStore } from "@ionite/core";
823
+ declare const ION_SDK_VERSION = "0.0.23-beta.20260820.2";
824
+ import { Workload as CoreWorkload, FrameworkWorkloadConfig, Ionite as Ionite5, JWTAssertionClaims, Logger as Logger7, TokenValidationResult, TrustedIdp, WorkloadConfigMap, WorkloadGetToken, WorkloadIdentityStore as WorkloadIdentityStore3, WorkloadIncomingOutgoing, WorkloadTokenResponse, WorkloadTokenStore } from "@ionite/core";
764
825
  import { StandardSchemaV1 } from "@standard-schema/spec";
765
826
  /**
766
827
  * Common fields shared across all workload authentication modes
@@ -817,7 +878,7 @@ type WorkloadConfigBase = {
817
878
  * merges stored attributes (e.g. `displayName`, `active`, default `scopes`) onto the validated
818
879
  * token identity. Authorization works without it; see {@link WorkloadIdentityStore}.
819
880
  */
820
- workloadIdentityStore?: WorkloadIdentityStore2;
881
+ workloadIdentityStore?: WorkloadIdentityStore3;
821
882
  /**
822
883
  * Automatically refresh tokens before expiration
823
884
  * @default true
@@ -985,8 +1046,8 @@ type Workload3 = {
985
1046
  config: WorkloadConfig;
986
1047
  beforeChange?: (listener: () => void) => () => void;
987
1048
  afterChange?: (listener: () => void) => () => void;
988
- isReady?: () => boolean;
989
- ready?: (timeout?: number) => Promise<void>;
1049
+ isReady: () => boolean;
1050
+ ready: (timeout?: number) => Promise<void>;
990
1051
  getToken: WorkloadGetToken;
991
1052
  refreshToken: (scope?: string) => Promise<WorkloadTokenResponse>;
992
1053
  generateJWTAssertion: (scope?: string) => Promise<string>;
@@ -996,38 +1057,38 @@ type Workload3 = {
996
1057
  parseJWT: (token: string) => Promise<JWTAssertionClaims>;
997
1058
  handler: (request: Request) => Promise<Response>;
998
1059
  };
999
- declare function workload(validators: WorkloadValidators, log: Logger5, fromVault?: Partial<WorkloadConfig> | WorkloadConfigMap | WorkloadIncomingOutgoing, fromCode?: FrameworkWorkloadConfig, incomingTrustOverride?: TrustedIdp[]): Workload3 | undefined;
1060
+ declare function workload(validators: WorkloadValidators, log: Logger7, fromVault?: Partial<WorkloadConfig> | WorkloadConfigMap | WorkloadIncomingOutgoing, fromCode?: FrameworkWorkloadConfig, incomingTrustOverride?: TrustedIdp[]): Workload3 | undefined;
1000
1061
  /**
1001
1062
  * Get the workload identity from an incoming request.
1002
1063
  */
1003
- declare function getWorkload(request: Request, ion: Ionite4): Promise<WorkloadIdentity | undefined>;
1064
+ declare function getWorkload(request: Request, ion: Ionite5): Promise<WorkloadIdentity | undefined>;
1004
1065
  /**
1005
1066
  * Get an access token for the configured workload identity.
1006
1067
  * Client is required and must be one of the configured outgoing workload clients.
1007
1068
  * Throws when no outgoing clients are configured on this Ionite instance.
1008
1069
  * Scope defaults to the config for the chosen client (e.g. workload.outgoing.<name>.scope); pass scope to override.
1009
1070
  */
1010
- declare function getWorkloadToken(client: string, ion: Ionite4, scope?: string): Promise<string>;
1071
+ declare function getWorkloadToken(client: string, ion: Ionite5, scope?: string): Promise<string>;
1011
1072
  /**
1012
1073
  * Validate a workload token from an incoming request.
1013
1074
  * Accepts either an Ionite instance (uses its workload) or a Workload instance directly
1014
1075
  * (e.g. a server-only Workload used for tenant creation auth).
1015
1076
  */
1016
- declare function validateWorkloadToken(request: Request, ionOrWorkload: Ionite4 | CoreWorkload): Promise<TokenValidationResult>;
1077
+ declare function validateWorkloadToken(request: Request, ionOrWorkload: Ionite5 | CoreWorkload): Promise<TokenValidationResult>;
1017
1078
  /**
1018
1079
  * Revoke a workload access token.
1019
1080
  */
1020
- declare function revokeWorkloadToken(token: string, ion: Ionite4): Promise<void>;
1081
+ declare function revokeWorkloadToken(token: string, ion: Ionite5): Promise<void>;
1021
1082
  /**
1022
1083
  * Framework-agnostic request handler for the Workload module (token, validate, jwks, refresh routes).
1023
1084
  */
1024
- declare function workloadHandler(request: Request, ion: Ionite4): Promise<Response>;
1025
- import { BaseWorkloadIdentity, ListOptions as ListOptions5, ListResult as ListResult5, WorkloadIdentityStore as WorkloadIdentityStore3 } from "@ionite/core";
1085
+ declare function workloadHandler(request: Request, ion: Ionite5): Promise<Response>;
1086
+ import { BaseWorkloadIdentity, ListOptions as ListOptions5, ListResult as ListResult5, WorkloadIdentityStore as WorkloadIdentityStore4 } from "@ionite/core";
1026
1087
  /**
1027
1088
  * In-memory {@link WorkloadIdentityStore} implementation using Maps. Suitable for development and
1028
1089
  * testing; use a durable store (e.g. Redis/SQL) in production.
1029
1090
  */
1030
- declare class InMemoryWorkloadIdentityStore<TExtended = Record<string, never>> implements WorkloadIdentityStore3<TExtended> {
1091
+ declare class InMemoryWorkloadIdentityStore<TExtended = Record<string, never>> implements WorkloadIdentityStore4<TExtended> {
1031
1092
  private identities;
1032
1093
  private clientIdIndex;
1033
1094
  get(id: string): Promise<BaseWorkloadIdentity<TExtended> | undefined>;
@@ -1056,10 +1117,10 @@ type IoniteConfig<C extends FrameworkConfigInput = FrameworkConfigInput> = C & {
1056
1117
  basePath?: string;
1057
1118
  stores?: FrameworkStores2;
1058
1119
  beforeChange?: ConfigChangeCallback;
1059
- afterChange?: (ion: Ionite5, config: RemoteConfig2, frameworkConfig: ModifiableFrameworkConfig, oldConfig: RemoteConfig2 | undefined) => void;
1120
+ afterChange?: (ion: Ionite6, config: RemoteConfig3, frameworkConfig: ModifiableFrameworkConfig, oldConfig: RemoteConfig3 | undefined) => void;
1060
1121
  routing?: RoutingOptions2;
1061
1122
  configRetry?: RemoteConfigRetryOptions;
1062
1123
  onConfigLoadError?: RemoteConfigRetryHook;
1063
1124
  };
1064
- declare function ionite<const C extends FrameworkConfigInput = FrameworkConfigInput>(source: ConfigSource9, config: IoniteConfig<C> | FrameworkConfigInput): Ionite5;
1065
- export { workloadHandler, workload, withSetCookies, withDefaultExternalId, verifyUser, vaultSocketDiagnostics, vaultConfig, vault, validateWorkloadToken, tenantManager, tenantConfigSource, subscribeSecretPathWithHttpPolling, sso, setVaultWebSocketCommandTimeout, sendTenantWebhook, secretConfigSource, sameOriginRedirectRules, routeRequest, rewriteRequestPath, rewriteRequestForTenantPath, rewriteRequestForDefaultTenantUi, rewriteRequestForDefaultTenantApi, revokeWorkloadToken, resolveTenantFromRequest, resolveRedirect, resolveDefaultRoute, resolveCapturedRedirect, resolveAfterRedirect, registerConfigLocatorAssert, reconcileSubjectAccess, mirrorSecrets, listSsoClientIdsFromCookies, listGenerator, lfvVault, isVaultConfigWaitingForSecretError, isVaultConfigInvalidPayloadError, isRedirectAllowed, ionite, initiateLogin, iamDeltaIdMapKey, iam, hasScope, hasRole2 as hasRole, hasPermission2 as hasPermission, hasGroup2 as hasGroup, hasAnyScope, hasAny2 as hasAny, hasAllScope, hasAll2 as hasAll, has, getWorkloadToken, getWorkload, getUser, getCustomer, generateULID, gcpConfig, expandRoot, escapeScimFilterValue, envConfig, enforceEndpointAuthz, discoverSessions, discoverSessionRecords, deriveIonUrls, defaultRedirectPolicies, createTenantIonResolver, createTenantIonHandler, createSessionReadCache, createManagedIamDelta, configSourceFromLocator, configSourceFromEnvValues, configLocatorFromEnvValues, collectReferencedDefinitions, closeAllVaultSockets, ciam, captureRedirect, callback, blockDangerousUrls, azureConfig, awsConfig, allowSameOrigin, allowRelativePaths, allowOrigins, allowHosts, VerifyUserOptions, VaultSubscribeNotSupportedError, VaultConfigWaitingForSecretError, VaultConfigSourceOptions, VaultConfigInvalidPayloadError, VAULT_MIN_POLLING_TTL_MS, UrlMap, UpdateTenantRequest2 as UpdateTenantRequest, TenantWebhookPayload, TenantValidators2 as TenantValidators, TenantStatus, TenantResponse, TenantResolutionContext, TenantManagerOptions, TenantManager, TenantIonUrls, TenantIonResolver, SubjectType3 as SubjectType, SubjectScope, SessionResponse, SessionReadCacheOptions, SessionDiscoveryOptions, SecretsMirror, ScimOutboundCreate, ScimOutboundClientOptions, ScimOutboundClient, ResolveTenantFromRequestOptions, ReferencedDefinitions, RedirectVerdict, RedirectRuleContext, RedirectRule, RedirectResult, RedirectPolicy, RedirectContext, ReconcileStores, OtelSignalConfig, OtelProviderType, OtelOAuthClientCredentialsConfig, OtelMetricsSignalConfig, OtelLogRecord, OtelLogLevel, OtelLevels, OtelConfig, Otel, MirrorSecretsOptions, LfvSecretsSource, IoniteErrorOptions, IoniteError, IoniteConfig, InMemoryWorkloadTokenStore, InMemoryWorkloadIdentityStore, InMemoryUserStore, InMemoryTenantStore, InMemorySessionStore, InMemoryResourceStore, InMemoryMagicLinkStore, InMemoryIamDeltaIdMapStore, InMemoryCustomerStore, InMemoryAccessIndex, InMemoryAccessCatalogStore, InMemoryAccessAssignmentStore, IamDeltaDeps, IamDeltaConfig, ION_SDK_VERSION, ION_CAPABILITY_CATALOG_VERSION, ION_CAPABILITY_CATALOG, HttpPollingHooks, GcpConfigSourceOptions, FrameworkStores3 as FrameworkStores, FrameworkOtelConfig, EnvironmentType, EnvConfigOptions, CreateTenantRequest2 as CreateTenantRequest, CreateTenantIonResolverOptions, CreateTenantIonHandlerOptions, ConfigLocatorContext, ConfigLocatorAssert, CatalogView, CatalogAdjacencyCache, CapabilityKey2 as CapabilityKey, CapabilityDescriptor, BeforeLogoutHook, BeforeLogoutContext, BeforeLoginHook, BeforeLoginContext, AzureConfigSourceOptions, AwsConfigSourceOptions, AfterLogoutHook, AfterLogoutContext, AfterLoginHook, AfterLoginContext, AccessCheckResult, AccessCheckReason };
1125
+ declare function ionite<const C extends FrameworkConfigInput = FrameworkConfigInput>(source: ConfigSource9, config: IoniteConfig<C> | FrameworkConfigInput): Ionite6;
1126
+ export { workloadHandler, workload, withSetCookies, verifyUser, vaultSocketDiagnostics, vaultConfig, vault, validateWorkloadToken, tenantMirror, tenantManager, subscribeSecretPathWithHttpPolling, sso, setVaultWebSocketCommandTimeout, sendTenantWebhook, secretConfigSource, sameOriginRedirectRules, routeRequest, rewriteRequestPath, rewriteRequestForTenantPath, rewriteRequestForDefaultTenantUi, rewriteRequestForDefaultTenantApi, revokeWorkloadToken, resolveTenantFromRequest, resolveRedirect, resolveDefaultRoute, resolveCapturedRedirect, resolveAfterRedirect, reconcileSubjectAccess, mirroredConfig, mirrorSecrets, listSsoClientIdsFromCookies, listGenerator, lfvVault, isVaultConfigWaitingForSecretError, isVaultConfigInvalidPayloadError, isRedirectAllowed, ionite, initiateLogin, iam, hasScope, hasRole2 as hasRole, hasPermission2 as hasPermission, hasGroup2 as hasGroup, hasAnyScope, hasAny2 as hasAny, hasAllScope, hasAll2 as hasAll, has, getWorkloadToken, getWorkload, getUser, getCustomer, generateULID, gcpConfig, expandRoot, escapeScimFilterValue, envConfig, enforceEndpointAuthz, discoverSessions, discoverSessionRecords, deriveIonUrls, defaultRedirectPolicies, createTenantIonResolver, createTenantIonHandler, createSessionReadCache, createManagedIamDelta, configSourceFromLocator, configSourceFromEnvValues, configLocatorFromEnvValues, configFromSource, collectReferencedDefinitions, closeAllVaultSockets, ciam, captureRedirect, callback, blockDangerousUrls, azureConfig, awsConfig, allowSameOrigin, allowRelativePaths, allowOrigins, allowHosts, VerifyUserOptions, VaultSubscribeNotSupportedError, VaultConfigWaitingForSecretError, VaultConfigSourceOptions, VaultConfigInvalidPayloadError, VAULT_MIN_POLLING_TTL_MS, UrlMap, UpdateTenantRequest2 as UpdateTenantRequest, TenantWebhookPayload, TenantValidators2 as TenantValidators, TenantStatus, TenantResponse, TenantResolutionContext, TenantMirrorOptions, TenantMirrorHooks, TenantMirror, TenantManagerOptions, TenantManager, TenantIonUrls, TenantIonResolver, SubjectType3 as SubjectType, SubjectScope, SessionResponse, SessionReadCacheOptions, SessionDiscoveryOptions, SecretsMirror, ScimOutboundResource, ScimOutboundReceiptCallbacks, ScimOutboundOutcome, ScimOutboundClientOptions, ScimOutboundClient, ResolveTenantFromRequestOptions, ReferencedDefinitions, RedirectVerdict, RedirectRuleContext, RedirectRule, RedirectResult, RedirectPolicy, RedirectContext, ReconcileStores, OtelSignalConfig, OtelProviderType, OtelOAuthClientCredentialsConfig, OtelMetricsSignalConfig, OtelLogRecord, OtelLogLevel, OtelLevels, OtelConfig, Otel, MirroredConfigSource, MirroredConfigOptions, MirrorSecretsOptions, LfvSecretsSource, IoniteErrorOptions, IoniteError, IoniteConfig, InMemoryWorkloadTokenStore, InMemoryWorkloadIdentityStore, InMemoryUserStore, InMemoryTenantStore, InMemorySessionStore, InMemoryResourceStore, InMemoryMagicLinkStore, InMemoryCustomerStore, InMemoryAccessIndex, InMemoryAccessCatalogStore, InMemoryAccessAssignmentStore, IamDeltaDeps, IamDeltaConfig, ION_SDK_VERSION, ION_CAPABILITY_CATALOG_VERSION, ION_CAPABILITY_CATALOG, HttpPollingHooks, GcpConfigSourceOptions, FrameworkStores3 as FrameworkStores, FrameworkOtelConfig, EnvironmentType, EnvConfigOptions, CreateTenantRequest2 as CreateTenantRequest, CreateTenantIonResolverOptions, CreateTenantIonHandlerOptions, ConfigFromSourceOptions, CatalogView, CatalogAdjacencyCache, CapabilityKey2 as CapabilityKey, CapabilityDescriptor, BeforeLogoutHook, BeforeLogoutContext, BeforeLoginHook, BeforeLoginContext, AzureConfigSourceOptions, AwsConfigSourceOptions, AfterLogoutHook, AfterLogoutContext, AfterLoginHook, AfterLoginContext, AccessCheckResult, AccessCheckReason };