@ionite/server 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1032 -0
- package/dist/index.js +1 -0
- package/package.json +47 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1032 @@
|
|
|
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";
|
|
3
|
+
import { CapabilityEndpointUrls } from "@ionite/core";
|
|
4
|
+
/**
|
|
5
|
+
* Deterministic set of ionite endpoint paths derived from a single `basePath`.
|
|
6
|
+
* These are the only URLs the SDK mounts; application code cannot customize individual paths
|
|
7
|
+
* (only `basePath`). Post-login/logout destinations are NOT here: they are decided by the appdev's
|
|
8
|
+
* `beforeLogin`/`afterLogin`/`beforeLogout`/`afterLogout` hooks (application UI routes), not ES endpoints derivable from `basePath`.
|
|
9
|
+
*/
|
|
10
|
+
type UrlMap = CapabilityEndpointUrls;
|
|
11
|
+
/**
|
|
12
|
+
* Derive every ionite endpoint path from `basePath`. Single source of truth consumed
|
|
13
|
+
* by module construction, the router, the readiness endpoint, and tenant-manager responses.
|
|
14
|
+
*/
|
|
15
|
+
declare function deriveIonUrls(basePath: string): UrlMap;
|
|
16
|
+
type TenantManagerOptions<
|
|
17
|
+
TCreateTenantRequest extends CreateTenantRequest = CreateTenantRequest,
|
|
18
|
+
TUpdateTenantRequest extends UpdateTenantRequest = UpdateTenantRequest,
|
|
19
|
+
TTenant extends BaseTenant = BaseTenant
|
|
20
|
+
> = {
|
|
21
|
+
validators: ApplicationValidators<TenantValidators<TCreateTenantRequest, TUpdateTenantRequest>>;
|
|
22
|
+
basePath: string;
|
|
23
|
+
store: TenantStore<TTenant>;
|
|
24
|
+
workloadAuth?: Workload;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the ionite `basePath` for a given tenant (e.g. `/api/${tenant.id}/es`).
|
|
27
|
+
* When provided, tenant responses include the derived absolute SSO `callbackUrl` and full `ionUrls`
|
|
28
|
+
* so the ECI/ConfigSource can register the matching callback path at the IdP. ES endpoint URLs are
|
|
29
|
+
* deterministic from this basePath; they are not configurable per-URL.
|
|
30
|
+
*/
|
|
31
|
+
tenantEsBasePath?: (tenant: TTenant) => string | undefined;
|
|
32
|
+
};
|
|
33
|
+
/** Absolute ionite URL set for a tenant, derived from its basePath and request origin. */
|
|
34
|
+
type TenantIonUrls = {
|
|
35
|
+
callbackUrl: string;
|
|
36
|
+
ionUrls: UrlMap;
|
|
37
|
+
};
|
|
38
|
+
type TenantManager<TTenant extends BaseTenant = BaseTenant> = {
|
|
39
|
+
handler(request: Request): Promise<Response>;
|
|
40
|
+
getTenant(id: string): Promise<TTenant | undefined>;
|
|
41
|
+
};
|
|
42
|
+
declare function tenantManager<
|
|
43
|
+
TCreateTenantRequest extends CreateTenantRequest = CreateTenantRequest,
|
|
44
|
+
TUpdateTenantRequest extends UpdateTenantRequest = UpdateTenantRequest,
|
|
45
|
+
TTenant extends BaseTenant = BaseTenant
|
|
46
|
+
>(ion: Ionite, options: TenantManagerOptions<TCreateTenantRequest, TUpdateTenantRequest, TTenant>): TenantManager<TTenant>;
|
|
47
|
+
import { CapabilityKey as CapabilityKey2 } from "@ionite/core";
|
|
48
|
+
export * from "@ionite/core";
|
|
49
|
+
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
|
+
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";
|
|
52
|
+
import { AccessAssignmentStore as AccessAssignmentStore2, AccessChange, ListOptions, ListResult, OaaAccessTargetType, SubjectType } from "@ionite/core";
|
|
53
|
+
/**
|
|
54
|
+
* In-memory store of granted access **roots** (source of truth). Roots are keyed by their
|
|
55
|
+
* deterministic id (`accessRootId`) and carry provenance + status. All stored roots are `active`
|
|
56
|
+
* (the SDK uses a transactional fail-fast model with no `pendingRemoval` sweep).
|
|
57
|
+
*/
|
|
58
|
+
declare class InMemoryAccessAssignmentStore implements AccessAssignmentStore2<AccessChange> {
|
|
59
|
+
private readonly roots;
|
|
60
|
+
private readonly byTarget;
|
|
61
|
+
private readonly bySubject;
|
|
62
|
+
private static targetKey;
|
|
63
|
+
private static subjectKey;
|
|
64
|
+
private indexAdd;
|
|
65
|
+
private indexRemove;
|
|
66
|
+
private deindex;
|
|
67
|
+
private index;
|
|
68
|
+
private resolve;
|
|
69
|
+
grant(change: AccessChange): Promise<void>;
|
|
70
|
+
revoke(change: AccessChange): Promise<void>;
|
|
71
|
+
get(id: string): Promise<AccessChange | undefined>;
|
|
72
|
+
list(options?: ListOptions): Promise<ListResult<AccessChange>>;
|
|
73
|
+
listByTarget(targetType: OaaAccessTargetType, target: string, options?: ListOptions): Promise<ListResult<AccessChange>>;
|
|
74
|
+
listByTargets(targets: Array<{
|
|
75
|
+
targetType: OaaAccessTargetType;
|
|
76
|
+
target: string;
|
|
77
|
+
}>): Promise<Map<string, AccessChange[]>>;
|
|
78
|
+
listBySubject(subject: string, subjectType?: SubjectType, options?: ListOptions): Promise<ListResult<AccessChange>>;
|
|
79
|
+
}
|
|
80
|
+
import { AccessCatalogStore as AccessCatalogStore2, CatalogChangeListener, EntityStore, Group, ListOptions as ListOptions2, ListResult as ListResult2, Permission, Resource, ResourceChangeListener, ResourceProvider as ResourceProvider2, Role } from "@ionite/core";
|
|
81
|
+
declare class InMemoryAccessCatalogStore implements AccessCatalogStore2 {
|
|
82
|
+
private readonly listeners;
|
|
83
|
+
private readonly emit;
|
|
84
|
+
readonly groups: EntityStore<Group>;
|
|
85
|
+
readonly roles: EntityStore<Role>;
|
|
86
|
+
readonly permissions: EntityStore<Permission>;
|
|
87
|
+
afterChange(listener: CatalogChangeListener): () => void;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Writable, in-memory {@link ResourceProvider} for zero-DB quickstarts, dev tools, and validation.
|
|
91
|
+
* Real applications should implement `ResourceProvider` directly over their own database/ORM (the
|
|
92
|
+
* 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.
|
|
94
|
+
*
|
|
95
|
+
* `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.
|
|
98
|
+
*/
|
|
99
|
+
declare class InMemoryResourceStore implements ResourceProvider2 {
|
|
100
|
+
private readonly items;
|
|
101
|
+
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
|
+
get(id: string): Promise<Resource | undefined>;
|
|
111
|
+
list(options?: ListOptions2): Promise<ListResult2<Resource>>;
|
|
112
|
+
children(id: string): Promise<Resource[]>;
|
|
113
|
+
changed(listener: ResourceChangeListener): () => void;
|
|
114
|
+
/** Upsert a resource and signal `changed`. */
|
|
115
|
+
set(resource: Resource): void;
|
|
116
|
+
/** Delete a resource and signal `changed` with `deleted: true`. */
|
|
117
|
+
delete(id: string): void;
|
|
118
|
+
private emitChange;
|
|
119
|
+
}
|
|
120
|
+
import { AccessCheckTarget, AccessIndex as AccessIndex2, AccessRef, AuthzDecision, BaseUser, EffectiveEdge, Group as Group2, OaaAccessTargetType as OaaAccessTargetType2, Permission as Permission2, Resource as Resource2, Role as Role2, SubjectRef, SubjectType as SubjectType2 } from "@ionite/core";
|
|
121
|
+
/**
|
|
122
|
+
* In-memory derived closure index. Rows are root-attributed: a single
|
|
123
|
+
* `(subject, targetType, target, resource)` edge may be justified by multiple roots, so revoking
|
|
124
|
+
* one root via {@link removeByRoot} leaves edges still backed by other roots. Rebuildable from
|
|
125
|
+
* AccessAssignmentStore roots + the catalog.
|
|
126
|
+
*/
|
|
127
|
+
declare class InMemoryAccessIndex implements AccessIndex2 {
|
|
128
|
+
/** edgeKey -> set of rootIds that justify it. */
|
|
129
|
+
private readonly rows;
|
|
130
|
+
/** tripleKey -> set of edgeKeys (for resource-agnostic "any" checks). */
|
|
131
|
+
private readonly byTriple;
|
|
132
|
+
/** rootId -> set of edgeKeys it materialized (for removeByRoot). */
|
|
133
|
+
private readonly byRoot;
|
|
134
|
+
/** subjectId -> set of edgeKeys (for clear(subject)). */
|
|
135
|
+
private readonly bySubject;
|
|
136
|
+
/** edgeKey -> structural metadata (avoids fragile key parsing on cleanup). */
|
|
137
|
+
private readonly edgeMeta;
|
|
138
|
+
/**
|
|
139
|
+
* Subject-disabled markers (subjectKey set). Deliberately independent of edge materialization:
|
|
140
|
+
* `materialize`/`removeByRoot`/`clear` never touch it, so reconcile cannot silently re-enable a
|
|
141
|
+
* SCIM-deactivated subject. Grants stay intact; re-enabling restores prior decisions unchanged.
|
|
142
|
+
*/
|
|
143
|
+
private readonly disabledSubjects;
|
|
144
|
+
has(subject: AccessRef<BaseUser>, targetType: OaaAccessTargetType2, target: AccessRef<Group2 | Role2 | Permission2>, resource?: AccessRef<Resource2>, subjectType?: SubjectType2): Promise<AuthzDecision>;
|
|
145
|
+
hasGroup(subject: AccessRef<BaseUser>, group: AccessRef<Group2>, resource?: AccessRef<Resource2>, subjectType?: SubjectType2): Promise<AuthzDecision>;
|
|
146
|
+
hasRole(subject: AccessRef<BaseUser>, role: AccessRef<Role2>, resource?: AccessRef<Resource2>, subjectType?: SubjectType2): Promise<AuthzDecision>;
|
|
147
|
+
hasPermission(subject: AccessRef<BaseUser>, permission: AccessRef<Permission2>, resource?: AccessRef<Resource2>, subjectType?: SubjectType2): Promise<AuthzDecision>;
|
|
148
|
+
hasAny(subject: AccessRef<BaseUser>, targets: AccessCheckTarget[], subjectType?: SubjectType2): Promise<AuthzDecision>;
|
|
149
|
+
hasAll(subject: AccessRef<BaseUser>, targets: AccessCheckTarget[], subjectType?: SubjectType2): Promise<AuthzDecision>;
|
|
150
|
+
materialize(rootId: string, edges: EffectiveEdge[]): Promise<void>;
|
|
151
|
+
removeByRoot(rootId: string): Promise<void>;
|
|
152
|
+
listSubjects(): Promise<SubjectRef[]>;
|
|
153
|
+
setSubjectDisabled(subject: string, subjectType: SubjectType2, disabled: boolean): Promise<void>;
|
|
154
|
+
isSubjectDisabled(subject: string, subjectType?: SubjectType2): Promise<boolean>;
|
|
155
|
+
clear(subject?: string, subjectType?: SubjectType2): Promise<void>;
|
|
156
|
+
private allow;
|
|
157
|
+
private addToSet;
|
|
158
|
+
/** Fully remove an edge key from every secondary index (used when no roots justify it anymore). */
|
|
159
|
+
private dropEdge;
|
|
160
|
+
private removeFromSet;
|
|
161
|
+
}
|
|
162
|
+
import { AwsSecretsConfig, ConfigSource, SecretsSource } from "@ionite/core";
|
|
163
|
+
type AwsConfigSourceOptions = Omit<AwsSecretsConfig, "type"> & {
|
|
164
|
+
vault?: SecretsSource;
|
|
165
|
+
ttl?: number;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Creates a ConfigSource which reads from AWS Secrets Manager.
|
|
169
|
+
*
|
|
170
|
+
* Not implemented in this build. Throws synchronously at construction (config-source resolution /
|
|
171
|
+
* startup) so a `type: 'aws'` locator fails fast with a clear error rather than type-checking and
|
|
172
|
+
* then throwing at first config access.
|
|
173
|
+
*/
|
|
174
|
+
declare function awsConfig(_config: AwsConfigSourceOptions): ConfigSource;
|
|
175
|
+
import { AzureSecretsConfig, ConfigSource as ConfigSource2, SecretsSource as SecretsSource2 } from "@ionite/core";
|
|
176
|
+
type AzureConfigSourceOptions = Omit<AzureSecretsConfig, "type"> & {
|
|
177
|
+
vault?: SecretsSource2;
|
|
178
|
+
path?: string;
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Creates a ConfigSource which reads from Azure Key Vault.
|
|
182
|
+
* The path is mapped to a Key Vault secret name via secretNameTransform (default: `/` → `-`).
|
|
183
|
+
* If ttl is set, the vault is polled every ttl milliseconds (minimum 10 minutes) and onConfig is called when config changes.
|
|
184
|
+
*/
|
|
185
|
+
declare function azureConfig(config: AzureConfigSourceOptions): ConfigSource2;
|
|
186
|
+
import { ConfigLocator, ConfigSource as ConfigSource3, ConfigSourceEnv, ConfigSourceType } from "@ionite/core";
|
|
187
|
+
type EnvConfigOptions = {
|
|
188
|
+
/** Override config source type (default: ION_CONFIG_TYPE from env). */
|
|
189
|
+
type?: ConfigSourceType;
|
|
190
|
+
};
|
|
191
|
+
declare function configLocatorFromEnvValues(env: Partial<ConfigSourceEnv>, options?: EnvConfigOptions): ConfigLocator;
|
|
192
|
+
/**
|
|
193
|
+
* Creates a ConfigSource from environment variables.
|
|
194
|
+
* Reads ION_CONFIG_TYPE to choose the source.
|
|
195
|
+
* For each supported type, it merges the options with available environment variables.
|
|
196
|
+
*/
|
|
197
|
+
declare function configSourceFromEnvValues(env: Partial<ConfigSourceEnv>, options?: EnvConfigOptions): ConfigSource3;
|
|
198
|
+
declare function envConfig(options?: EnvConfigOptions): ConfigSource3;
|
|
199
|
+
import { ConfigSource as ConfigSource4, GcpSecretsConfig, SecretsSource as SecretsSource3 } from "@ionite/core";
|
|
200
|
+
type GcpConfigSourceOptions = Omit<GcpSecretsConfig, "type"> & {
|
|
201
|
+
vault?: SecretsSource3;
|
|
202
|
+
ttl?: number;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Creates a ConfigSource which reads from GCP Secrets Manager.
|
|
206
|
+
*
|
|
207
|
+
* Not implemented in this build. Throws synchronously at construction (config-source resolution /
|
|
208
|
+
* startup) so a `type: 'gcp'` locator fails fast with a clear error rather than type-checking and
|
|
209
|
+
* then throwing at first config access.
|
|
210
|
+
*/
|
|
211
|
+
declare function gcpConfig(_config: GcpConfigSourceOptions): ConfigSource4;
|
|
212
|
+
import { ConfigSource as ConfigSource5, SecretsSource as SecretsSource4 } from "@ionite/core";
|
|
213
|
+
/**
|
|
214
|
+
* Creates a ConfigSource from a SecretsSource path that stores a ConfigLocator.
|
|
215
|
+
* The returned source rebinds subscriptions when the bootstrap secret changes.
|
|
216
|
+
*
|
|
217
|
+
* The resolved inner ConfigSource is cached by a hash of the bootstrap locator so repeated `load()`
|
|
218
|
+
* calls and unchanged bootstrap refreshes reuse the same inner source (and, for vault-backed inner
|
|
219
|
+
* sources, the same websocket/poll) instead of constructing a fresh one every time. When the
|
|
220
|
+
* bootstrap actually changes, the superseded inner source is disposed (its `secret.close()` is
|
|
221
|
+
* invoked) before the new one is built, so config churn cannot leak duplicate connections.
|
|
222
|
+
*/
|
|
223
|
+
declare function secretConfigSource(source: SecretsSource4, path: string): ConfigSource5;
|
|
224
|
+
import { ConfigSource as ConfigSource6, SecretsSource as SecretsSource5, VaultSecretsConfig } from "@ionite/core";
|
|
225
|
+
type VaultConfigSourceOptions = Omit<VaultSecretsConfig, "type"> & {
|
|
226
|
+
vault?: SecretsSource5;
|
|
227
|
+
path?: string;
|
|
228
|
+
};
|
|
229
|
+
declare class VaultConfigWaitingForSecretError extends Error {
|
|
230
|
+
readonly path: string;
|
|
231
|
+
constructor(path: string, message?: string);
|
|
232
|
+
readonly code = "not_found";
|
|
233
|
+
readonly sourceType = "vault";
|
|
234
|
+
readonly status = 404;
|
|
235
|
+
}
|
|
236
|
+
declare function isVaultConfigWaitingForSecretError(error: unknown): error is VaultConfigWaitingForSecretError;
|
|
237
|
+
/**
|
|
238
|
+
* The vault config secret exists but is not a usable RemoteConfig (wrong shape / unknown keys). This
|
|
239
|
+
* is a hard, non-recoverable error (unlike {@link VaultConfigWaitingForSecretError}): the initial
|
|
240
|
+
* apply rejects rather than retries.
|
|
241
|
+
*/
|
|
242
|
+
declare class VaultConfigInvalidPayloadError extends Error {
|
|
243
|
+
readonly path: string;
|
|
244
|
+
constructor(path: string, message: string);
|
|
245
|
+
readonly code = "invalid_payload";
|
|
246
|
+
readonly sourceType = "vault";
|
|
247
|
+
}
|
|
248
|
+
declare function isVaultConfigInvalidPayloadError(error: unknown): error is VaultConfigInvalidPayloadError;
|
|
249
|
+
/**
|
|
250
|
+
* Creates a ConfigSource that reads config from a vault instance.
|
|
251
|
+
* Uses the given vault client to fetch secrets at the specified path.
|
|
252
|
+
* If ttl is set, the vault will be polled every ttl milliseconds (minimum 10 minutes) and onConfig will be called when the config changes.
|
|
253
|
+
* When a custom vault client is provided, ttl is still honored for config subscription polling if the client does not support native subscribe().
|
|
254
|
+
*/
|
|
255
|
+
declare function vaultConfig(config: VaultConfigSourceOptions): ConfigSource6;
|
|
256
|
+
import { BaseCustomer, CustomerStore, ListOptions as ListOptions3, ListResult as ListResult3 } from "@ionite/core";
|
|
257
|
+
/**
|
|
258
|
+
* In-memory customer store implementation using Maps.
|
|
259
|
+
*
|
|
260
|
+
* The CIAM customer domain counterpart to `InMemoryUserStore`.
|
|
261
|
+
*/
|
|
262
|
+
declare class InMemoryCustomerStore<TExtended = Record<string, never>> implements CustomerStore<TExtended> {
|
|
263
|
+
private customers;
|
|
264
|
+
private userNameIndex;
|
|
265
|
+
get(id: string): Promise<BaseCustomer<TExtended> | undefined>;
|
|
266
|
+
lookup(customer: BaseCustomer<TExtended>): Promise<BaseCustomer<TExtended> | undefined>;
|
|
267
|
+
upsert(customer: BaseCustomer<TExtended>): Promise<BaseCustomer<TExtended>>;
|
|
268
|
+
delete(id: string): Promise<number>;
|
|
269
|
+
list(options?: ListOptions3): Promise<ListResult3<BaseCustomer<TExtended>>>;
|
|
270
|
+
}
|
|
271
|
+
import { AccessCatalogStore as AccessCatalogStore3, IamDeltaEmitter, IamDeltaIdMapStore as IamDeltaIdMapStore2, IamDeltaMode, Logger, ResourceProvider as ResourceProvider3, UserStore, Workload as Workload2 } from "@ionite/core";
|
|
272
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
273
|
+
/** RemoteConfig-derived destination descriptor for IAM delta egress. */
|
|
274
|
+
type IamDeltaConfig = {
|
|
275
|
+
mode?: IamDeltaMode;
|
|
276
|
+
/** Destination SCIM base URL of the IAM tool. */
|
|
277
|
+
url?: string;
|
|
278
|
+
/** Outgoing workload client name used to authenticate pushes (`IAMConfig.deltaAudience`). */
|
|
279
|
+
audience?: string;
|
|
280
|
+
/** Tenant scope for the mapping cache. */
|
|
281
|
+
tenantId?: string;
|
|
282
|
+
};
|
|
283
|
+
/** Runtime capabilities the emitter binds to (resolved from the merged config/stores in buildES). */
|
|
284
|
+
type IamDeltaDeps = {
|
|
285
|
+
workload?: Workload2;
|
|
286
|
+
userStore?: UserStore;
|
|
287
|
+
catalogStore?: AccessCatalogStore3;
|
|
288
|
+
/** Read-through provider for derived-entitlement resolution (externalId lookup on delta egress). */
|
|
289
|
+
resources?: ResourceProvider3;
|
|
290
|
+
/** `externalId -> provider id` mapping cache for outbound SCIM (defaults to in-memory). */
|
|
291
|
+
idMapStore?: IamDeltaIdMapStore2;
|
|
292
|
+
/** Injectable fetch (defaults to global fetch); enables testing the patch path in-process. */
|
|
293
|
+
fetchImpl?: FetchLike;
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* Managed IAM delta module (mirrors `createManagedAuthz`). Creates ONE persistent
|
|
297
|
+
* {@link IamDeltaEmitter} whose readiness promise is stable across RemoteConfig applies;
|
|
298
|
+
* `update(config, deps)` reconfigures the destination/capabilities in place.
|
|
299
|
+
*
|
|
300
|
+
* `'patch'` emits externalId-only outbound SCIM into the IAM tool at the access-mutation
|
|
301
|
+
* chokepoint (needs `url` + workload + an `idMapStore`, which defaults to in-memory). Every push is
|
|
302
|
+
* authenticated with the outgoing workload client, which the destination treats as the verified
|
|
303
|
+
* origin. See the README "IAM delta egress" section.
|
|
304
|
+
*/
|
|
305
|
+
declare function createManagedIamDelta(log: Logger): {
|
|
306
|
+
update(config: IamDeltaConfig, deps: IamDeltaDeps): IamDeltaEmitter;
|
|
307
|
+
};
|
|
308
|
+
import { IamDeltaIdMapKey, IamDeltaIdMapStore as IamDeltaIdMapStore3 } from "@ionite/core";
|
|
309
|
+
/**
|
|
310
|
+
* Stable string key for an {@link IamDeltaIdMapKey}. Scoped by tenant + destination so the same
|
|
311
|
+
* `externalId` can map to different provider ids across IAM tools and tenants. Shared by the
|
|
312
|
+
* in-memory and Redis implementations to keep keying identical.
|
|
313
|
+
*/
|
|
314
|
+
declare function iamDeltaIdMapKey(key: IamDeltaIdMapKey): string;
|
|
315
|
+
/**
|
|
316
|
+
* In-memory {@link IamDeltaIdMapStore}. Suitable for single-process apps and tests. Production
|
|
317
|
+
* deployments should use a durable implementation (e.g. `RedisIamDeltaIdMapStore` or a SQL-backed
|
|
318
|
+
* store) so the externalId -> provider-id cache survives restarts and is shared across instances.
|
|
319
|
+
*/
|
|
320
|
+
declare class InMemoryIamDeltaIdMapStore implements IamDeltaIdMapStore3 {
|
|
321
|
+
private readonly map;
|
|
322
|
+
get(key: IamDeltaIdMapKey): Promise<string | undefined>;
|
|
323
|
+
set(key: IamDeltaIdMapKey, providerId: string): Promise<void>;
|
|
324
|
+
delete(key: IamDeltaIdMapKey): Promise<void>;
|
|
325
|
+
}
|
|
326
|
+
import { CapabilityKey, ModuleName } from "@ionite/core";
|
|
327
|
+
type CapabilityDescriptor = {
|
|
328
|
+
/**
|
|
329
|
+
* Stable machine key (also the catalog map key). This is the SAME key the runtime `capabilitiez`
|
|
330
|
+
* manifest uses ({@link CapabilityKey}); the catalog is generated from that enum (AUDIT_HISTORY.md §11.3) so
|
|
331
|
+
* the two cannot drift and no manual key bridge is required.
|
|
332
|
+
*/
|
|
333
|
+
key: CapabilityKey;
|
|
334
|
+
/** Owning module. */
|
|
335
|
+
module: ModuleName;
|
|
336
|
+
/** Human-readable label for ECI catalog UIs. */
|
|
337
|
+
label: string;
|
|
338
|
+
/** Capability the application must wire for this feature to be `capable` (informational). */
|
|
339
|
+
requires?: string;
|
|
340
|
+
/** Reason surfaced when `requested` but not `capable`. */
|
|
341
|
+
incapableReason?: string;
|
|
342
|
+
};
|
|
343
|
+
declare const ION_CAPABILITY_CATALOG: readonly [{
|
|
344
|
+
readonly key: "sso.login";
|
|
345
|
+
readonly module: "sso";
|
|
346
|
+
readonly label: "SSO login (workforce single sign-on)";
|
|
347
|
+
}, {
|
|
348
|
+
readonly key: "sso.jit";
|
|
349
|
+
readonly module: "sso";
|
|
350
|
+
readonly label: "SSO just-in-time user provisioning";
|
|
351
|
+
}, {
|
|
352
|
+
readonly key: "sso.logout";
|
|
353
|
+
readonly module: "sso";
|
|
354
|
+
readonly label: "SSO logout";
|
|
355
|
+
}, {
|
|
356
|
+
readonly key: "sso.back_channel_logout";
|
|
357
|
+
readonly module: "sso";
|
|
358
|
+
readonly label: "SSO back-channel logout";
|
|
359
|
+
}, {
|
|
360
|
+
readonly key: "ciam.magic_link";
|
|
361
|
+
readonly module: "ciam";
|
|
362
|
+
readonly label: "CIAM magic-link login";
|
|
363
|
+
}, {
|
|
364
|
+
readonly key: "ciam.oidc_login";
|
|
365
|
+
readonly module: "ciam";
|
|
366
|
+
readonly label: "CIAM third-party OIDC login";
|
|
367
|
+
}, {
|
|
368
|
+
readonly key: "ciam.customer";
|
|
369
|
+
readonly module: "ciam";
|
|
370
|
+
readonly label: "CIAM customer profile resolution";
|
|
371
|
+
}, {
|
|
372
|
+
readonly key: "ciam.logout";
|
|
373
|
+
readonly module: "ciam";
|
|
374
|
+
readonly label: "CIAM logout";
|
|
375
|
+
}, {
|
|
376
|
+
readonly key: "iam.users";
|
|
377
|
+
readonly module: "iam";
|
|
378
|
+
readonly label: "SCIM Users inbound";
|
|
379
|
+
readonly requires: "userStore";
|
|
380
|
+
readonly incapableReason: "SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.";
|
|
381
|
+
}, {
|
|
382
|
+
readonly key: "iam.groups";
|
|
383
|
+
readonly module: "iam";
|
|
384
|
+
readonly label: "SCIM Groups inbound";
|
|
385
|
+
readonly requires: "AccessCatalogStore";
|
|
386
|
+
readonly incapableReason: "SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.";
|
|
387
|
+
}, {
|
|
388
|
+
readonly key: "workload.incoming";
|
|
389
|
+
readonly module: "workload";
|
|
390
|
+
readonly label: "Workload incoming token validation";
|
|
391
|
+
}, {
|
|
392
|
+
readonly key: "workload.outgoing";
|
|
393
|
+
readonly module: "workload";
|
|
394
|
+
readonly label: "Workload outgoing token minting";
|
|
395
|
+
}, {
|
|
396
|
+
readonly key: "authz.oaa";
|
|
397
|
+
readonly module: "authz";
|
|
398
|
+
readonly label: "Authz OAA projection (Veza)";
|
|
399
|
+
readonly requires: "AccessAssignmentStore + AccessCatalogStore";
|
|
400
|
+
readonly incapableReason: "OAA projection is configured by RemoteConfig but no access/catalog store capability is wired by the application.";
|
|
401
|
+
}];
|
|
402
|
+
import { BaseCustomer as BaseCustomer2, MagicLink, MagicLinkStore } from "@ionite/core";
|
|
403
|
+
/**
|
|
404
|
+
* In-memory implementation of MagicLinkStore from @ionite/core.
|
|
405
|
+
*/
|
|
406
|
+
declare class InMemoryMagicLinkStore<TExtended = Record<string, never>> implements MagicLinkStore<TExtended> {
|
|
407
|
+
private magicLinks;
|
|
408
|
+
create(token: string, customer: BaseCustomer2, expiresAt: Date): Promise<void>;
|
|
409
|
+
get(token: string): Promise<MagicLink<TExtended> | null>;
|
|
410
|
+
getAndDelete(token: string): Promise<MagicLink<TExtended> | null>;
|
|
411
|
+
delete(token: string): Promise<void>;
|
|
412
|
+
}
|
|
413
|
+
import { Ionite as Ionite2, ResolvedRoute, RoutingOptions } from "@ionite/core";
|
|
414
|
+
/**
|
|
415
|
+
* Deny-by-default authorization gate for a resolved SDK route. Returns the 401/403 `Response` to
|
|
416
|
+
* short-circuit with when the caller is not authorized, or `undefined` to proceed. Enforcement reuses
|
|
417
|
+
* the request-level `hasPermission` helper so a granted entitlement OR a matching OAuth scope (when
|
|
418
|
+
* `RemoteConfig.authz.scopesAsEntitlements` is enabled) satisfies the gate; the `response()` already
|
|
419
|
+
* logs the denial server-side without leaking the missing permission to the caller.
|
|
420
|
+
*/
|
|
421
|
+
declare function enforceEndpointAuthz(request: Request, ion: Ionite2, required: NonNullable<ResolvedRoute["requiredPermission"]>): Promise<Response | undefined>;
|
|
422
|
+
/**
|
|
423
|
+
* Resolve the default route for a request using the deterministic, basePath-derived endpoint paths.
|
|
424
|
+
* Endpoint URLs are no longer read from per-module config; they are computed from `basePath`.
|
|
425
|
+
*/
|
|
426
|
+
declare function resolveDefaultRoute(request: Request, ion: Ionite2, urls: UrlMap, pathname?: string): ResolvedRoute | undefined;
|
|
427
|
+
declare function routeRequest(request: Request, ion: Ionite2, routing?: RoutingOptions, urls?: UrlMap): Promise<Response>;
|
|
428
|
+
import { IamDeltaIdMapStore as IamDeltaIdMapStore4, IamDeltaResourceType, Logger as Logger2 } from "@ionite/core";
|
|
429
|
+
type FetchLike2 = (input: string, init?: RequestInit) => Promise<Response>;
|
|
430
|
+
/**
|
|
431
|
+
* Outcome of an outbound membership patch:
|
|
432
|
+
* - `'pushed'` — the destination accepted the mutation (2xx).
|
|
433
|
+
* - `'skipped'` — the mutation was not attempted (subject/target not resolvable at the destination).
|
|
434
|
+
* - `'error'` — the destination rejected the mutation (non-2xx); the caller surfaces this as a
|
|
435
|
+
* degraded egress / reconcile error so it is never mistaken for success (§4.8/§19.1).
|
|
436
|
+
*/
|
|
437
|
+
type ScimPatchOutcome = "pushed" | "skipped" | "error";
|
|
438
|
+
/**
|
|
439
|
+
* Result of resolving a destination provider id. A lookup/create HTTP failure is `'error'`, NOT
|
|
440
|
+
* `'absent'`: conflating the two would let a transient 401/500 masquerade as "no such resource",
|
|
441
|
+
* which either triggers a spurious create (duplicate resources) or a misleading `'skipped'` outcome.
|
|
442
|
+
* - `{ found }` — a confirmed provider id (from cache, filter match, or create).
|
|
443
|
+
* - `'absent'` — the destination confirmed no resource exists for this `externalId` (2xx, empty).
|
|
444
|
+
* - `'error'` — the lookup/create could not be completed (non-2xx); treat as degraded egress.
|
|
445
|
+
*/
|
|
446
|
+
type ProviderIdResolution = {
|
|
447
|
+
found: string;
|
|
448
|
+
} | "absent" | "error";
|
|
449
|
+
/** Minimal create payload used only when the destination has no resource for an `externalId`. */
|
|
450
|
+
type ScimOutboundCreate = {
|
|
451
|
+
/** SCIM `userName` (required for Users) or unused for Groups. */
|
|
452
|
+
userName?: string;
|
|
453
|
+
/** SCIM `displayName` (required for Groups; optional for Users). */
|
|
454
|
+
displayName?: string;
|
|
455
|
+
};
|
|
456
|
+
type ScimOutboundClientOptions = {
|
|
457
|
+
/** Destination SCIM base URL (e.g. https://iam.example.com/scim/v2). */
|
|
458
|
+
baseUrl: string;
|
|
459
|
+
/** Mints a bearer token for the destination audience (workload outgoing client). */
|
|
460
|
+
getToken: () => Promise<string>;
|
|
461
|
+
/** Durable externalId -> provider-id cache (required). */
|
|
462
|
+
idMapStore: IamDeltaIdMapStore4;
|
|
463
|
+
/** Tenant scope for the mapping cache. */
|
|
464
|
+
tenantId?: string;
|
|
465
|
+
log: Logger2;
|
|
466
|
+
/** Injectable fetch (defaults to global fetch); enables testing against a mock SCIM server. */
|
|
467
|
+
fetchImpl?: FetchLike2;
|
|
468
|
+
};
|
|
469
|
+
/**
|
|
470
|
+
* Escape a value interpolated into a SCIM filter string literal (RFC 7644 §3.4.2.2). Filter string
|
|
471
|
+
* comparison values are JSON strings, so a literal backslash and double-quote must be escaped
|
|
472
|
+
* (backslash first, then quote) — otherwise an id containing `"` would break out of the literal and
|
|
473
|
+
* corrupt the filter (or the remove path), silently matching the wrong resource. IDs are SDK-managed
|
|
474
|
+
* externalIds/provider ids, but this closes the injection/corruption vector regardless of source.
|
|
475
|
+
*/
|
|
476
|
+
declare function escapeScimFilterValue(value: string): string;
|
|
477
|
+
/**
|
|
478
|
+
* externalId-only outbound SCIM client for IAM delta `'patch'` egress.
|
|
479
|
+
*
|
|
480
|
+
* Resolves a destination provider id for a resource STRICTLY by `externalId` (never email,
|
|
481
|
+
* employeeId, samAccountName, or any custom attribute), backed by a durable mapping cache:
|
|
482
|
+
*
|
|
483
|
+
* - cache hit -> use the stored provider id
|
|
484
|
+
* - miss -> `GET /{Resource}?filter=externalId eq "..."` -> store + use the returned id
|
|
485
|
+
* - empty -> `POST /{Resource}` (create) -> store + use the returned id
|
|
486
|
+
* - stale (404/410 on a subsequent write) -> drop the mapping, re-resolve, retry once
|
|
487
|
+
*
|
|
488
|
+
* Concurrent resolutions for the same `(destination, resourceType, externalId)` are single-flighted.
|
|
489
|
+
*/
|
|
490
|
+
declare class ScimOutboundClient {
|
|
491
|
+
private readonly baseUrl;
|
|
492
|
+
private readonly getToken;
|
|
493
|
+
private readonly idMapStore;
|
|
494
|
+
private readonly tenantId?;
|
|
495
|
+
private readonly log;
|
|
496
|
+
private readonly fetchImpl;
|
|
497
|
+
private readonly inflight;
|
|
498
|
+
constructor(options: ScimOutboundClientOptions);
|
|
499
|
+
private headers;
|
|
500
|
+
private inflightKey;
|
|
501
|
+
/**
|
|
502
|
+
* Resolve (or create) the destination provider id for a resource identified by `externalId`.
|
|
503
|
+
* Returns a discriminated {@link ProviderIdResolution}: a confirmed id, `'absent'` (destination has
|
|
504
|
+
* no such resource and no `create` was supplied/succeeded), or `'error'` (lookup/create failed).
|
|
505
|
+
*/
|
|
506
|
+
resolveProviderId(resourceType: IamDeltaResourceType, externalId: string, create?: ScimOutboundCreate): Promise<ProviderIdResolution>;
|
|
507
|
+
private resolveUncached;
|
|
508
|
+
private filterByExternalId;
|
|
509
|
+
private create;
|
|
510
|
+
/** Drop a possibly-stale mapping so the next resolve re-filters the destination. */
|
|
511
|
+
private invalidate;
|
|
512
|
+
/**
|
|
513
|
+
* Add or remove a user (by `userExternalId`) from a group (by `groupExternalId`) at the destination.
|
|
514
|
+
* Resolves both ids by externalId, issues a SCIM PATCH, and self-heals once on a stale group id.
|
|
515
|
+
*/
|
|
516
|
+
patchGroupMembership(args: {
|
|
517
|
+
groupExternalId: string;
|
|
518
|
+
userExternalId: string;
|
|
519
|
+
op: "add" | "remove";
|
|
520
|
+
groupCreate?: ScimOutboundCreate;
|
|
521
|
+
userCreate?: ScimOutboundCreate;
|
|
522
|
+
}): Promise<ScimPatchOutcome>;
|
|
523
|
+
}
|
|
524
|
+
import { SecretsSource as SecretsSource6, VaultLfvSecretsConfig } from "@ionite/core";
|
|
525
|
+
type LfvSecretsSource = SecretsSource6 & {
|
|
526
|
+
isDeliveryRequest(request: Request): boolean;
|
|
527
|
+
isEventsRequest(request: Request): boolean;
|
|
528
|
+
handleDelivery(request: Request): Promise<Response>;
|
|
529
|
+
handleEvents(request: Request): Promise<Response>;
|
|
530
|
+
/** Normalized inbound delivery path this source claims (used to enforce global uniqueness at apply time). */
|
|
531
|
+
readonly deliveryPath: string;
|
|
532
|
+
/** Normalized inbound events path this source claims (used to enforce global uniqueness at apply time). */
|
|
533
|
+
readonly eventsPath: string;
|
|
534
|
+
/** Normalized `serverUrl|path` callback-hub key this source registers under. */
|
|
535
|
+
readonly callbackKey: string;
|
|
536
|
+
/** Stable identity of this source's verify JWKS trust material (undefined when unconfigured). */
|
|
537
|
+
readonly trustId?: string;
|
|
538
|
+
};
|
|
539
|
+
declare function lfvVault(config: VaultLfvSecretsConfig): LfvSecretsSource;
|
|
540
|
+
import { SessionStore } from "@ionite/core";
|
|
541
|
+
/**
|
|
542
|
+
* Options for {@link createSessionReadCache}. Values are the already-clamped internal (ms/count)
|
|
543
|
+
* form produced by the core `resolveSessionCacheConfig` from the portable
|
|
544
|
+
* `RemoteConfig.cache.session.read` block.
|
|
545
|
+
*/
|
|
546
|
+
type SessionReadCacheOptions = {
|
|
547
|
+
/** Max time a cached `get(sid)` result may be served, in ms. */
|
|
548
|
+
ttlMs: number;
|
|
549
|
+
/** Max distinct session ids held at once (bounded LRU). */
|
|
550
|
+
maxEntries: number;
|
|
551
|
+
};
|
|
552
|
+
/**
|
|
553
|
+
* Instance-local read-through cache decorator for a {@link SessionStore}. DEFAULT-OFF: only wired
|
|
554
|
+
* when `RemoteConfig.cache.session.read.enabled === true`. It is the "monolith knob" — it trades a
|
|
555
|
+
* bounded amount of cross-instance staleness (a logout/refresh on another node is visible after at
|
|
556
|
+
* most `ttlMs`) for eliminating repeated `get(sid)` round-trips to a Redis/DB session store on
|
|
557
|
+
* hot paths.
|
|
558
|
+
*
|
|
559
|
+
* Semantics (portable contract):
|
|
560
|
+
* - `get(sid)` is served from a bounded LRU for up to `ttlMs`; on miss it reads through and caches.
|
|
561
|
+
* - **Misses are NOT cached** (a null result never populates the cache), which avoids a login race
|
|
562
|
+
* (a session created moments later would otherwise be masked) and an unauthenticated-flood memory
|
|
563
|
+
* vector (only valid sids ever become keys).
|
|
564
|
+
* - `update`/`delete` write through to the underlying store AND invalidate the local entry, so a
|
|
565
|
+
* same-process logout/refresh is immediately visible.
|
|
566
|
+
* - `create` writes through; it does not pre-populate the cache (kept lazy; the first `get` caches).
|
|
567
|
+
* - Lazy TTL expiry only (no timers/sweepers — safe in serverless): an expired entry is dropped on
|
|
568
|
+
* the next access.
|
|
569
|
+
*
|
|
570
|
+
* A fresh instance is created on every RemoteConfig apply (the caller drops the previous one) so a
|
|
571
|
+
* live re-tune never leaks the old cache.
|
|
572
|
+
*/
|
|
573
|
+
declare function createSessionReadCache<TExtended = Record<string, never>>(store: SessionStore<TExtended>, options: SessionReadCacheOptions): SessionStore<TExtended>;
|
|
574
|
+
import { Session, SessionStore as SessionStore2 } from "@ionite/core";
|
|
575
|
+
/**
|
|
576
|
+
* In-memory session store implementation using Maps.
|
|
577
|
+
*
|
|
578
|
+
* Lazily purges records whose `expiresAt` has passed on `get`, mirroring the physical expiry a
|
|
579
|
+
* TTL-backed store (Redis `EX`) gives for free (AUDIT_HISTORY.md §1.3). There is no background sweep, so an
|
|
580
|
+
* abandoned session lingers in the Map until it is next looked up; for unbounded-lifetime deployments
|
|
581
|
+
* prefer a TTL-backed store.
|
|
582
|
+
*/
|
|
583
|
+
declare class InMemorySessionStore<TExtended = Record<string, never>> implements SessionStore2<TExtended> {
|
|
584
|
+
private sessions;
|
|
585
|
+
create(session: Session<TExtended>): Promise<void>;
|
|
586
|
+
get(sid: string): Promise<Session<TExtended> | null>;
|
|
587
|
+
update(sid: string, data: Partial<Session<TExtended>>): Promise<void>;
|
|
588
|
+
delete(sid: string): Promise<void>;
|
|
589
|
+
}
|
|
590
|
+
import { ConfigSource as ConfigSource8, ConfigSourceResolver as ConfigSourceResolver2, TenantConfigLocator as TenantConfigLocator2 } from "@ionite/core";
|
|
591
|
+
import { ConfigLocator as ConfigLocator2, ConfigSource as ConfigSource7 } from "@ionite/core";
|
|
592
|
+
/**
|
|
593
|
+
* Materialize a runtime {@link ConfigSource} from a full, self-contained {@link ConfigLocator}. This
|
|
594
|
+
* is the ROOT/bootstrap path (env vars via `envConfig()`, or a bootstrap secret via
|
|
595
|
+
* `secretConfigSource()`): the locator carries the connection details/credentials needed to build a
|
|
596
|
+
* fresh source. Tenants do NOT use this path — see {@link tenantConfigSourceFromResolver}.
|
|
597
|
+
*/
|
|
598
|
+
declare function configSourceFromLocator(locator: ConfigLocator2): ConfigSource7;
|
|
599
|
+
/**
|
|
600
|
+
* Context threaded into tenant config-source validation so a locator can be checked against the tenant
|
|
601
|
+
* that owns it. INVARIANT: each tenant MUST resolve to a DISTINCT backing config path (e.g. a unique
|
|
602
|
+
* vault path). Two tenants sharing a config path would cross-load each other's RemoteConfig.
|
|
603
|
+
*/
|
|
604
|
+
type ConfigLocatorContext = {
|
|
605
|
+
tenantId?: string;
|
|
606
|
+
};
|
|
607
|
+
/**
|
|
608
|
+
* Optional validation hook invoked before a tenant's locator is materialized. Implementations should
|
|
609
|
+
* throw when a locator is not valid (e.g. a shared/duplicate config path). The shared source client
|
|
610
|
+
* may still be reused across tenants; only the resolved path must differ per tenant.
|
|
611
|
+
*/
|
|
612
|
+
type ConfigLocatorAssert = (input: {
|
|
613
|
+
locator: TenantConfigLocator2;
|
|
614
|
+
}) => void;
|
|
615
|
+
declare function registerConfigLocatorAssert(assert: ConfigLocatorAssert | undefined): void;
|
|
616
|
+
/**
|
|
617
|
+
* Materialize a tenant's {@link ConfigSource} from its {@link TenantConfigLocator}, resolving against
|
|
618
|
+
* the root ES (`ion.secret` / `ion.secrets`). Pass the root `es` (or any {@link ConfigSourceResolver}).
|
|
619
|
+
*
|
|
620
|
+
* This lives in `@ionite/server` (not core) so the materialization can reference the
|
|
621
|
+
* server-only source implementations directly, with no import-time registration side effect — keeping
|
|
622
|
+
* every published package truthfully `sideEffects: false`.
|
|
623
|
+
*/
|
|
624
|
+
declare function tenantConfigSource(locator: TenantConfigLocator2, ion: ConfigSourceResolver2): ConfigSource8;
|
|
625
|
+
import { Ionite as Ionite3, TenantPathNamespace, TenantRoutingStrategy } from "@ionite/core";
|
|
626
|
+
type MaybePromise<T> = Promise<T> | T;
|
|
627
|
+
type TenantResolutionContext = {
|
|
628
|
+
namespace: "api" | "ui";
|
|
629
|
+
restPath: string;
|
|
630
|
+
restSegments: string[];
|
|
631
|
+
};
|
|
632
|
+
type ResolveTenantFromRequestOptions = {
|
|
633
|
+
strategy?: TenantRoutingStrategy;
|
|
634
|
+
namespace?: "api" | "ui";
|
|
635
|
+
/**
|
|
636
|
+
* App-owned resolver for tenants that are not encoded in the URL path. The SDK does not infer a
|
|
637
|
+
* tenant from unverified input (JWT/header/host/cookie); if you need that, implement it here and
|
|
638
|
+
* verify it yourself before returning an id.
|
|
639
|
+
*/
|
|
640
|
+
custom?: (request: Request) => MaybePromise<string | null | undefined>;
|
|
641
|
+
};
|
|
642
|
+
type CreateTenantIonResolverOptions = {
|
|
643
|
+
store: {
|
|
644
|
+
getIon(id: string): Promise<Ionite3 | undefined>;
|
|
645
|
+
};
|
|
646
|
+
getIon?: never;
|
|
647
|
+
} | {
|
|
648
|
+
store?: never;
|
|
649
|
+
getIon: (id: string) => Promise<Ionite3 | null | undefined>;
|
|
650
|
+
};
|
|
651
|
+
type TenantIonResolver = (id: string) => Promise<Ionite3 | undefined>;
|
|
652
|
+
type CreateTenantIonHandlerOptions = {
|
|
653
|
+
getIon: (id: string, request: Request) => MaybePromise<Ionite3 | null | undefined>;
|
|
654
|
+
resolveTenant?: (request: Request) => MaybePromise<{
|
|
655
|
+
id: string;
|
|
656
|
+
context?: TenantResolutionContext;
|
|
657
|
+
} | string | null | undefined>;
|
|
658
|
+
rewriteRequest?: (request: Request, details: {
|
|
659
|
+
id: string;
|
|
660
|
+
ion: Ionite3;
|
|
661
|
+
context?: TenantResolutionContext;
|
|
662
|
+
}) => MaybePromise<Request>;
|
|
663
|
+
onMissingTenant?: (request: Request) => MaybePromise<Response>;
|
|
664
|
+
onMissingIonite?: (request: Request, id: string) => MaybePromise<Response>;
|
|
665
|
+
};
|
|
666
|
+
declare function createTenantIonResolver(options: CreateTenantIonResolverOptions): TenantIonResolver;
|
|
667
|
+
declare function resolveTenantFromRequest(request: Request, options?: ResolveTenantFromRequestOptions): Promise<{
|
|
668
|
+
id: string;
|
|
669
|
+
context?: TenantResolutionContext;
|
|
670
|
+
} | null>;
|
|
671
|
+
declare function rewriteRequestPath(request: Request, pathname: string): Request;
|
|
672
|
+
declare function rewriteRequestForTenantPath(request: Request, id: string, sourceNamespace: TenantPathNamespace, targetNamespace: TenantPathNamespace): Request;
|
|
673
|
+
declare function rewriteRequestForDefaultTenantApi(request: Request, id: string, targetNamespace?: TenantPathNamespace): Request;
|
|
674
|
+
declare function rewriteRequestForDefaultTenantUi(request: Request, id: string, targetNamespace?: TenantPathNamespace): Request;
|
|
675
|
+
declare function createTenantIonHandler(options: CreateTenantIonHandlerOptions): (request: Request) => Promise<Response>;
|
|
676
|
+
import { BaseUser as BaseUser2, ListOptions as ListOptions4, ListResult as ListResult4, UserStore as UserStore2 } from "@ionite/core";
|
|
677
|
+
/**
|
|
678
|
+
* In-memory user store implementation using Maps.
|
|
679
|
+
*/
|
|
680
|
+
declare class InMemoryUserStore<TExtended = Record<string, never>> implements UserStore2<TExtended> {
|
|
681
|
+
private users;
|
|
682
|
+
private userNameIndex;
|
|
683
|
+
get(id: string): Promise<BaseUser2<TExtended> | undefined>;
|
|
684
|
+
lookup(user: BaseUser2<TExtended>): Promise<BaseUser2<TExtended> | undefined>;
|
|
685
|
+
upsert(user: BaseUser2<TExtended>): Promise<BaseUser2<TExtended>>;
|
|
686
|
+
delete(sub: string): Promise<number>;
|
|
687
|
+
list(options?: ListOptions4): Promise<ListResult4<BaseUser2<TExtended>>>;
|
|
688
|
+
}
|
|
689
|
+
import { SecretsSource as SecretsSource8, VaultSecretsConfig as VaultSecretsConfig3 } from "@ionite/core";
|
|
690
|
+
import { Secret, SecretsSource as SecretsSource7, SecretsSubscriptionOptions, VaultSecretsConfig as VaultSecretsConfig2 } from "@ionite/core";
|
|
691
|
+
declare class VaultSubscribeNotSupportedError extends Error {
|
|
692
|
+
readonly sourceType: string;
|
|
693
|
+
readonly path: string;
|
|
694
|
+
constructor(sourceType: string, path: string, message?: string);
|
|
695
|
+
}
|
|
696
|
+
declare const VAULT_MIN_POLLING_TTL_MS = 6e5;
|
|
697
|
+
/** Optional health hooks so a polling source can flip its degraded `isAvailable()` state. */
|
|
698
|
+
type HttpPollingHooks = {
|
|
699
|
+
/** Invoked after every poll attempt (initial read + each tick) with the observed health. */
|
|
700
|
+
onHealth?: (healthy: boolean) => void;
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* Subscribe to a secret path via HTTP polling using a self-scheduling `setTimeout` chain. The next
|
|
704
|
+
* poll is scheduled only after the current one settles, so polls can never overlap or pile up during
|
|
705
|
+
* a slow/failing upstream (no `setInterval` storm). The returned unsubscribe sets a `closed` flag and
|
|
706
|
+
* cancels any pending timer/sleep, so teardown halts all activity immediately even mid-outage.
|
|
707
|
+
*/
|
|
708
|
+
declare function subscribeSecretPathWithHttpPolling<T>(source: Pick<SecretsSource7, "getFullSecret">, path: string, onChange: (fullSecret: Secret<T>) => void, ttl: number, log?: VaultSecretsConfig2["log"], options?: SecretsSubscriptionOptions, hooks?: HttpPollingHooks): Promise<() => void>;
|
|
709
|
+
/**
|
|
710
|
+
* Override the per-command websocket timeout (ms). Primarily a diagnostic/test knob; production code
|
|
711
|
+
* should leave the 30s default in place.
|
|
712
|
+
*/
|
|
713
|
+
declare function setVaultWebSocketCommandTimeout(ms: number): void;
|
|
714
|
+
/** Test/diagnostic helper: number of live sockets and total registered subscriptions. */
|
|
715
|
+
declare function vaultSocketDiagnostics(): {
|
|
716
|
+
urls: string[];
|
|
717
|
+
sockets: number;
|
|
718
|
+
subscriptions: number;
|
|
719
|
+
};
|
|
720
|
+
/** Test helper: force-close every vault socket in the process. */
|
|
721
|
+
declare function closeAllVaultSockets(): void;
|
|
722
|
+
type OpenbaoVaultOptions = Omit<VaultSecretsConfig3, "type"> & {
|
|
723
|
+
type?: "openbao" | "vault";
|
|
724
|
+
};
|
|
725
|
+
/**
|
|
726
|
+
* Compatibility helper for OpenBao/Hashicorp-compatible vault endpoints.
|
|
727
|
+
* Internally uses the standard vault secrets source implementation.
|
|
728
|
+
*/
|
|
729
|
+
declare function openbaoVault(options: OpenbaoVaultOptions): SecretsSource8;
|
|
730
|
+
import { Workload as CoreWorkload, FrameworkWorkloadConfig, Ionite as Ionite4, JWTAssertionClaims, Logger as Logger4, TokenValidationResult, TrustedIdp, WorkloadConfigMap, WorkloadGetToken, WorkloadIdentityStore as WorkloadIdentityStore2, WorkloadIncomingOutgoing, WorkloadTokenResponse, WorkloadTokenStore } from "@ionite/core";
|
|
731
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
732
|
+
/**
|
|
733
|
+
* Common fields shared across all workload authentication modes
|
|
734
|
+
*/
|
|
735
|
+
type WorkloadConfigBase = {
|
|
736
|
+
/**
|
|
737
|
+
* App workload token endpoint path (e.g. /api/ionite/tenant/workload/token).
|
|
738
|
+
* Used for routing; set in code.
|
|
739
|
+
*/
|
|
740
|
+
tokenUrl?: string;
|
|
741
|
+
/**
|
|
742
|
+
* IdP OAuth2 token endpoint URL (e.g. https://sso.example.com/.../token).
|
|
743
|
+
* REQUIRED for client role (token acquisition); typically set in vault.
|
|
744
|
+
*/
|
|
745
|
+
idpTokenUrl?: string;
|
|
746
|
+
/**
|
|
747
|
+
* JWKS endpoint URL for public key retrieval
|
|
748
|
+
* REQUIRED for server role (token validation)
|
|
749
|
+
*/
|
|
750
|
+
jwksUri?: string;
|
|
751
|
+
/**
|
|
752
|
+
* Expected token issuer URL for validation
|
|
753
|
+
* RECOMMENDED for server role (token validation)
|
|
754
|
+
*/
|
|
755
|
+
issuer?: string;
|
|
756
|
+
/**
|
|
757
|
+
* Target audience for tokens
|
|
758
|
+
*/
|
|
759
|
+
audience?: string;
|
|
760
|
+
/**
|
|
761
|
+
* Per-IdP scopesAsEntitlements intent (incoming/server role only). See core `WorkloadConfigBase`.
|
|
762
|
+
*/
|
|
763
|
+
scopesAsEntitlements?: boolean;
|
|
764
|
+
/**
|
|
765
|
+
* Default OAuth2 scopes (space-delimited)
|
|
766
|
+
*/
|
|
767
|
+
scope?: string;
|
|
768
|
+
/**
|
|
769
|
+
* JWT assertion/token lifetime in seconds
|
|
770
|
+
* @default 300 (5 minutes)
|
|
771
|
+
*/
|
|
772
|
+
tokenLifetime?: number;
|
|
773
|
+
/**
|
|
774
|
+
* Refresh threshold in seconds (refresh token this many seconds before expiry)
|
|
775
|
+
* @default 60
|
|
776
|
+
*/
|
|
777
|
+
refreshThreshold?: number;
|
|
778
|
+
/**
|
|
779
|
+
* Optional token store for caching access tokens
|
|
780
|
+
*/
|
|
781
|
+
tokenStore?: WorkloadTokenStore;
|
|
782
|
+
/**
|
|
783
|
+
* Optional registry/enrichment store for workload principals. When set, `getWorkloadIdentity`
|
|
784
|
+
* merges stored attributes (e.g. `displayName`, `active`, default `scopes`) onto the validated
|
|
785
|
+
* token identity. Authorization works without it; see {@link WorkloadIdentityStore}.
|
|
786
|
+
*/
|
|
787
|
+
workloadIdentityStore?: WorkloadIdentityStore2;
|
|
788
|
+
/**
|
|
789
|
+
* Automatically refresh tokens before expiration
|
|
790
|
+
* @default true
|
|
791
|
+
*/
|
|
792
|
+
autoRefresh?: boolean;
|
|
793
|
+
/**
|
|
794
|
+
* Optional RFC 7009 token revocation endpoint
|
|
795
|
+
*/
|
|
796
|
+
revocationEndpoint?: string;
|
|
797
|
+
/**
|
|
798
|
+
* Optional handler defaults (merged with per-call overrides in `handler`)
|
|
799
|
+
*/
|
|
800
|
+
validateUrl?: string;
|
|
801
|
+
jwksUrl?: string;
|
|
802
|
+
refreshUrl?: string;
|
|
803
|
+
validators?: WorkloadValidators;
|
|
804
|
+
};
|
|
805
|
+
type WorkloadValidators = {
|
|
806
|
+
jwtAssertionClaims: StandardSchemaV1<unknown, JWTAssertionClaims>;
|
|
807
|
+
tokenResponse: StandardSchemaV1<unknown, WorkloadTokenResponse>;
|
|
808
|
+
};
|
|
809
|
+
/**
|
|
810
|
+
* JWT Bearer Grant (RFC 7523) Configuration
|
|
811
|
+
*
|
|
812
|
+
* Used for SPIFFE-style workload identities where services have their own
|
|
813
|
+
* cryptographic identity and sign their own JWT assertions.
|
|
814
|
+
*
|
|
815
|
+
* @example
|
|
816
|
+
* ```json
|
|
817
|
+
* {
|
|
818
|
+
* "token_url": "https://auth.example.com/oauth/token",
|
|
819
|
+
* "jwks_uri": "https://auth.example.com/.well-known/jwks.json",
|
|
820
|
+
* "workload_id": "spiffe://trust-domain/ns/service",
|
|
821
|
+
* "audience": "https://auth.example.com/oauth/token",
|
|
822
|
+
* "private_key": "-----BEGIN PRIVATE KEY-----...",
|
|
823
|
+
* "algorithm": "RS256"
|
|
824
|
+
* }
|
|
825
|
+
* ```
|
|
826
|
+
*/
|
|
827
|
+
type JwtBearerWorkloadConfig = WorkloadConfigBase & {
|
|
828
|
+
/**
|
|
829
|
+
* Workload identifier (e.g., SPIFFE ID: spiffe://trust-domain/namespace/service)
|
|
830
|
+
* REQUIRED for JWT Bearer Grant mode
|
|
831
|
+
*/
|
|
832
|
+
workloadId: string;
|
|
833
|
+
/**
|
|
834
|
+
* PEM-encoded private key for signing JWT assertions
|
|
835
|
+
* REQUIRED for client role in JWT Bearer Grant mode
|
|
836
|
+
*/
|
|
837
|
+
privateKey: string;
|
|
838
|
+
/**
|
|
839
|
+
* Key ID (kid) to include in JWT header for key rotation support
|
|
840
|
+
*/
|
|
841
|
+
keyId?: string;
|
|
842
|
+
/**
|
|
843
|
+
* JWT signing algorithm
|
|
844
|
+
* @default 'RS256'
|
|
845
|
+
*/
|
|
846
|
+
algorithm?: "RS256" | "RS384" | "RS512" | "ES256" | "ES384" | "ES512";
|
|
847
|
+
};
|
|
848
|
+
/**
|
|
849
|
+
* OAuth2 Client Credentials Configuration
|
|
850
|
+
*
|
|
851
|
+
* Standard OAuth2 Client Credentials Grant (RFC 6749 Section 4.4).
|
|
852
|
+
* Used with identity providers like Keycloak for service-to-service authentication.
|
|
853
|
+
*
|
|
854
|
+
* @example
|
|
855
|
+
* ```json
|
|
856
|
+
* {
|
|
857
|
+
* "token_url": "https://sso.example.com/realms/myrealm/protocol/openid-connect/token",
|
|
858
|
+
* "jwks_uri": "https://sso.example.com/realms/myrealm/protocol/openid-connect/certs",
|
|
859
|
+
* "client_id": "my-service",
|
|
860
|
+
* "client_secret": "secret-from-idp",
|
|
861
|
+
* "issuer": "https://sso.example.com/realms/myrealm",
|
|
862
|
+
* "scope": "api:read api:write"
|
|
863
|
+
* }
|
|
864
|
+
* ```
|
|
865
|
+
*/
|
|
866
|
+
type ClientCredentialsWorkloadConfig = WorkloadConfigBase & {
|
|
867
|
+
/**
|
|
868
|
+
* OAuth2 client identifier registered with the authorization server
|
|
869
|
+
* REQUIRED for Client Credentials mode
|
|
870
|
+
*/
|
|
871
|
+
clientId: string;
|
|
872
|
+
/**
|
|
873
|
+
* OAuth2 client secret
|
|
874
|
+
* REQUIRED for Client Credentials mode
|
|
875
|
+
*/
|
|
876
|
+
clientSecret: string;
|
|
877
|
+
};
|
|
878
|
+
/**
|
|
879
|
+
* Server-Only Workload Configuration
|
|
880
|
+
*
|
|
881
|
+
* Used when a service only needs to validate incoming workload tokens,
|
|
882
|
+
* not acquire tokens for outbound calls. Requires only jwks_uri for
|
|
883
|
+
* public key retrieval.
|
|
884
|
+
*
|
|
885
|
+
* Note: jwksUri and issuer are optional in TypeScript (since they come from vault)
|
|
886
|
+
* but are required at runtime and validated by standardSchema validators.
|
|
887
|
+
*
|
|
888
|
+
* @example
|
|
889
|
+
* ```json
|
|
890
|
+
* {
|
|
891
|
+
* "jwks_uri": "https://sso.example.com/realms/myrealm/protocol/openid-connect/certs",
|
|
892
|
+
* "issuer": "https://sso.example.com/realms/myrealm"
|
|
893
|
+
* }
|
|
894
|
+
* ```
|
|
895
|
+
*/
|
|
896
|
+
type ServerOnlyWorkloadConfig = WorkloadConfigBase & {
|
|
897
|
+
/**
|
|
898
|
+
* JWKS endpoint URL for public key retrieval
|
|
899
|
+
* REQUIRED at runtime (validated by standardSchema), optional in TypeScript (comes from vault)
|
|
900
|
+
*/
|
|
901
|
+
jwksUri?: string;
|
|
902
|
+
};
|
|
903
|
+
/**
|
|
904
|
+
* Workload Identity Authentication Configuration
|
|
905
|
+
*
|
|
906
|
+
* Union type supporting multiple authentication modes. The mode is automatically
|
|
907
|
+
* detected based on which fields are present:
|
|
908
|
+
*
|
|
909
|
+
* - **JWT Bearer Grant**: Requires `workload_id` + `private_key`
|
|
910
|
+
* - **Client Credentials**: Requires `client_id` + `client_secret`
|
|
911
|
+
* - **Server-Only**: Only `jwks_uri` (and optionally `issuer`) for token validation
|
|
912
|
+
*
|
|
913
|
+
* The developer uses the same API regardless of mode - the library handles the details.
|
|
914
|
+
*/
|
|
915
|
+
type WorkloadConfig = JwtBearerWorkloadConfig | ClientCredentialsWorkloadConfig | ServerOnlyWorkloadConfig;
|
|
916
|
+
/**
|
|
917
|
+
* Workload Identity extracted from validated tokens
|
|
918
|
+
*/
|
|
919
|
+
type WorkloadIdentity = {
|
|
920
|
+
/**
|
|
921
|
+
* Workload identifier (for JWT Bearer Grant tokens)
|
|
922
|
+
*/
|
|
923
|
+
workloadId?: string;
|
|
924
|
+
/**
|
|
925
|
+
* Client identifier (for OAuth2 Client Credentials tokens)
|
|
926
|
+
*/
|
|
927
|
+
clientId?: string;
|
|
928
|
+
/**
|
|
929
|
+
* Granted scopes
|
|
930
|
+
*/
|
|
931
|
+
scope?: string;
|
|
932
|
+
/**
|
|
933
|
+
* Whether the trusted IdP that validated this token opts into honoring its OAuth `scope` claim as
|
|
934
|
+
* entitlements (per-IdP intent, resolved at validation time).
|
|
935
|
+
*/
|
|
936
|
+
scopesAsEntitlements?: boolean;
|
|
937
|
+
/**
|
|
938
|
+
* Enterprise Controlled ID for this workload (`ecid:<realm>:<opaque>`), when carried on the token
|
|
939
|
+
* `ecid` claim or enriched from a wired `WorkloadIdentityStore`. A workload is its own governance
|
|
940
|
+
* root. See https://ionite.com/docs/llms-ecid.txt.
|
|
941
|
+
*/
|
|
942
|
+
ecid?: string;
|
|
943
|
+
/**
|
|
944
|
+
* Full JWT claims from the token
|
|
945
|
+
*/
|
|
946
|
+
claims: JWTAssertionClaims;
|
|
947
|
+
};
|
|
948
|
+
/**
|
|
949
|
+
* Workload Identity Authentication Interface
|
|
950
|
+
*/
|
|
951
|
+
type Workload3 = {
|
|
952
|
+
config: WorkloadConfig;
|
|
953
|
+
beforeChange?: (listener: () => void) => () => void;
|
|
954
|
+
afterChange?: (listener: () => void) => () => void;
|
|
955
|
+
isReady?: () => boolean;
|
|
956
|
+
ready?: (timeout?: number) => Promise<void>;
|
|
957
|
+
getToken: WorkloadGetToken;
|
|
958
|
+
refreshToken: (scope?: string) => Promise<WorkloadTokenResponse>;
|
|
959
|
+
generateJWTAssertion: (scope?: string) => Promise<string>;
|
|
960
|
+
revokeToken: (token: string) => Promise<void>;
|
|
961
|
+
validateToken: (token: string) => Promise<TokenValidationResult>;
|
|
962
|
+
getWorkloadIdentity: (request: Request) => Promise<WorkloadIdentity | undefined>;
|
|
963
|
+
parseJWT: (token: string) => Promise<JWTAssertionClaims>;
|
|
964
|
+
handler: (request: Request) => Promise<Response>;
|
|
965
|
+
};
|
|
966
|
+
declare function workload(validators: WorkloadValidators, log: Logger4, fromVault?: Partial<WorkloadConfig> | WorkloadConfigMap | WorkloadIncomingOutgoing, fromCode?: FrameworkWorkloadConfig, incomingTrustOverride?: TrustedIdp[]): Workload3 | undefined;
|
|
967
|
+
/**
|
|
968
|
+
* Get the workload identity from an incoming request.
|
|
969
|
+
*/
|
|
970
|
+
declare function getWorkload(request: Request, ion: Ionite4): Promise<WorkloadIdentity | undefined>;
|
|
971
|
+
/**
|
|
972
|
+
* Get an access token for the configured workload identity.
|
|
973
|
+
* Client is required and must be one of the configured outgoing workload clients.
|
|
974
|
+
* Throws when no outgoing clients are configured on this Ionite instance.
|
|
975
|
+
* Scope defaults to the config for the chosen client (e.g. workload.outgoing.<name>.scope); pass scope to override.
|
|
976
|
+
*/
|
|
977
|
+
declare function getWorkloadToken(client: string, ion: Ionite4, scope?: string): Promise<string>;
|
|
978
|
+
/**
|
|
979
|
+
* Validate a workload token from an incoming request.
|
|
980
|
+
* Accepts either an Ionite instance (uses its workload) or a Workload instance directly
|
|
981
|
+
* (e.g. a server-only Workload used for tenant creation auth).
|
|
982
|
+
*/
|
|
983
|
+
declare function validateWorkloadToken(request: Request, ionOrWorkload: Ionite4 | CoreWorkload): Promise<TokenValidationResult>;
|
|
984
|
+
/**
|
|
985
|
+
* Revoke a workload access token.
|
|
986
|
+
*/
|
|
987
|
+
declare function revokeWorkloadToken(token: string, ion: Ionite4): Promise<void>;
|
|
988
|
+
/**
|
|
989
|
+
* Framework-agnostic request handler for the Workload module (token, validate, jwks, refresh routes).
|
|
990
|
+
*/
|
|
991
|
+
declare function workloadHandler(request: Request, ion: Ionite4): Promise<Response>;
|
|
992
|
+
import { BaseWorkloadIdentity, ListOptions as ListOptions5, ListResult as ListResult5, WorkloadIdentityStore as WorkloadIdentityStore3 } from "@ionite/core";
|
|
993
|
+
/**
|
|
994
|
+
* In-memory {@link WorkloadIdentityStore} implementation using Maps. Suitable for development and
|
|
995
|
+
* testing; use a durable store (e.g. Redis/SQL) in production.
|
|
996
|
+
*/
|
|
997
|
+
declare class InMemoryWorkloadIdentityStore<TExtended = Record<string, never>> implements WorkloadIdentityStore3<TExtended> {
|
|
998
|
+
private identities;
|
|
999
|
+
private clientIdIndex;
|
|
1000
|
+
get(id: string): Promise<BaseWorkloadIdentity<TExtended> | undefined>;
|
|
1001
|
+
lookup(identity: BaseWorkloadIdentity<TExtended>): Promise<BaseWorkloadIdentity<TExtended> | undefined>;
|
|
1002
|
+
upsert(identity: BaseWorkloadIdentity<TExtended>): Promise<BaseWorkloadIdentity<TExtended>>;
|
|
1003
|
+
delete(id: string): Promise<number>;
|
|
1004
|
+
list(options?: ListOptions5): Promise<ListResult5<BaseWorkloadIdentity<TExtended>>>;
|
|
1005
|
+
}
|
|
1006
|
+
import { CachedWorkloadToken, WorkloadTokenStore as WorkloadTokenStore2 } from "@ionite/core";
|
|
1007
|
+
/**
|
|
1008
|
+
* In-memory workload token store implementation using Maps.
|
|
1009
|
+
*/
|
|
1010
|
+
declare class InMemoryWorkloadTokenStore<TExtended = object> implements WorkloadTokenStore2<TExtended> {
|
|
1011
|
+
private tokens;
|
|
1012
|
+
set(token: CachedWorkloadToken<TExtended>): Promise<void>;
|
|
1013
|
+
get(workload_id: string): Promise<CachedWorkloadToken<TExtended> | null>;
|
|
1014
|
+
delete(workload_id: string): Promise<void>;
|
|
1015
|
+
isValid(workload_id: string): Promise<boolean>;
|
|
1016
|
+
cleanup(): Promise<void>;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Config object for ionite(source, config). Includes FrameworkConfig plus
|
|
1020
|
+
* server-only builder hints and lifecycle/routing (stripped before passing to module constructors).
|
|
1021
|
+
*/
|
|
1022
|
+
type IoniteConfig<C extends FrameworkConfigInput = FrameworkConfigInput> = C & {
|
|
1023
|
+
basePath?: string;
|
|
1024
|
+
stores?: FrameworkStores2;
|
|
1025
|
+
beforeChange?: ConfigChangeCallback;
|
|
1026
|
+
afterChange?: (ion: Ionite5, config: RemoteConfig2, frameworkConfig: ModifiableFrameworkConfig, oldConfig: RemoteConfig2 | undefined) => void;
|
|
1027
|
+
routing?: RoutingOptions2;
|
|
1028
|
+
configRetry?: RemoteConfigRetryOptions;
|
|
1029
|
+
onConfigLoadError?: RemoteConfigRetryHook;
|
|
1030
|
+
};
|
|
1031
|
+
declare function ionite<const C extends FrameworkConfigInput = FrameworkConfigInput>(source: ConfigSource9, config: IoniteConfig<C> | FrameworkConfigInput): Ionite5;
|
|
1032
|
+
export { workloadHandler, workload, withSetCookies, withDefaultExternalId, verifyUser, vaultSocketDiagnostics, vaultConfig, validateWorkloadToken, tenantManager, tenantConfigSource, subscribeSecretPathWithHttpPolling, sso, setVaultWebSocketCommandTimeout, sendTenantWebhook, secretConfigSource, sameOriginRedirectRules, routeRequest, rewriteRequestPath, rewriteRequestForTenantPath, rewriteRequestForDefaultTenantUi, rewriteRequestForDefaultTenantApi, revokeWorkloadToken, resolveTenantFromRequest, resolveRedirect, resolveDefaultRoute, resolveCapturedRedirect, resolveAfterRedirect, registerConfigLocatorAssert, reconcileSubjectAccess, openbaoVault, 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, ScimOutboundCreate, ScimOutboundClientOptions, ScimOutboundClient, ResolveTenantFromRequestOptions, ReferencedDefinitions, RedirectVerdict, RedirectRuleContext, RedirectRule, RedirectResult, RedirectPolicy, RedirectContext, ReconcileStores, OtelSignalConfig, OtelProviderType, OtelOAuthClientCredentialsConfig, OtelMetricsSignalConfig, OtelLogRecord, OtelLogLevel, OtelLevels, OtelConfig, Otel, OpenbaoVaultOptions, LfvSecretsSource, IoniteErrorOptions, IoniteError, IoniteConfig, InMemoryWorkloadTokenStore, InMemoryWorkloadIdentityStore, InMemoryUserStore, InMemoryTenantStore, InMemorySessionStore, InMemoryResourceStore, InMemoryMagicLinkStore, InMemoryIamDeltaIdMapStore, InMemoryCustomerStore, InMemoryAccessIndex, InMemoryAccessCatalogStore, InMemoryAccessAssignmentStore, IamDeltaDeps, IamDeltaConfig, 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 };
|